Compare commits

...
Author SHA1 Message Date
notandClaude Opus 4.8 5fdfd4f843 fix(verify): attach stdin (-i) so the zaak-status read-back runs (refs #106)
CI / lint (pull_request) Successful in 1m22s
CI / build (pull_request) Successful in 1m4s
CI / unit (pull_request) Successful in 1m14s
CI / frontend (pull_request) Successful in 2m41s
CI / mutation (pull_request) Successful in 5m43s
CI / verify-stack (pull_request) Successful in 7m54s
The cancellation reaches OpenZaak correctly (Geannuleerd status_created), but
the verify read-back ran 'docker run python:3-slim python -' without -i, so the
heredoc never reached the container's stdin and the script was empty — the check
always saw an empty status. Add -i so the read actually queries OpenZaak.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 15:37:29 +02:00
notandClaude Opus 4.8 e5eef71a57 test(acl): kill cancellation-path mutants to clear the mutation ratchet (refs #106)
CI / lint (pull_request) Successful in 1m29s
CI / build (pull_request) Successful in 1m3s
CI / unit (pull_request) Successful in 1m19s
CI / frontend (pull_request) Successful in 5m12s
CI / mutation (pull_request) Successful in 5m26s
CI / verify-stack (pull_request) Failing after 6m27s
The new SetZaakToCancellationStatusAsync added surviving mutants (uncovered
null-guards and the failure-action messages) that dropped the ACL mutation
score below the 90% break threshold. Add null-argument and rejected-POST tests
for the cancellation path; score back to 93.46%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 15:13:36 +02:00
2 changed files with 52 additions and 3 deletions
+2 -1
View File
@@ -364,7 +364,8 @@ zaak_url_v="$(printf '%s' "$body" | grep -oiE 'http://[^"]*/zaken/api/v1/zaken/[
echo ">> confirming the zaak $zaak_url_v reached the Geannuleerd status in OpenZaak"
read_zaak_status() {
docker run --rm --network "$net" \
# -i so the heredoc reaches `python -` on the container's stdin (without it the script is empty).
docker run --rm -i --network "$net" \
-e OZ_CLIENT_ID="${OZ_CLIENT_ID:-big-reference-seed}" \
-e OZ_SECRET="${OZ_SECRET:-insecure-dev-secret-change-me}" \
python:3-slim python - "$1" <<'PY'
+50 -2
View File
@@ -310,14 +310,12 @@ public class OpenZaakGatewayTests
Assert.Contains("\"zaak\":\"" + ZaakUrl + "\"", resultaat.Body);
// The cancellation resultaat (Vervallen) is chosen by name — not the approval one (Geregistreerd).
Assert.Contains("\"resultaattype\":\"http://openzaak/catalogi/api/v1/resultaattypen/vervallen\"", resultaat.Body);
Assert.True(resultaat.Length > 0);
var status = rec.Sent("/statussen");
Assert.Contains("\"zaak\":\"" + ZaakUrl + "\"", status.Body);
// The Geannuleerd statustype is chosen by name — not the Afgehandeld eindstatus (approval).
Assert.Contains("\"statustype\":\"http://openzaak/catalogi/api/v1/statustypen/geannuleerd\"", status.Body);
Assert.Contains("\"datumStatusGezet\":\"2026-06-04T00:00:00Z\"", status.Body);
Assert.True(status.Length > 0);
}
[Fact]
@@ -336,6 +334,56 @@ public class OpenZaakGatewayTests
Assert.Contains("Geannuleerd", ex.Message);
}
[Fact]
public async Task Cancelling_rejects_a_null_zaak_without_calling_openzaak()
{
var handler = new StubHandler(_ => throw new InvalidOperationException("should not be sent"));
await Assert.ThrowsAsync<ArgumentNullException>(() =>
Gateway(handler).SetZaakToCancellationStatusAsync(null!, Zaaktype, new DateOnly(2026, 6, 4)));
}
[Fact]
public async Task Cancelling_rejects_a_null_zaaktype_without_calling_openzaak()
{
var handler = new StubHandler(_ => throw new InvalidOperationException("should not be sent"));
await Assert.ThrowsAsync<ArgumentNullException>(() =>
Gateway(handler).SetZaakToCancellationStatusAsync(new Uri(ZaakUrl), null!, new DateOnly(2026, 6, 4)));
}
[Fact]
public async Task Cancelling_surfaces_the_failure_when_recording_the_resultaat_is_rejected()
{
var rec = new Recorder();
var ex = await Assert.ThrowsAsync<HttpRequestException>(() =>
Gateway(ApprovalStub(rec, new OzRoutes
{
StatustypenJson = CancellationStatustypenJson,
ResultaattypenJson = CancellationResultaattypenJson,
ResultaatPostStatus = HttpStatusCode.BadRequest,
})).SetZaakToCancellationStatusAsync(new Uri(ZaakUrl), Zaaktype, new DateOnly(2026, 6, 4)));
Assert.Contains("cancellation resultaat", ex.Message);
// It fails on the resultaat, before it ever posts the status.
Assert.Equal(-1, rec.IndexOf("/statussen"));
}
[Fact]
public async Task Cancelling_surfaces_the_failure_when_recording_the_status_is_rejected()
{
var rec = new Recorder();
var ex = await Assert.ThrowsAsync<HttpRequestException>(() =>
Gateway(ApprovalStub(rec, new OzRoutes
{
StatustypenJson = CancellationStatustypenJson,
ResultaattypenJson = CancellationResultaattypenJson,
StatusPostStatus = HttpStatusCode.BadRequest,
})).SetZaakToCancellationStatusAsync(new Uri(ZaakUrl), Zaaktype, new DateOnly(2026, 6, 4)));
Assert.Contains("cancellation status", ex.Message);
}
[Fact]
public async Task Approving_falls_back_to_the_highest_volgnummer_when_no_eindstatus_is_flagged()
{