test(acl): submit writes an INGEDIEND record, and records are readable back (refs #153)

Ports and failing tests for the ACL half of S-19b-2, ahead of the implementation.

Once the projection is sourced from Objecten (ADR-0028's stated direction), a submitted
registration has to exist in the register the moment the zaak is opened — otherwise
re-sourcing silently drops every INGEDIEND row, since today only approval writes a record.
So `OpenZaakAsync` gains a second write, and approval upserts that same record to
INGESCHREVEN.

The subscriber gets only an object URL on an `objecten` notification (the payload carries no
record data) and may not read Objecten itself (§8.1), so `IRegisterRecordGateway` gains a
read and `AclService` exposes it.

Red:
- AclService does not yet write on open → the record assertion fails on an empty list.
- ObjectenGateway.GetAsync is a shell throwing NotImplementedException; its tests pin the
  contract: fetch the object URL directly (no objecttype resolution, no search), the CRS
  header a geo API requires, static Token auth, and a 404 read as "nothing to project"
  rather than an error (§8.6).
This commit is contained in:
not
2026-08-28 12:28:01 +02:00
parent 2125fb0cfd
commit 06c0444859
6 changed files with 120 additions and 0 deletions
+56
View File
@@ -79,11 +79,21 @@ public class AclServiceTests
{
public readonly List<RegisterRecord> Upserted = [];
public RegisterRecord? Stored;
public Uri? ReadFrom;
public Task UpsertAsync(RegisterRecord record, CancellationToken ct = default)
{
Upserted.Add(record);
return Task.CompletedTask;
}
public Task<RegisterRecord?> GetAsync(Uri objectUrl, CancellationToken ct = default)
{
ReadFrom = objectUrl;
return Task.FromResult(Stored);
}
}
private static AclDefaults Defaults() => new()
@@ -130,6 +140,52 @@ public class AclServiceTests
Assert.Equal("reg-77", req.Identificatie);
}
[Fact]
public async Task Opening_a_zaak_also_writes_an_ingediend_register_record(/* S-19b-2 */)
{
var gateway = new FakeGateway();
var register = new FakeRegisterRecordGateway();
var service = ServiceWith(gateway, register, Defaults(), new DateOnly(2026, 6, 4));
await service.OpenZaakAsync(new DomainRegistration("123456782", "reg-77"));
// The register — not ZGW — is what the read projection is sourced from (ADR-0028), so a
// submitted registration has to exist there the moment the zaak is opened, not only on
// approval. Approval upserts this same record to INGESCHREVEN.
var record = Assert.Single(register.Upserted);
Assert.Equal("abc", record.Id);
Assert.Equal("INGEDIEND", record.Status);
// The reference comes from the registration itself — no ZGW read-back needed on this path.
Assert.Equal("reg-77", record.Reference);
}
[Fact]
public async Task Reading_a_register_record_goes_through_the_objecten_gateway(/* S-19b-2 */)
{
var gateway = new FakeGateway();
var register = new FakeRegisterRecordGateway { Stored = new RegisterRecord("abc", "INGESCHREVEN", "reg-77") };
var service = ServiceWith(gateway, register, Defaults(), new DateOnly(2026, 6, 4));
var objectUrl = new Uri("http://objecten.local:8000/api/v2/objects/9de4a2ca");
var record = await service.GetRegisterRecordAsync(objectUrl);
Assert.Equal(objectUrl, register.ReadFrom);
Assert.Equal("abc", record!.Id);
Assert.Equal("INGESCHREVEN", record.Status);
Assert.Equal("reg-77", record.Reference);
}
[Fact]
public async Task Reading_a_register_record_from_a_null_url_is_rejected(/* S-19b-2 */)
{
var gateway = new FakeGateway();
var register = new FakeRegisterRecordGateway();
var service = ServiceWith(gateway, register, Defaults(), new DateOnly(2026, 6, 4));
await Assert.ThrowsAsync<ArgumentNullException>(() => service.GetRegisterRecordAsync(null!));
Assert.Null(register.ReadFrom);
}
[Fact]
public async Task Opening_a_zaak_reflects_a_default_fill_update(/* S-15b */)
{