From 57cc3637c96e3ea73cadb0b21a222525818ceb3f Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Wed, 15 Jul 2026 09:16:46 +0200 Subject: [PATCH] =?UTF-8?q?test(workflow):=20user-task=20client=20?= =?UTF-8?q?=E2=80=94=20werkbak=20query,=20claim,=20complete=20beoordeling?= =?UTF-8?q?=20(refs=20#13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Red — GetOpenBeoordelingenAsync/ClaimAsync/CompleteBeoordelingAsync do not exist yet. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Big.Tests/FlowableWorkflowClientTests.cs | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/services/domain/Big.Tests/FlowableWorkflowClientTests.cs b/services/domain/Big.Tests/FlowableWorkflowClientTests.cs index 625d69f..3d53a04 100644 --- a/services/domain/Big.Tests/FlowableWorkflowClientTests.cs +++ b/services/domain/Big.Tests/FlowableWorkflowClientTests.cs @@ -1,5 +1,6 @@ using System.Net; using System.Text; +using Big.Application; using Big.Domain; using Big.Infrastructure; @@ -136,4 +137,106 @@ public class FlowableWorkflowClientTests await Assert.ThrowsAsync( () => client.CompleteOpenZaakJobAsync("job-1", new Uri("http://openzaak/zaken/api/v1/zaken/abc"))); } + + // ── S-12b: behandelaar user tasks (werkbak / claim / complete) ──────────────────────────────── + + [Fact] + public async Task Open_beoordelingen_queries_beoordelen_tasks_with_their_registration_id() + { + var rid = RegistrationId.New(); + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.OK, + $$""" + {"data":[{"id":"task-1","processVariables":[{"name":"registrationId","type":"string","value":"{{rid}}"}]}],"total":1} + """)); + + var tasks = await client.GetOpenBeoordelingenAsync(); + + var task = Assert.Single(tasks); + Assert.Equal("task-1", task.TaskId); + Assert.Equal(rid, task.RegistrationId); + Assert.Equal(HttpMethod.Post, capture.Seen!.Method); + Assert.Equal("http://flowable/flowable-rest/service/runtime/tasks/query", + capture.Seen.RequestUri!.ToString()); + Assert.Equal("rest-admin:test", DecodeBasic(capture.Seen)); + Assert.Contains("\"processDefinitionKey\":\"registratie\"", capture.Body); + Assert.Contains("\"taskDefinitionKey\":\"Beoordelen\"", capture.Body); + Assert.Contains("\"includeProcessVariables\":true", capture.Body); + } + + [Theory] + [InlineData("""{"data":[],"total":0}""")] + [InlineData("""{"data":null,"total":0}""")] + public async Task Open_beoordelingen_is_empty_when_no_tasks_are_waiting(string body) + { + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.OK, body)); + + Assert.Empty(await client.GetOpenBeoordelingenAsync()); + Assert.NotNull(capture.Seen); + } + + [Fact] + public async Task Open_beoordelingen_throws_when_a_task_carries_no_registration_id() + { + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.OK, + """{"data":[{"id":"task-1","processVariables":[]}],"total":1}""")); + + var ex = await Assert.ThrowsAsync(() => client.GetOpenBeoordelingenAsync()); + Assert.Contains("task-1", ex.Message); + Assert.Contains("registrationId", ex.Message); + } + + [Fact] + public async Task Claim_assigns_the_task_to_the_behandelaar() + { + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.OK)); + + await client.ClaimAsync("task-1", "merel-behandelaar"); + + Assert.Equal(HttpMethod.Post, capture.Seen!.Method); + Assert.Equal("http://flowable/flowable-rest/service/runtime/tasks/task-1", + capture.Seen.RequestUri!.ToString()); + Assert.Contains("\"action\":\"claim\"", capture.Body); + Assert.Contains("\"assignee\":\"merel-behandelaar\"", capture.Body); + } + + [Fact] + public async Task Claim_throws_when_flowable_rejects_the_request() + { + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.Conflict)); + + await Assert.ThrowsAsync(() => client.ClaimAsync("task-1", "merel-behandelaar")); + } + + [Theory] + [InlineData(BeoordelingsBesluit.Goedkeuren, "goedkeuren")] + [InlineData(BeoordelingsBesluit.Afwijzen, "afwijzen")] + public async Task Complete_posts_the_besluit_variable_to_the_task(BeoordelingsBesluit besluit, string expected) + { + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.OK)); + + await client.CompleteBeoordelingAsync("task-1", besluit); + + Assert.Equal(HttpMethod.Post, capture.Seen!.Method); + Assert.Equal("http://flowable/flowable-rest/service/runtime/tasks/task-1", + capture.Seen.RequestUri!.ToString()); + Assert.Contains("\"action\":\"complete\"", capture.Body); + Assert.Contains("\"name\":\"besluit\"", capture.Body); + Assert.Contains($"\"value\":\"{expected}\"", capture.Body); + } + + [Fact] + public async Task Complete_beoordeling_throws_when_flowable_rejects_the_request() + { + var capture = new RequestCapture(); + var client = Client(capture.Responds(HttpStatusCode.InternalServerError)); + + await Assert.ThrowsAsync( + () => client.CompleteBeoordelingAsync("task-1", BeoordelingsBesluit.Goedkeuren)); + } }