using Acl.Application; namespace Acl.Tests; public class AclServiceTests { private sealed class FakeGateway : IZaakGateway { public ZaakRequest? Captured; public Uri Result { get; } = new("http://openzaak/zaken/api/v1/zaken/abc"); public (Uri Zaak, Uri Zaaktype, DateOnly Datum)? Approved; public Task OpenZaakAsync(ZaakRequest request, CancellationToken ct = default) { Captured = request; return Task.FromResult(Result); } public Task SetZaakToEindstatusAsync(Uri zaakUrl, Uri zaaktypeUrl, DateOnly datumStatusGezet, CancellationToken ct = default) { Approved = (zaakUrl, zaaktypeUrl, datumStatusGezet); return Task.CompletedTask; } public (Uri Zaak, Uri Zaaktype, DateOnly Datum)? Cancelled; public Task SetZaakToCancellationStatusAsync(Uri zaakUrl, Uri zaaktypeUrl, DateOnly datumStatusGezet, CancellationToken ct = default) { Cancelled = (zaakUrl, zaaktypeUrl, datumStatusGezet); return Task.CompletedTask; } public Uri? ReadReferenceFor; public Task GetZaakIdentificatieAsync(Uri zaakUrl, CancellationToken ct = default) { ReadReferenceFor = zaakUrl; return Task.FromResult("REG-FROM-ZAAK"); } public DocumentRequest? StoredDocument; public Uri DocumentResult { get; } = new("http://openzaak/documenten/api/v1/enkelvoudiginformatieobjecten/doc-1"); public Task StoreDocumentAsync(DocumentRequest request, CancellationToken ct = default) { StoredDocument = request; return Task.FromResult(DocumentResult); } } private static AclDefaults Defaults() => new() { Bronorganisatie = "517439943", VerantwoordelijkeOrganisatie = "517439943", Vertrouwelijkheidaanduiding = "openbaar", ZaaktypeUrl = new("http://openzaak/catalogi/api/v1/zaaktypen/big"), InformatieobjecttypeUrl = new("http://openzaak/catalogi/api/v1/informatieobjecttypen/dip"), }; private sealed class FixedClock(DateOnly today) : IClock { public DateOnly Today { get; } = today; } [Fact] public async Task Opening_a_zaak_default_fills_zgw_fields_and_returns_the_zaak_url() { var gateway = new FakeGateway(); var defaults = new AclDefaults { Bronorganisatie = "517439943", VerantwoordelijkeOrganisatie = "517439943", Vertrouwelijkheidaanduiding = "openbaar", ZaaktypeUrl = new("http://openzaak/catalogi/api/v1/zaaktypen/big"), InformatieobjecttypeUrl = new("http://openzaak/catalogi/api/v1/informatieobjecttypen/dip"), }; var service = new AclService(gateway, defaults, new FixedClock(new DateOnly(2026, 6, 4))); var url = await service.OpenZaakAsync(new DomainRegistration("123456782", "reg-77")); Assert.Equal(gateway.Result, url); var req = Assert.IsType(gateway.Captured); Assert.Equal("517439943", req.Bronorganisatie); Assert.Equal("517439943", req.VerantwoordelijkeOrganisatie); Assert.Equal("openbaar", req.Vertrouwelijkheidaanduiding); Assert.Equal(defaults.ZaaktypeUrl, req.Zaaktype); Assert.Equal(new DateOnly(2026, 6, 4), req.Startdatum); // The registration reference becomes the zaak identificatie (#78). Assert.Equal("reg-77", req.Identificatie); } [Fact] public async Task Rejects_a_null_registration_without_calling_the_gateway() { var gateway = new FakeGateway(); var defaults = new AclDefaults { Bronorganisatie = "517439943", VerantwoordelijkeOrganisatie = "517439943", Vertrouwelijkheidaanduiding = "openbaar", ZaaktypeUrl = new("http://openzaak/catalogi/api/v1/zaaktypen/big"), InformatieobjecttypeUrl = new("http://openzaak/catalogi/api/v1/informatieobjecttypen/dip"), }; var service = new AclService(gateway, defaults, new FixedClock(new DateOnly(2026, 6, 4))); await Assert.ThrowsAsync(() => service.OpenZaakAsync(null!)); Assert.Null(gateway.Captured); } [Fact] public async Task Approving_a_zaak_sets_it_to_its_zaaktypes_eindstatus_dated_today() { var gateway = new FakeGateway(); var defaults = Defaults(); var service = new AclService(gateway, defaults, new FixedClock(new DateOnly(2026, 6, 4))); var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc"); await service.ApproveZaakAsync(zaak); Assert.NotNull(gateway.Approved); Assert.Equal(zaak, gateway.Approved!.Value.Zaak); Assert.Equal(defaults.ZaaktypeUrl, gateway.Approved.Value.Zaaktype); Assert.Equal(new DateOnly(2026, 6, 4), gateway.Approved.Value.Datum); } [Fact] public async Task Approving_a_null_zaak_is_rejected_without_touching_the_gateway() { var gateway = new FakeGateway(); var service = new AclService(gateway, Defaults(), new FixedClock(new DateOnly(2026, 6, 4))); await Assert.ThrowsAsync(() => service.ApproveZaakAsync(null!)); Assert.Null(gateway.Approved); } [Fact] public async Task Storing_a_diploma_default_fills_the_document_fields_and_returns_its_url() { var gateway = new FakeGateway(); var defaults = Defaults(); var service = new AclService(gateway, defaults, new FixedClock(new DateOnly(2026, 6, 4))); var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc"); var url = await service.StoreDiplomaAsync(zaak, [1, 2, 3], "diploma.pdf", "application/pdf"); Assert.Equal(gateway.DocumentResult, url); var req = gateway.StoredDocument!; Assert.Equal(zaak, req.Zaak); Assert.Equal(defaults.InformatieobjecttypeUrl, req.Informatieobjecttype); Assert.Equal("517439943", req.Bronorganisatie); Assert.Equal("openbaar", req.Vertrouwelijkheidaanduiding); Assert.Equal(new DateOnly(2026, 6, 4), req.Creatiedatum); Assert.Equal("nld", req.Taal); Assert.Equal("diploma.pdf", req.Bestandsnaam); Assert.Equal("application/pdf", req.Formaat); Assert.Equal(new byte[] { 1, 2, 3 }, req.Inhoud); } [Fact] public async Task Storing_a_diploma_rejects_null_or_blank_arguments() { var service = new AclService(new FakeGateway(), Defaults(), new FixedClock(new DateOnly(2026, 6, 4))); var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc"); await Assert.ThrowsAsync(() => service.StoreDiplomaAsync(null!, [1], "d.pdf", "application/pdf")); await Assert.ThrowsAsync(() => service.StoreDiplomaAsync(zaak, null!, "d.pdf", "application/pdf")); await Assert.ThrowsAnyAsync(() => service.StoreDiplomaAsync(zaak, [1], " ", "application/pdf")); await Assert.ThrowsAnyAsync(() => service.StoreDiplomaAsync(zaak, [1], "d.pdf", " ")); } [Fact] public async Task Reading_a_zaak_reference_returns_the_zaaks_identificatie() { var gateway = new FakeGateway(); var service = new AclService(gateway, Defaults(), new FixedClock(new DateOnly(2026, 6, 4))); var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc"); var reference = await service.GetZaakReferenceAsync(zaak); Assert.Equal("REG-FROM-ZAAK", reference); Assert.Equal(zaak, gateway.ReadReferenceFor); } [Fact] public async Task Reading_a_null_zaak_reference_is_rejected() { var gateway = new FakeGateway(); var service = new AclService(gateway, Defaults(), new FixedClock(new DateOnly(2026, 6, 4))); await Assert.ThrowsAsync(() => service.GetZaakReferenceAsync(null!)); Assert.Null(gateway.ReadReferenceFor); } }