From 389d35fd39edb144d614696ce0b48c01c026de5a Mon Sep 17 00:00:00 2001 From: Edwin van den Houdt Date: Thu, 4 Jun 2026 11:16:38 +0200 Subject: [PATCH] feat(acl): wire BDD step bindings to AclService (refs #5) Implement the step definitions for EenZaakOpenen.feature against the existing AclService, with an in-memory gateway standing in for the OpenZaak Zaken API. The scenario now passes: a domain registration is default-filled into a ZaakRequest (ADR-0003) and the created zaak URL is returned. Co-Authored-By: Claude Opus 4.8 --- tests/acceptance/Acceptance.csproj | 1 + tests/acceptance/Steps/EenZaakOpenenSteps.cs | 65 +++++++++++++++++++ tests/acceptance/Support/FixedClock.cs | 10 +++ .../acceptance/Support/InMemoryZaakGateway.cs | 20 ++++++ 4 files changed, 96 insertions(+) create mode 100644 tests/acceptance/Steps/EenZaakOpenenSteps.cs create mode 100644 tests/acceptance/Support/FixedClock.cs create mode 100644 tests/acceptance/Support/InMemoryZaakGateway.cs diff --git a/tests/acceptance/Acceptance.csproj b/tests/acceptance/Acceptance.csproj index a1f3232..c182441 100644 --- a/tests/acceptance/Acceptance.csproj +++ b/tests/acceptance/Acceptance.csproj @@ -11,6 +11,7 @@ + diff --git a/tests/acceptance/Steps/EenZaakOpenenSteps.cs b/tests/acceptance/Steps/EenZaakOpenenSteps.cs new file mode 100644 index 0000000..8c191bc --- /dev/null +++ b/tests/acceptance/Steps/EenZaakOpenenSteps.cs @@ -0,0 +1,65 @@ +using Acceptance.Support; +using Acl.Application; +using Reqnroll; +using Xunit; + +namespace Acceptance.Steps; + +/// Bindings for EenZaakOpenen.feature. Reqnroll creates one +/// instance per scenario, so instance fields hold scenario-scoped state. +[Binding] +public sealed class EenZaakOpenenSteps +{ + private readonly InMemoryZaakGateway _gateway = new(); + private DomainRegistration? _registration; + private AclDefaults? _defaults; + private DateOnly _today; + private Uri? _returnedUrl; + + [Given("a domain registration for BSN \"(.*)\"")] + public void GivenADomainRegistrationForBsn(string bsn) + => _registration = new DomainRegistration(bsn); + + [Given("the ACL is configured with these defaults:")] + public void GivenTheAclIsConfiguredWithTheseDefaults(DataTable defaults) + { + var values = ToFieldMap(defaults); + _defaults = new AclDefaults + { + Bronorganisatie = values["bronorganisatie"], + VerantwoordelijkeOrganisatie = values["verantwoordelijkeOrganisatie"], + Vertrouwelijkheidaanduiding = values["vertrouwelijkheidaanduiding"], + ZaaktypeUrl = new Uri(values["zaaktype"]), + }; + } + + [Given("today is \"(.*)\"")] + public void GivenTodayIs(string date) + => _today = DateOnly.Parse(date); + + [When("the domain asks the ACL to open a zaak")] + public async Task WhenTheDomainAsksTheAclToOpenAZaak() + { + var service = new AclService(_gateway, _defaults!, new FixedClock(_today)); + _returnedUrl = await service.OpenZaakAsync(_registration!); + } + + [Then("a zaak is created with these default-filled fields")] + public void ThenAZaakIsCreatedWithTheseDefaultFilledFields(DataTable expected) + { + var request = Assert.IsType(_gateway.Captured); + var fields = ToFieldMap(expected); + Assert.Equal(fields["bronorganisatie"], request.Bronorganisatie); + Assert.Equal(fields["verantwoordelijkeOrganisatie"], request.VerantwoordelijkeOrganisatie); + Assert.Equal(fields["vertrouwelijkheidaanduiding"], request.Vertrouwelijkheidaanduiding); + Assert.Equal(fields["zaaktype"], request.Zaaktype.ToString()); + Assert.Equal(fields["startdatum"], request.Startdatum.ToString("yyyy-MM-dd")); + } + + [Then("the ACL returns the URL of the created zaak")] + public void ThenTheAclReturnsTheUrlOfTheCreatedZaak() + => Assert.Equal(InMemoryZaakGateway.CreatedZaakUrl, _returnedUrl); + + private static Dictionary ToFieldMap(DataTable table) + => table.Rows.ToDictionary(r => r["field"], r => r["value"]); +} diff --git a/tests/acceptance/Support/FixedClock.cs b/tests/acceptance/Support/FixedClock.cs new file mode 100644 index 0000000..b6d8dce --- /dev/null +++ b/tests/acceptance/Support/FixedClock.cs @@ -0,0 +1,10 @@ +using Acl.Application; + +namespace Acceptance.Support; + +/// A clock pinned to a known date so startdatum is deterministic +/// in scenarios (ADR-0003). +public sealed class FixedClock(DateOnly today) : IClock +{ + public DateOnly Today { get; } = today; +} diff --git a/tests/acceptance/Support/InMemoryZaakGateway.cs b/tests/acceptance/Support/InMemoryZaakGateway.cs new file mode 100644 index 0000000..a1dde7b --- /dev/null +++ b/tests/acceptance/Support/InMemoryZaakGateway.cs @@ -0,0 +1,20 @@ +using Acl.Application; + +namespace Acceptance.Support; + +/// An in-memory stand-in for the OpenZaak Zaken API. It captures the +/// fully default-filled the ACL builds and returns a +/// fixed zaak URL, so the acceptance scenario can verify the use case without a +/// running OpenZaak (real-OpenZaak verification is a separate slice). +public sealed class InMemoryZaakGateway : IZaakGateway +{ + public static readonly Uri CreatedZaakUrl = new("http://openzaak/zaken/api/v1/zaken/created-123"); + + public ZaakRequest? Captured { get; private set; } + + public Task OpenZaakAsync(ZaakRequest request, CancellationToken ct = default) + { + Captured = request; + return Task.FromResult(CreatedZaakUrl); + } +}