The wire said Application, the domain said Aanvraag — one aggregate with two names at every hop. Rename the backend DTOs and the /applications route to /aanvragen, regenerate the typed client, and rename the frontend adapter/store to match. Renamed: ApplicationSummaryDto/DetailDto, CreateApplicationRequest, SubmitApplicationRequest/Response → Aanvraag* equivalents; ApplicationsAdapter/Store → AanvragenAdapter/Store; applications.adapter.ts/applications.store.ts → aanvragen.*. Left untouched: the admin Case/Zaak vocabulary (/admin/cases, AdminCasesStore) — a separate read model, not part of this rename; the internal BigRegister.Domain.Applications namespace and the Applications EF table (renaming those needs a new EF migration, out of scope here). Part of the dashboard-readability refactor (see the approved plan). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
76 lines
2.7 KiB
C#
76 lines
2.7 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using BigRegister.Api.Contracts;
|
|
using BigRegister.Api.Data;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
|
|
namespace BigRegister.Tests;
|
|
|
|
/// WP-36: admin cross-owner case list + admin delete, gated by `cases:manage`.
|
|
public class AdminCasesTests(TestWebApplicationFactory factory) : IClassFixture<TestWebApplicationFactory>
|
|
{
|
|
private readonly HttpClient _client = factory.CreateClient();
|
|
|
|
private HttpRequestMessage Admin(HttpMethod method, string path)
|
|
{
|
|
var req = new HttpRequestMessage(method, path);
|
|
req.Headers.Add("X-Role", "admin");
|
|
return req;
|
|
}
|
|
|
|
private async Task<AanvraagDetailDto> Create(string type)
|
|
{
|
|
var res = await _client.PostAsJsonAsync("/api/v1/aanvragen", new { type });
|
|
Assert.Equal(HttpStatusCode.Created, res.StatusCode);
|
|
return (await res.Content.ReadFromJsonAsync<AanvraagDetailDto>())!;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Admin_lists_every_case_with_its_owner()
|
|
{
|
|
var a = await Create("herregistratie");
|
|
try
|
|
{
|
|
var list = await _client.SendAsync(Admin(HttpMethod.Get, "/api/v1/admin/cases"));
|
|
list.EnsureSuccessStatusCode();
|
|
var cases = (await list.Content.ReadFromJsonAsync<List<AanvraagSummaryDto>>())!;
|
|
var mine = cases.Single(x => x.Id == a.Id);
|
|
// RB-03/BIO-003: the owner is carried, but masked — it is a BSN, and this list is
|
|
// read by someone who is not the subject.
|
|
Assert.Equal("******782", mine.Owner);
|
|
Assert.DoesNotContain(DocumentStore.DemoOwner, mine.Owner);
|
|
}
|
|
finally
|
|
{
|
|
await _client.SendAsync(Admin(HttpMethod.Delete, $"/api/v1/admin/cases/{a.Id}"));
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Non_admin_is_forbidden()
|
|
{
|
|
Assert.Equal(HttpStatusCode.Forbidden, (await _client.GetAsync("/api/v1/admin/cases")).StatusCode);
|
|
Assert.Equal(HttpStatusCode.Forbidden, (await _client.DeleteAsync("/api/v1/admin/cases/anything")).StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Admin_can_delete_a_submitted_case()
|
|
{
|
|
var a = await Create("registratie");
|
|
(await _client.PostAsJsonAsync($"/api/v1/aanvragen/{a.Id}/submit", new { diplomaHerkomst = "duo" }))
|
|
.EnsureSuccessStatusCode();
|
|
|
|
// The user-facing DELETE refuses a submitted case (409); admin delete removes it.
|
|
var del = await _client.SendAsync(Admin(HttpMethod.Delete, $"/api/v1/admin/cases/{a.Id}"));
|
|
Assert.Equal(HttpStatusCode.NoContent, del.StatusCode);
|
|
Assert.Equal(HttpStatusCode.NotFound, (await _client.GetAsync($"/api/v1/aanvragen/{a.Id}")).StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Deleting_a_missing_case_is_not_found()
|
|
{
|
|
var del = await _client.SendAsync(Admin(HttpMethod.Delete, "/api/v1/admin/cases/does-not-exist"));
|
|
Assert.Equal(HttpStatusCode.NotFound, del.StatusCode);
|
|
}
|
|
}
|