refactor(domain): introduce UserFactory and WorkplaceFactory for reconstitution
Consistent with ReservationFactory — moves Reconstitute out of the entity into a dedicated factory class, and makes the reconstitution constructor internal to restrict direct instantiation to within the domain assembly. Adds unit tests for all three factories. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,10 +10,7 @@ public class User : Entity
|
||||
public bool IsApproved { get; private set; }
|
||||
public bool IsAdmin { get; private set; }
|
||||
|
||||
public static User Reconstitute(Guid id, string email, string name, string passwordHash, bool isApproved, bool isAdmin) =>
|
||||
new(id, email, name, passwordHash, isApproved, isAdmin);
|
||||
|
||||
private User(Guid id, string email, string name, string passwordHash, bool isApproved, bool isAdmin) : base(id)
|
||||
internal User(Guid id, string email, string name, string passwordHash, bool isApproved, bool isAdmin) : base(id)
|
||||
{
|
||||
Email = email;
|
||||
Name = name;
|
||||
|
||||
7
src/backend/src/Randall.Domain/Users/UserFactory.cs
Normal file
7
src/backend/src/Randall.Domain/Users/UserFactory.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Randall.Domain.Users;
|
||||
|
||||
public static class UserFactory
|
||||
{
|
||||
public static User Reconstitute(Guid id, string email, string name, string passwordHash, bool isApproved, bool isAdmin) =>
|
||||
new(id, email, name, passwordHash, isApproved, isAdmin);
|
||||
}
|
||||
@@ -8,10 +8,7 @@ public class Workplace : Entity
|
||||
public string Location { get; private set; }
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
public static Workplace Reconstitute(Guid id, string name, string location, bool isActive) =>
|
||||
new(id, name, location, isActive);
|
||||
|
||||
private Workplace(Guid id, string name, string location, bool isActive) : base(id)
|
||||
internal Workplace(Guid id, string name, string location, bool isActive) : base(id)
|
||||
{
|
||||
Name = name;
|
||||
Location = location;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Randall.Domain.Workplaces;
|
||||
|
||||
public static class WorkplaceFactory
|
||||
{
|
||||
public static Workplace Reconstitute(Guid id, string name, string location, bool isActive) =>
|
||||
new(id, name, location, isActive);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Randall.Infrastructure.Persistence.Mappers;
|
||||
public static class UserMapper
|
||||
{
|
||||
public static User ToDomain(UserRecord record) =>
|
||||
User.Reconstitute(
|
||||
UserFactory.Reconstitute(
|
||||
record.Id,
|
||||
record.Email,
|
||||
record.Name,
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Randall.Infrastructure.Persistence.Mappers;
|
||||
public static class WorkplaceMapper
|
||||
{
|
||||
public static Workplace ToDomain(WorkplaceRecord record) =>
|
||||
Workplace.Reconstitute(
|
||||
WorkplaceFactory.Reconstitute(
|
||||
record.Id,
|
||||
record.Name,
|
||||
record.Location,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using Randall.Domain.Reservations;
|
||||
|
||||
namespace Randall.Domain.UnitTests.Reservations;
|
||||
|
||||
public class ReservationFactoryTests
|
||||
{
|
||||
private static readonly Guid Id = Guid.NewGuid();
|
||||
private static readonly Guid WorkplaceId = Guid.NewGuid();
|
||||
private const string Email = "jane@company.com";
|
||||
private const string Name = "Jane Smith";
|
||||
private static readonly DateOnly Date = new(2026, 6, 1);
|
||||
private static readonly DateTime CreatedAt = new(2026, 5, 1, 12, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_MapsAllFieldsExactly()
|
||||
{
|
||||
var reservation = ReservationFactory.Reconstitute(Id, WorkplaceId, Email, Name, Date, ReservationStatus.Active, CreatedAt);
|
||||
|
||||
Assert.Equal(Id, reservation.Id);
|
||||
Assert.Equal(WorkplaceId, reservation.WorkplaceId);
|
||||
Assert.Equal(Email, reservation.EmployeeEmail);
|
||||
Assert.Equal(Name, reservation.EmployeeName);
|
||||
Assert.Equal(Date, reservation.Date);
|
||||
Assert.Equal(ReservationStatus.Active, reservation.Status);
|
||||
Assert.Equal(CreatedAt, reservation.CreatedAt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_PreservesProvidedId()
|
||||
{
|
||||
var reservation = ReservationFactory.Reconstitute(Id, WorkplaceId, Email, Name, Date, ReservationStatus.Active, CreatedAt);
|
||||
|
||||
Assert.Equal(Id, reservation.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreActiveReservation()
|
||||
{
|
||||
var reservation = ReservationFactory.Reconstitute(Id, WorkplaceId, Email, Name, Date, ReservationStatus.Active, CreatedAt);
|
||||
|
||||
Assert.Equal(ReservationStatus.Active, reservation.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreCancelledReservation()
|
||||
{
|
||||
var reservation = ReservationFactory.Reconstitute(Id, WorkplaceId, Email, Name, Date, ReservationStatus.Cancelled, CreatedAt);
|
||||
|
||||
Assert.Equal(ReservationStatus.Cancelled, reservation.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestorePastReservation()
|
||||
{
|
||||
var pastDate = new DateOnly(2020, 1, 1);
|
||||
|
||||
var reservation = ReservationFactory.Reconstitute(Id, WorkplaceId, Email, Name, pastDate, ReservationStatus.Active, CreatedAt);
|
||||
|
||||
Assert.Equal(pastDate, reservation.Date);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using Randall.Domain.Users;
|
||||
|
||||
namespace Randall.Domain.UnitTests.Users;
|
||||
|
||||
public class UserFactoryTests
|
||||
{
|
||||
private static readonly Guid Id = Guid.NewGuid();
|
||||
private const string Email = "jane@company.com";
|
||||
private const string Name = "Jane Smith";
|
||||
private const string PasswordHash = "hashed-password";
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_MapsAllFieldsExactly()
|
||||
{
|
||||
var user = UserFactory.Reconstitute(Id, Email, Name, PasswordHash, isApproved: true, isAdmin: false);
|
||||
|
||||
Assert.Equal(Id, user.Id);
|
||||
Assert.Equal(Email, user.Email);
|
||||
Assert.Equal(Name, user.Name);
|
||||
Assert.Equal(PasswordHash, user.PasswordHash);
|
||||
Assert.True(user.IsApproved);
|
||||
Assert.False(user.IsAdmin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_PreservesProvidedId()
|
||||
{
|
||||
var user = UserFactory.Reconstitute(Id, Email, Name, PasswordHash, isApproved: false, isAdmin: false);
|
||||
|
||||
Assert.Equal(Id, user.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreApprovedNonAdminUser()
|
||||
{
|
||||
var user = UserFactory.Reconstitute(Id, Email, Name, PasswordHash, isApproved: true, isAdmin: false);
|
||||
|
||||
Assert.True(user.IsApproved);
|
||||
Assert.False(user.IsAdmin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreUnapprovedUser()
|
||||
{
|
||||
var user = UserFactory.Reconstitute(Id, Email, Name, PasswordHash, isApproved: false, isAdmin: false);
|
||||
|
||||
Assert.False(user.IsApproved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreAdminUser()
|
||||
{
|
||||
var user = UserFactory.Reconstitute(Id, Email, Name, PasswordHash, isApproved: true, isAdmin: true);
|
||||
|
||||
Assert.True(user.IsAdmin);
|
||||
Assert.True(user.IsApproved);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Randall.Domain.Workplaces;
|
||||
|
||||
namespace Randall.Domain.UnitTests.Workplaces;
|
||||
|
||||
public class WorkplaceFactoryTests
|
||||
{
|
||||
private static readonly Guid Id = Guid.NewGuid();
|
||||
private const string Name = "D13";
|
||||
private const string Location = "Pod A";
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_MapsAllFieldsExactly()
|
||||
{
|
||||
var workplace = WorkplaceFactory.Reconstitute(Id, Name, Location, isActive: true);
|
||||
|
||||
Assert.Equal(Id, workplace.Id);
|
||||
Assert.Equal(Name, workplace.Name);
|
||||
Assert.Equal(Location, workplace.Location);
|
||||
Assert.True(workplace.IsActive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_PreservesProvidedId()
|
||||
{
|
||||
var workplace = WorkplaceFactory.Reconstitute(Id, Name, Location, isActive: true);
|
||||
|
||||
Assert.Equal(Id, workplace.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreActiveWorkplace()
|
||||
{
|
||||
var workplace = WorkplaceFactory.Reconstitute(Id, Name, Location, isActive: true);
|
||||
|
||||
Assert.True(workplace.IsActive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reconstitute_CanRestoreInactiveWorkplace()
|
||||
{
|
||||
var workplace = WorkplaceFactory.Reconstitute(Id, Name, Location, isActive: false);
|
||||
|
||||
Assert.False(workplace.IsActive);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user