using System.Net.Http.Json;
using BigRegister.Api.Contracts;
using BigRegister.Api.Data;
using BigRegister.Domain.Applications;
using BigRegister.Domain.Authorization;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
namespace BigRegister.Tests;
/// Wraps but returns a DIFFERENT case id than the
/// underlying Aanvraag.Id — reproduces exactly what OpenZaakZaakSource does in
/// production (the FE-facing case id from ListCases is the ZGW zaak's own uuid, not
/// ApplicationStore's primary key) without needing a live OpenZaak, so the besluit
/// endpoint's Referentie-based resolution (the fix below) gets coverage on every push.
file sealed class IdMismatchZaakSource : IZaakSource
{
private readonly LocalZaakSource inner = new();
private static ApplicationSummaryDto Rekey(ApplicationSummaryDto dto) => dto with { Id = $"zaak-{dto.Id}" };
public IReadOnlyList ListCases(DateTimeOffset now) =>
inner.ListCases(now).Select(Rekey).ToList();
public IReadOnlyList ListMyCases(ZorgverlenerCaller caller, DateTimeOffset now) =>
inner.ListMyCases(caller, now).Select(Rekey).ToList();
public (string Referentie, AanvraagStatusDto Status, string? ZaakUrl) CreateZaak(
Aanvraag aanvraag, DateTimeOffset now, CallerIdentity caller) => inner.CreateZaak(aanvraag, now, caller);
public void RecordBesluit(Aanvraag aanvraag, Besluit besluit, string? toelichting, DateTimeOffset now, CallerIdentity caller) =>
inner.RecordBesluit(aanvraag, besluit, toelichting, now, caller);
}
///
/// Regression for a real, live-repro'd bug: recording a besluit from the behandelportal always
/// 404'd against a real OpenZaak. Root cause — POST /beoordeling/{id}/besluit looked
/// id up directly in ApplicationStore (its own primary key), but id is
/// whatever IZaakSource.ListCases handed the FE; under OpenZaakZaakSource that's
/// the ZGW zaak's own uuid, a different value entirely. Fixed by resolving the case through
/// the same ListCases seak the GET sibling () already uses,
/// then to the local Aanvraag via its Referentie (ApplicationStore.GetByReferentie)
/// — the one identifier stable across both sources.
/// reproduces the id divergence without a live OpenZaak.
///
public class BeoordelingIdMismatchTests
{
private static WebApplicationFactory Factory()
{
var dbPath = Path.Combine(Path.GetTempPath(), $"bigregister-id-mismatch-{Guid.NewGuid():N}.db");
return new WebApplicationFactory().WithWebHostBuilder(builder => builder
.UseSetting("ConnectionStrings:AppDb", $"Data Source={dbPath}")
.ConfigureTestServices(services => services.AddSingleton()));
}
private static HttpRequestMessage Behandelaar(HttpMethod method, string path, object? body = null)
{
var req = new HttpRequestMessage(method, path);
req.Headers.Add("X-Medewerker", "medewerker-1");
if (body is not null) req.Content = JsonContent.Create(body);
return req;
}
[Fact]
public async Task Besluit_resolves_by_referentie_when_the_case_id_differs_from_the_local_aanvraag_id()
{
using var factory = Factory();
using var client = factory.CreateClient();
var created = await client.PostAsJsonAsync("/api/v1/applications", new { type = "registratie" });
var app = (await created.Content.ReadFromJsonAsync())!;
var submit = await client.PostAsJsonAsync($"/api/v1/applications/{app.Id}/submit", new { diplomaHerkomst = "handmatig" });
submit.EnsureSuccessStatusCode();
var werkvoorraad = await client.SendAsync(Behandelaar(HttpMethod.Get, "/api/v1/werkvoorraad"));
var items = (await werkvoorraad.Content.ReadFromJsonAsync>())!;
var caseId = Assert.Single(items).Id;
// Sanity: the id divergence this test exists for is real, not accidentally absent.
Assert.NotEqual(app.Id, caseId);
var res = await client.SendAsync(Behandelaar(HttpMethod.Post, $"/api/v1/beoordeling/{caseId}/besluit",
new { besluit = "Afwijzen", toelichting = "onvolledig" }));
res.EnsureSuccessStatusCode();
var body = (await res.Content.ReadFromJsonAsync())!;
Assert.Equal("Afgewezen", body.Status.Tag);
}
}