diff --git a/services/domain/Big.Tests/ApproveRegistrationTests.cs b/services/domain/Big.Tests/ApproveRegistrationTests.cs new file mode 100644 index 0000000..2112f96 --- /dev/null +++ b/services/domain/Big.Tests/ApproveRegistrationTests.cs @@ -0,0 +1,74 @@ +using Big.Application; +using Big.Domain; + +namespace Big.Tests; + +public class ApproveRegistrationTests +{ + private static Registration WithZaak(string bsn = "123456782") + { + var registration = Registration.Submit(bsn); + registration.AttachZaak(FakeAclClient.DefaultZaakUrl); + return registration; + } + + [Fact] + public async Task Approving_sets_the_zaak_status_via_the_acl_and_marks_the_registration_ingeschreven() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + store.Seed(registration); + var handler = new ApproveRegistration(store, acl); + + await handler.HandleAsync(new ApproveRegistrationCommand(registration.Id)); + + var saved = await store.GetAsync(registration.Id); + Assert.Equal(RegistrationStatus.Ingeschreven, saved!.Status); + Assert.Equal(FakeAclClient.DefaultZaakUrl, acl.ApprovedZaakUrl); + Assert.Equal(1, acl.ApproveCallCount); + } + + [Fact] + public async Task Approving_an_unknown_registration_throws_and_does_not_call_the_acl() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var handler = new ApproveRegistration(store, acl); + + await Assert.ThrowsAsync( + () => handler.HandleAsync(new ApproveRegistrationCommand(RegistrationId.New()))); + Assert.Equal(0, acl.ApproveCallCount); + } + + [Fact] + public async Task Approving_before_the_zaak_is_opened_throws_without_calling_the_acl() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = Registration.Submit("123456782"); // no zaak yet + store.Seed(registration); + var handler = new ApproveRegistration(store, acl); + + await Assert.ThrowsAsync( + () => handler.HandleAsync(new ApproveRegistrationCommand(registration.Id))); + Assert.Equal(0, acl.ApproveCallCount); + } + + [Fact] + public async Task Re_approving_an_already_ingeschreven_registration_is_idempotent() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + store.Seed(registration); + var handler = new ApproveRegistration(store, acl); + + await handler.HandleAsync(new ApproveRegistrationCommand(registration.Id)); + await handler.HandleAsync(new ApproveRegistrationCommand(registration.Id)); + + // The second approval is a no-op: the ACL is not asked to set the status again. + Assert.Equal(1, acl.ApproveCallCount); + Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status); + } +} diff --git a/services/domain/Big.Tests/Fakes.cs b/services/domain/Big.Tests/Fakes.cs index 38d1bae..2377b7b 100644 --- a/services/domain/Big.Tests/Fakes.cs +++ b/services/domain/Big.Tests/Fakes.cs @@ -52,10 +52,20 @@ internal sealed class FakeAclClient(Uri? zaakUrl = null) : IAclClient public string? OpenedForBsn { get; private set; } public int CallCount { get; private set; } + public Uri? ApprovedZaakUrl { get; private set; } + public int ApproveCallCount { get; private set; } + public Task OpenZaakAsync(string bsn, CancellationToken ct = default) { CallCount++; OpenedForBsn = bsn; return Task.FromResult(_zaakUrl); } + + public Task ApproveZaakAsync(Uri zaakUrl, CancellationToken ct = default) + { + ApproveCallCount++; + ApprovedZaakUrl = zaakUrl; + return Task.CompletedTask; + } }