feat(zgw): docker OpenZaak integration-test harness (WP-54)

Opt-in docker-compose (postgres+redis+OpenZaak, no celery/nginx) +
bootstrap-catalogus.sh seed a real OpenZaak instance; OpenZaakIntegrationTests
(Category=Integration, excluded from default dotnet test/CI) proves the ZGW
seam against it for the first time. That live run caught a real bug:
ZgwHttpClient never sent Content-Crs/Accept-Crs headers, so every write would
412 against a spec-compliant OpenZaak — fixed alongside the harness.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-30 09:08:35 +02:00
co-authored by Claude Sonnet 5
parent 73172510ea
commit 5cb3e1a9f0
12 changed files with 471 additions and 15 deletions
@@ -0,0 +1,56 @@
using System.Net.Http.Json;
using BigRegister.Api.Contracts;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
namespace BigRegister.Tests;
/// <summary>
/// WP-54: the one test that proves the BFF actually talks to a REAL OpenZaak — auth accepted,
/// real response shapes, real pagination/zaaktype resolution — rather than the stub
/// HttpMessageHandler every other Zgw test (<see cref="ZgwZaakMapperTests"/>,
/// <see cref="OpenZaakZaakSourceTests"/>) uses. Requires the harness in <c>backend/openzaak/</c>
/// to be up and seeded first (see its README); tagged Category=Integration so it's excluded
/// from the default `dotnet test` run and from CI (`ci.yml`, `scripts/ci-local.sh` both filter
/// it out) — nobody without a live OpenZaak should see it fail.
///
/// Not an <see cref="IClassFixture{TFixture}"/> off <see cref="TestWebApplicationFactory"/>:
/// that fixture hardcodes <c>Zgw:Enabled=false</c> (offline default) for every other test class,
/// so this one builds its own <see cref="WebApplicationFactory{TEntryPoint}"/> layering the
/// harness's URLs/credentials (matching <c>backend/openzaak/setup_configuration/data.yaml</c>
/// and <c>bootstrap-catalogus.sh</c>) on top.
/// </summary>
[Trait("Category", "Integration")]
public class OpenZaakIntegrationTests
{
private static WebApplicationFactory<Program> Factory()
{
var dbPath = Path.Combine(Path.GetTempPath(), $"bigregister-oz-integration-{Guid.NewGuid():N}.db");
return new WebApplicationFactory<Program>().WithWebHostBuilder(builder => builder
.UseSetting("ConnectionStrings:AppDb", $"Data Source={dbPath}")
.UseSetting("Zgw:Enabled", "true")
.UseSetting("Zgw:ZrcBaseUrl", "http://localhost:8000/zaken/api/v1")
.UseSetting("Zgw:ZtcBaseUrl", "http://localhost:8000/catalogi/api/v1")
.UseSetting("Zgw:ClientId", "bigregister-test")
.UseSetting("Zgw:Secret", "bigregister-test-secret")
.UseSetting("Zgw:UserId", "bigregister-test")
.UseSetting("Zgw:UserRepresentation", "WP-54 integration test"));
}
[Fact]
public async Task Admin_cases_returns_the_seeded_zaak_mapped_through_real_HTTP_and_JWT()
{
using var factory = Factory();
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-Role", "admin"); // CasesAdmin gate (cases:manage)
var cases = await client.GetFromJsonAsync<List<ApplicationSummaryDto>>("/api/v1/admin/cases");
Assert.NotNull(cases);
// bootstrap-catalogus.sh seeds exactly one zaak, identificatie BIG-2026-000123, under a
// zaaktype whose omschrijving is "Herregistratie arts" — see backend/openzaak/README.md.
var seeded = Assert.Single(cases!, c => c.Status.Referentie == "BIG-2026-000123");
Assert.Equal("Herregistratie arts", seeded.Type);
Assert.Equal("InBehandeling", seeded.Status.Tag);
}
}