From ffd59c0aac463408baa7b60d4e82f2ed5bbea8d3 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Wed, 15 Jul 2026 11:00:46 +0200 Subject: [PATCH] test(domain): werkbak query lists open beoordelingen enriched from the store (refs #13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Red — the Werkbak use-case and WerkbakItem do not exist yet. Co-Authored-By: Claude Opus 4.8 (1M context) --- services/domain/Big.Tests/Fakes.cs | 23 +++++++++++ services/domain/Big.Tests/WerkbakTests.cs | 49 +++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 services/domain/Big.Tests/WerkbakTests.cs diff --git a/services/domain/Big.Tests/Fakes.cs b/services/domain/Big.Tests/Fakes.cs index cf0a37d..bfd0a54 100644 --- a/services/domain/Big.Tests/Fakes.cs +++ b/services/domain/Big.Tests/Fakes.cs @@ -41,6 +41,29 @@ internal sealed class FakeWorkflowClient(string processInstanceId = "proc-1", Ac } } +/// A fake user-task client for the werkbak/decision use cases: returns a scripted set of +/// open beoordeling tasks and records claim/complete calls. +internal sealed class FakeUserTaskClient(IReadOnlyList open) : IUserTaskClient +{ + public (string TaskId, string Behandelaar)? Claimed { get; private set; } + public (string TaskId, BeoordelingsBesluit Besluit)? Completed { get; private set; } + + public Task> GetOpenBeoordelingenAsync(CancellationToken ct = default) + => Task.FromResult(open); + + public Task ClaimAsync(string taskId, string behandelaar, CancellationToken ct = default) + { + Claimed = (taskId, behandelaar); + return Task.CompletedTask; + } + + public Task CompleteBeoordelingAsync(string taskId, BeoordelingsBesluit besluit, CancellationToken ct = default) + { + Completed = (taskId, besluit); + return Task.CompletedTask; + } +} + /// A fake ACL client that records the bsn it was asked to open a zaak for and returns a /// fixed zaak URL. internal sealed class FakeAclClient(Uri? zaakUrl = null) : IAclClient diff --git a/services/domain/Big.Tests/WerkbakTests.cs b/services/domain/Big.Tests/WerkbakTests.cs new file mode 100644 index 0000000..bfbf182 --- /dev/null +++ b/services/domain/Big.Tests/WerkbakTests.cs @@ -0,0 +1,49 @@ +using Big.Application; +using Big.Domain; + +namespace Big.Tests; + +/// +/// The werkbak query (S-12c): the behandelaar's list of registrations awaiting beoordeling. It reads +/// the open Beoordelen tasks from the workflow engine (§8.2) and enriches each with its registration +/// (bsn + status) from the store. A task whose registration is unknown is skipped defensively. +/// +public class WerkbakTests +{ + [Fact] + public async Task Lists_an_item_per_open_beoordeling_enriched_from_the_registration() + { + var store = new FakeRegistrationStore(); + var registration = Registration.Submit("123456782"); + registration.AttachZaak(FakeAclClient.DefaultZaakUrl); + registration.TakeIntoBehandeling(); + store.Seed(registration); + var tasks = new FakeUserTaskClient([new BeoordelingTask("task-1", registration.Id)]); + var werkbak = new Werkbak(tasks, store); + + var items = await werkbak.GetAsync(); + + var item = Assert.Single(items); + Assert.Equal(registration.Id.ToString(), item.RegistrationId); + Assert.Equal("123456782", item.Bsn); + Assert.Equal("InBehandeling", item.Status); + } + + [Fact] + public async Task Is_empty_when_no_beoordelingen_are_open() + { + var werkbak = new Werkbak(new FakeUserTaskClient([]), new FakeRegistrationStore()); + + Assert.Empty(await werkbak.GetAsync()); + } + + [Fact] + public async Task Skips_a_task_whose_registration_is_unknown() + { + // Defensive: the werkbak never invents an item for a task the domain has no aggregate for. + var tasks = new FakeUserTaskClient([new BeoordelingTask("task-1", RegistrationId.New())]); + var werkbak = new Werkbak(tasks, new FakeRegistrationStore()); + + Assert.Empty(await werkbak.GetAsync()); + } +}