mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 03:43:11 +00:00
Add starter unit tests for validators, DTO mappers, and PagedResult (#9)
This commit is contained in:
parent
1f3972ae49
commit
b2aeb35a55
5 changed files with 241 additions and 0 deletions
34
SeaHaven.Services.Tests/PagedResultTests.cs
Normal file
34
SeaHaven.Services.Tests/PagedResultTests.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using FluentAssertions;
|
||||
using SeaHaven.Services.DTOs;
|
||||
using Xunit;
|
||||
|
||||
namespace SeaHaven.Services.Tests;
|
||||
|
||||
public class PagedResultTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, 10, 0)]
|
||||
[InlineData(10, 10, 1)]
|
||||
[InlineData(25, 10, 3)]
|
||||
[InlineData(100, 25, 4)]
|
||||
public void TotalPages_IsCeilingOfCountOverPageSize(int totalCount, int pageSize, int expectedPages)
|
||||
{
|
||||
var result = new PagedResult<string> { TotalCount = totalCount, PageSize = pageSize, Page = 1 };
|
||||
|
||||
result.TotalPages.Should().Be(expectedPages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasPrevious_IsFalseOnFirstPage_TrueAfterward()
|
||||
{
|
||||
new PagedResult<string> { Page = 1, PageSize = 10, TotalCount = 30 }.HasPrevious.Should().BeFalse();
|
||||
new PagedResult<string> { Page = 2, PageSize = 10, TotalCount = 30 }.HasPrevious.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasNext_IsTrueBeforeLastPage_FalseOnLastPage()
|
||||
{
|
||||
new PagedResult<string> { Page = 2, PageSize = 10, TotalCount = 30 }.HasNext.Should().BeTrue();
|
||||
new PagedResult<string> { Page = 3, PageSize = 10, TotalCount = 30 }.HasNext.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
23
SeaHaven.Services.Tests/SeaHaven.Services.Tests.csproj
Normal file
23
SeaHaven.Services.Tests/SeaHaven.Services.Tests.csproj
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
||||
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SeaHaven.Services\SeaHaven.Services.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
104
SeaHaven.Services.Tests/ValidationTests.cs
Normal file
104
SeaHaven.Services.Tests/ValidationTests.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
using FluentAssertions;
|
||||
using SeaHaven.Services.DTOs;
|
||||
using SeaHaven.Services.Validation;
|
||||
using Xunit;
|
||||
|
||||
namespace SeaHaven.Services.Tests;
|
||||
|
||||
public class CreateAssetValidationTests
|
||||
{
|
||||
private readonly CreateAssetValidation _validator = new();
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenNameEmpty_Fails()
|
||||
{
|
||||
var result = _validator.Validate(new CreateAssetDTO { Name = "" });
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateAssetDTO.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenNameTooLong_Fails()
|
||||
{
|
||||
var result = _validator.Validate(new CreateAssetDTO { Name = new string('a', 201) });
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateAssetDTO.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenLocationIdZero_Fails()
|
||||
{
|
||||
var result = _validator.Validate(new CreateAssetDTO { Name = "Pump", LocationId = 0 });
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateAssetDTO.LocationId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenValid_Passes()
|
||||
{
|
||||
var result = _validator.Validate(new CreateAssetDTO { Name = "Pump", LocationId = 5 });
|
||||
|
||||
result.IsValid.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateContactValidationTests
|
||||
{
|
||||
private readonly CreateContactValidation _validator = new();
|
||||
|
||||
private static CreateContactDTO Valid() => new()
|
||||
{
|
||||
FirstName = "Ada",
|
||||
LastName = "Lovelace",
|
||||
Email = "ada@example.com"
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenNamesMissing_Fails()
|
||||
{
|
||||
var dto = Valid();
|
||||
dto.FirstName = "";
|
||||
dto.LastName = "";
|
||||
|
||||
var result = _validator.Validate(dto);
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateContactDTO.FirstName));
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateContactDTO.LastName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenEmailMalformed_Fails()
|
||||
{
|
||||
var dto = Valid();
|
||||
dto.Email = "not-an-email";
|
||||
|
||||
var result = _validator.Validate(dto);
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateContactDTO.Email));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenPhoneTooLong_Fails()
|
||||
{
|
||||
var dto = Valid();
|
||||
dto.Phone = new string('1', 21);
|
||||
|
||||
var result = _validator.Validate(dto);
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateContactDTO.Phone));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_WhenValid_Passes()
|
||||
{
|
||||
var result = _validator.Validate(Valid());
|
||||
|
||||
result.IsValid.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
74
SeaHaven.Services.Tests/WorkOrderMappingTests.cs
Normal file
74
SeaHaven.Services.Tests/WorkOrderMappingTests.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using Data.SeaHavenIndustries;
|
||||
using Data.SeaHavenIndustries.Enums;
|
||||
using FluentAssertions;
|
||||
using SeaHaven.Services.DTOs;
|
||||
using Xunit;
|
||||
|
||||
namespace SeaHaven.Services.Tests;
|
||||
|
||||
public class WorkOrderMappingTests
|
||||
{
|
||||
[Fact]
|
||||
public void MapToModel_WithValidEnumStrings_ParsesStatusAndPriority()
|
||||
{
|
||||
var entity = new WorkOrder
|
||||
{
|
||||
Id = 7,
|
||||
WorkerOrderTitle = "Fix pump",
|
||||
Status = "InProgress",
|
||||
Priority = "High"
|
||||
};
|
||||
|
||||
var dto = WorkOrderDTO.MapToModel(entity);
|
||||
|
||||
dto.Id.Should().Be(7);
|
||||
dto.WorkerOrderTitle.Should().Be("Fix pump");
|
||||
dto.Status.Should().Be(WorkOrderStatus.InProgress);
|
||||
dto.Priority.Should().Be(WorkOrderPriority.High);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapToModel_WithUnparseableEnumStrings_FallsBackToDefaults()
|
||||
{
|
||||
var entity = new WorkOrder
|
||||
{
|
||||
WorkerOrderTitle = "Garbage",
|
||||
Status = "not-a-status",
|
||||
Priority = "not-a-priority"
|
||||
};
|
||||
|
||||
var dto = WorkOrderDTO.MapToModel(entity);
|
||||
|
||||
dto.Status.Should().Be(WorkOrderStatus.Open);
|
||||
dto.Priority.Should().Be(WorkOrderPriority.Medium);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapToEntity_SerializesEnumsToStrings()
|
||||
{
|
||||
var dto = new WorkOrderDTO
|
||||
{
|
||||
Id = 3,
|
||||
WorkerOrderTitle = "Inspect",
|
||||
Status = WorkOrderStatus.Completed,
|
||||
Priority = WorkOrderPriority.Critical
|
||||
};
|
||||
|
||||
var entity = WorkOrderDTO.MapToEntity(dto);
|
||||
|
||||
entity.Status.Should().Be("Completed");
|
||||
entity.Priority.Should().Be("Critical");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateMapToEntity_WhenStatusAndPriorityNull_AppliesDefaults()
|
||||
{
|
||||
var dto = new CreateWorkOrderDTO { WorkerOrderTitle = "New" };
|
||||
|
||||
var entity = CreateWorkOrderDTO.MapToEntity(dto);
|
||||
|
||||
entity.Status.Should().Be("Open");
|
||||
entity.Priority.Should().Be("Medium");
|
||||
entity.CreatedDate.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeaHaven.DataServices", "Se
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api.SeaHavenIndustries.Tests", "Api.SeaHavenIndustries.Tests\Api.SeaHavenIndustries.Tests.csproj", "{1222E2E5-2FB0-4AA8-842C-0D77CFBA5E45}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeaHaven.Services.Tests", "SeaHaven.Services.Tests\SeaHaven.Services.Tests.csproj", "{97455198-C479-47F2-8BC8-601B335DFFAB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -45,6 +47,10 @@ Global
|
|||
{1222E2E5-2FB0-4AA8-842C-0D77CFBA5E45}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1222E2E5-2FB0-4AA8-842C-0D77CFBA5E45}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1222E2E5-2FB0-4AA8-842C-0D77CFBA5E45}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{97455198-C479-47F2-8BC8-601B335DFFAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{97455198-C479-47F2-8BC8-601B335DFFAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{97455198-C479-47F2-8BC8-601B335DFFAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{97455198-C479-47F2-8BC8-601B335DFFAB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue