Add unittests

This commit is contained in:
Robert van Diest
2026-03-25 19:22:25 +01:00
parent 3219b3a14d
commit ed293a57be
10 changed files with 435 additions and 1 deletions

View File

@@ -0,0 +1,53 @@
using Randall.Domain.Common;
namespace Randall.Domain.UnitTests.Common;
public class ResultTests
{
[Fact]
public void Success_IsSuccessIsTrue()
{
var result = Result.Success();
Assert.True(result.IsSuccess);
Assert.Null(result.Error);
}
[Fact]
public void Failure_IsSuccessIsFalse()
{
var result = Result.Failure("Something went wrong");
Assert.False(result.IsSuccess);
Assert.Equal("Something went wrong", result.Error);
}
[Fact]
public void SuccessOfT_ContainsValue()
{
var result = Result.Success(42);
Assert.True(result.IsSuccess);
Assert.Equal(42, result.Value);
Assert.Null(result.Error);
}
[Fact]
public void FailureOfT_ValueIsDefault()
{
var result = Result.Failure<int>("error");
Assert.False(result.IsSuccess);
Assert.Equal(default, result.Value);
Assert.Equal("error", result.Error);
}
[Fact]
public void FailureOfT_ReferenceType_ValueIsNull()
{
var result = Result.Failure<string>("error");
Assert.False(result.IsSuccess);
Assert.Null(result.Value);
}
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Randall.Domain\Randall.Domain.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,48 @@
using Randall.Domain.Reservations;
namespace Randall.Domain.UnitTests.Reservations;
public class ReservationCancelTests
{
private static Reservation CreateActiveReservation()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
return Reservation.Create(Guid.NewGuid(), "jane@company.com", "Jane", today, today).Value!;
}
[Fact]
public void Cancel_ActiveReservation_Succeeds()
{
var reservation = CreateActiveReservation();
var result = reservation.Cancel();
Assert.True(result.IsSuccess);
Assert.Equal(ReservationStatus.Cancelled, reservation.Status);
}
[Fact]
public void Cancel_AlreadyCancelledReservation_Fails()
{
var reservation = CreateActiveReservation();
reservation.Cancel();
var result = reservation.Cancel();
Assert.False(result.IsSuccess);
Assert.Contains("already cancelled", result.Error, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void Cancel_DoesNotChangeOtherFields()
{
var reservation = CreateActiveReservation();
var originalDate = reservation.Date;
var originalEmail = reservation.EmployeeEmail;
reservation.Cancel();
Assert.Equal(originalDate, reservation.Date);
Assert.Equal(originalEmail, reservation.EmployeeEmail);
}
}

View File

@@ -0,0 +1,98 @@
using Randall.Domain.Reservations;
namespace Randall.Domain.UnitTests.Reservations;
public class ReservationCreateTests
{
private static readonly Guid WorkplaceId = Guid.NewGuid();
private const string Email = "jane@company.com";
private const string Name = "Jane Smith";
[Fact]
public void Create_WithValidFutureDate_Succeeds()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var result = Reservation.Create(WorkplaceId, Email, Name, today, today);
Assert.True(result.IsSuccess);
Assert.NotNull(result.Value);
}
[Fact]
public void Create_WithTodayAsDate_Succeeds()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var result = Reservation.Create(WorkplaceId, Email, Name, today, today);
Assert.True(result.IsSuccess);
}
[Fact]
public void Create_WithMaxAdvanceDate_Succeeds()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var maxDate = today.AddDays(Reservation.MaxAdvanceDays);
var result = Reservation.Create(WorkplaceId, Email, Name, maxDate, today);
Assert.True(result.IsSuccess);
}
[Fact]
public void Create_WithPastDate_Fails()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var yesterday = today.AddDays(-1);
var result = Reservation.Create(WorkplaceId, Email, Name, yesterday, today);
Assert.False(result.IsSuccess);
Assert.Contains("past", result.Error, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void Create_BeyondMaxAdvanceDays_Fails()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var tooFar = today.AddDays(Reservation.MaxAdvanceDays + 1);
var result = Reservation.Create(WorkplaceId, Email, Name, tooFar, today);
Assert.False(result.IsSuccess);
Assert.Contains(Reservation.MaxAdvanceDays.ToString(), result.Error);
}
[Fact]
public void Create_SetsStatusToActive()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var result = Reservation.Create(WorkplaceId, Email, Name, today, today);
Assert.Equal(ReservationStatus.Active, result.Value!.Status);
}
[Fact]
public void Create_PopulatesAllFields()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var result = Reservation.Create(WorkplaceId, Email, Name, today, today);
var reservation = result.Value!;
Assert.Equal(WorkplaceId, reservation.WorkplaceId);
Assert.Equal(Email, reservation.EmployeeEmail);
Assert.Equal(Name, reservation.EmployeeName);
Assert.Equal(today, reservation.Date);
Assert.NotEqual(Guid.Empty, reservation.Id);
}
[Fact]
public void Create_SetsCreatedAtToApproximatelyNow()
{
var before = DateTime.UtcNow;
var today = DateOnly.FromDateTime(DateTime.UtcNow);
var result = Reservation.Create(WorkplaceId, Email, Name, today, today);
var after = DateTime.UtcNow;
Assert.InRange(result.Value!.CreatedAt, before, after);
}
}

View File

@@ -0,0 +1,84 @@
using Randall.Domain.Users;
namespace Randall.Domain.UnitTests.Users;
public class UserCreateTests
{
[Fact]
public void Create_WithValidData_Succeeds()
{
var result = User.Create("jane@company.com", "Jane Smith", "hash");
Assert.True(result.IsSuccess);
Assert.NotNull(result.Value);
}
[Fact]
public void Create_NormalisesEmailToLowercase()
{
var result = User.Create("JANE@COMPANY.COM", "Jane Smith", "hash");
Assert.Equal("jane@company.com", result.Value!.Email);
}
[Fact]
public void Create_TrimsNameWhitespace()
{
var result = User.Create("jane@company.com", " Jane Smith ", "hash");
Assert.Equal("Jane Smith", result.Value!.Name);
}
[Fact]
public void Create_WithEmptyEmail_Fails()
{
var result = User.Create("", "Jane Smith", "hash");
Assert.False(result.IsSuccess);
Assert.Contains("email", result.Error, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void Create_WithWhitespaceEmail_Fails()
{
var result = User.Create(" ", "Jane Smith", "hash");
Assert.False(result.IsSuccess);
}
[Fact]
public void Create_WithEmptyName_Fails()
{
var result = User.Create("jane@company.com", "", "hash");
Assert.False(result.IsSuccess);
Assert.Contains("name", result.Error, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void Create_RegularUser_IsNotApprovedByDefault()
{
var result = User.Create("jane@company.com", "Jane Smith", "hash");
Assert.False(result.Value!.IsApproved);
Assert.False(result.Value!.IsAdmin);
}
[Fact]
public void Create_AdminUser_IsAutoApproved()
{
var result = User.Create("admin@company.com", "Admin", "hash", isAdmin: true);
Assert.True(result.Value!.IsAdmin);
Assert.True(result.Value!.IsApproved);
}
[Fact]
public void Create_AssignsUniqueId()
{
var a = User.Create("a@company.com", "A", "hash").Value!;
var b = User.Create("b@company.com", "B", "hash").Value!;
Assert.NotEqual(a.Id, b.Id);
}
}

View File

@@ -0,0 +1,42 @@
using Randall.Domain.Users;
namespace Randall.Domain.UnitTests.Users;
public class UserStateTests
{
private static User CreateRegularUser() =>
User.Create("jane@company.com", "Jane Smith", "hash").Value!;
[Fact]
public void Approve_SetsIsApprovedToTrue()
{
var user = CreateRegularUser();
user.Approve();
Assert.True(user.IsApproved);
}
[Fact]
public void MakeAdmin_SetsIsAdminAndIsApproved()
{
var user = CreateRegularUser();
user.MakeAdmin();
Assert.True(user.IsAdmin);
Assert.True(user.IsApproved);
}
[Fact]
public void MakeAdmin_OnAlreadyApprovedUser_RemainsApproved()
{
var user = CreateRegularUser();
user.Approve();
user.MakeAdmin();
Assert.True(user.IsApproved);
Assert.True(user.IsAdmin);
}
}

View File

@@ -0,0 +1,61 @@
using Randall.Domain.Workplaces;
namespace Randall.Domain.UnitTests.Workplaces;
public class WorkplaceTests
{
[Fact]
public void Create_IsActiveByDefault()
{
var workplace = new Workplace("A1", "Pod A");
Assert.True(workplace.IsActive);
}
[Fact]
public void Create_SetsNameAndLocation()
{
var workplace = new Workplace("A1", "Pod A");
Assert.Equal("A1", workplace.Name);
Assert.Equal("Pod A", workplace.Location);
}
[Fact]
public void Create_AssignsNonEmptyId()
{
var workplace = new Workplace("A1", "Pod A");
Assert.NotEqual(Guid.Empty, workplace.Id);
}
[Fact]
public void Deactivate_SetsIsActiveToFalse()
{
var workplace = new Workplace("A1", "Pod A");
workplace.Deactivate();
Assert.False(workplace.IsActive);
}
[Fact]
public void Activate_AfterDeactivate_SetsIsActiveToTrue()
{
var workplace = new Workplace("A1", "Pod A");
workplace.Deactivate();
workplace.Activate();
Assert.True(workplace.IsActive);
}
[Fact]
public void Create_TwoWorkplaces_HaveDifferentIds()
{
var a = new Workplace("A1", "Pod A");
var b = new Workplace("A2", "Pod A");
Assert.NotEqual(a.Id, b.Id);
}
}