From b672132ed4f9a5b64d4d97abfa93cf4a521b6926 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Mon, 13 Jul 2026 17:02:39 +0200 Subject: [PATCH] test(event-subscriber): project INGESCHREVEN from a status-set notification (refs #75) A zaken/status/create notification (hoofdObject = the zaak) updates the zaak's row to INGESCHREVEN, and a rebuild reproduces it. Red: Notification has no hoofdObject/ IsZaakStatusSet and RegistrationStatus.Ingeschreven doesn't exist. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../NotificationProjectorTests.cs | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/services/event-subscriber/EventSubscriber.Tests/NotificationProjectorTests.cs b/services/event-subscriber/EventSubscriber.Tests/NotificationProjectorTests.cs index 65d1092..c472c9a 100644 --- a/services/event-subscriber/EventSubscriber.Tests/NotificationProjectorTests.cs +++ b/services/event-subscriber/EventSubscriber.Tests/NotificationProjectorTests.cs @@ -8,6 +8,7 @@ namespace EventSubscriber.Tests; public sealed class NotificationProjectorTests { private const string ZaakUrl = "http://openzaak:8000/zaken/api/v1/zaken/11111111-1111-1111-1111-111111111111"; + private const string StatusUrl = "http://openzaak:8000/zaken/api/v1/statussen/22222222-2222-2222-2222-222222222222"; private readonly InMemoryNotificationLog _log = new(); private readonly InMemoryProjectionStore _store = new(); @@ -17,6 +18,10 @@ public sealed class NotificationProjectorTests private static Notification ZaakCreated(string url = ZaakUrl) => new("zaken", "zaak", "create", new Uri(url)); + // A status-set notification: resourceUrl is the status resource, hoofdObject is the zaak it belongs to. + private static Notification StatusSet(string zaakUrl = ZaakUrl, string statusUrl = StatusUrl) + => new("zaken", "status", "create", new Uri(statusUrl), new Uri(zaakUrl)); + [Fact] public async Task creating_a_zaak_writes_one_row_with_status_ingediend() { @@ -62,16 +67,53 @@ public sealed class NotificationProjectorTests [Theory] [InlineData("documenten", "enkelvoudiginformatieobject", "create")] // wrong kanaal + resource [InlineData("documenten", "zaak", "create")] // wrong kanaal only - [InlineData("zaken", "status", "create")] // wrong resource only [InlineData("zaken", "zaak", "update")] // wrong actie [InlineData("zaken", "zaak", "destroy")] // wrong actie - public async Task only_a_zaken_zaak_create_notification_is_projected(string kanaal, string resource, string actie) + [InlineData("zaken", "status", "update")] // a status change we ignore + [InlineData("zaken", "resultaat", "create")] // not a status we project + public async Task an_unrelated_notification_is_not_projected(string kanaal, string resource, string actie) { await Projector().HandleAsync(new Notification(kanaal, resource, actie, new Uri(ZaakUrl))); Assert.Empty(await _store.AllAsync()); } + [Fact] + public async Task setting_a_status_projects_ingeschreven_keyed_on_the_zaak_not_the_status() + { + await Projector().HandleAsync(StatusSet()); + + var entry = Assert.Single(await _store.AllAsync()); + // Keyed on the zaak (hoofdObject), not the status resource URL. + Assert.Equal("11111111-1111-1111-1111-111111111111", entry.Id); + Assert.Equal(RegistrationStatus.Ingeschreven, entry.Status); + } + + [Fact] + public async Task approving_updates_the_existing_zaak_row_from_ingediend_to_ingeschreven() + { + var projector = Projector(); + await projector.HandleAsync(ZaakCreated()); + await projector.HandleAsync(StatusSet()); + + var entry = Assert.Single(await _store.AllAsync()); + Assert.Equal("11111111-1111-1111-1111-111111111111", entry.Id); + Assert.Equal(RegistrationStatus.Ingeschreven, entry.Status); + } + + [Fact] + public async Task rebuild_reproduces_the_approved_status() + { + var projector = Projector(); + await projector.HandleAsync(ZaakCreated()); + await projector.HandleAsync(StatusSet()); + + await projector.RebuildAsync(); + + var entry = Assert.Single(await _store.AllAsync()); + Assert.Equal(RegistrationStatus.Ingeschreven, entry.Status); + } + [Fact] public async Task rebuild_clears_stale_rows_and_repopulates_from_the_notification_log() {