feat(behandelportal): WP-64 werkvoorraad (queue) screen
CI / changes (pull_request) Successful in 15s
CI / lint (pull_request) Successful in 57s
CI / frontend (pull_request) Successful in 2m36s
CI / storybook-a11y (pull_request) Failing after 3m14s
CI / backend (pull_request) Successful in 2m1s
CI / semgrep (pull_request) Successful in 1m10s
CI / e2e (pull_request) Successful in 3m3s
CI / api-client-drift (pull_request) Successful in 2m1s
CI / changes (pull_request) Successful in 15s
CI / lint (pull_request) Successful in 57s
CI / frontend (pull_request) Successful in 2m36s
CI / storybook-a11y (pull_request) Failing after 3m14s
CI / backend (pull_request) Successful in 2m1s
CI / semgrep (pull_request) Successful in 1m10s
CI / e2e (pull_request) Successful in 3m3s
CI / api-client-drift (pull_request) Successful in 2m1s
New GET /werkvoorraad endpoint lists aanvragen still open (Ingediend/InBehandeling), gated by the medewerker capability (CanBeoordelen) rather than the admin role — reuses the existing ApplicationSummaryDto, no new DTO. GET /me now surfaces aanvraag:beoordelen for a behandelaar so the FE can gate with the same AccessStore/capabilityGuard idiom every other page uses. FE: a behandeling domain type deliberately narrower than ssp's full AanvraagStatus union (only the two open tags — illegal states unrepresentable), composed into a werkvoorraad-list organism from existing shared/ui molecules. Replaces WP-61's scaffold placeholder as the app's real landing page. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using BigRegister.Api.Contracts;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
|
||||
namespace BigRegister.Tests;
|
||||
|
||||
/// WP-64: the behandelportal's queue of aanvragen needing treatment, gated by the
|
||||
/// medewerker capability `CanBeoordelen` (WP-62) — not the admin role.
|
||||
public class WerkvoorraadTests(TestWebApplicationFactory factory) : IClassFixture<TestWebApplicationFactory>
|
||||
{
|
||||
private readonly HttpClient _client = factory.CreateClient();
|
||||
|
||||
private HttpRequestMessage AsBehandelaar(string path)
|
||||
{
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, path);
|
||||
req.Headers.Add("X-Medewerker", "medewerker-1");
|
||||
return req;
|
||||
}
|
||||
|
||||
private async Task<ApplicationDetailDto> CreateAndSubmitHerregistratie()
|
||||
{
|
||||
var created = await _client.PostAsJsonAsync("/api/v1/applications", new { type = "herregistratie" });
|
||||
var a = (await created.Content.ReadFromJsonAsync<ApplicationDetailDto>())!;
|
||||
(await _client.PostAsJsonAsync($"/api/v1/applications/{a.Id}/submit", new { uren = 200 }))
|
||||
.EnsureSuccessStatusCode();
|
||||
return a;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Behandelaar_sees_submitted_cases_in_the_queue()
|
||||
{
|
||||
var a = await CreateAndSubmitHerregistratie();
|
||||
try
|
||||
{
|
||||
var res = await _client.SendAsync(AsBehandelaar("/api/v1/werkvoorraad"));
|
||||
res.EnsureSuccessStatusCode();
|
||||
var queue = (await res.Content.ReadFromJsonAsync<List<ApplicationSummaryDto>>())!;
|
||||
var mine = queue.Single(x => x.Id == a.Id);
|
||||
Assert.Equal("InBehandeling", mine.Status.Tag);
|
||||
Assert.False(string.IsNullOrEmpty(mine.Owner)); // cross-owner, like /admin/cases
|
||||
}
|
||||
finally
|
||||
{
|
||||
await _client.SendAsync(new HttpRequestMessage(HttpMethod.Delete, $"/api/v1/admin/cases/{a.Id}")
|
||||
{
|
||||
Headers = { { "X-Role", "admin" } },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Queue_excludes_concepts()
|
||||
{
|
||||
var created = await _client.PostAsJsonAsync("/api/v1/applications", new { type = "herregistratie" });
|
||||
var a = (await created.Content.ReadFromJsonAsync<ApplicationDetailDto>())!;
|
||||
try
|
||||
{
|
||||
var res = await _client.SendAsync(AsBehandelaar("/api/v1/werkvoorraad"));
|
||||
res.EnsureSuccessStatusCode();
|
||||
var queue = (await res.Content.ReadFromJsonAsync<List<ApplicationSummaryDto>>())!;
|
||||
Assert.DoesNotContain(queue, x => x.Id == a.Id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await _client.DeleteAsync($"/api/v1/applications/{a.Id}");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Zorgverlener_is_forbidden_even_with_admin_role()
|
||||
{
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, "/api/v1/werkvoorraad");
|
||||
req.Headers.Add("X-Role", "admin"); // admin role, but no X-Medewerker — still a zorgverlener
|
||||
Assert.Equal(HttpStatusCode.Forbidden, (await _client.SendAsync(req)).StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Medewerker_without_behandelaar_rol_is_forbidden()
|
||||
{
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, "/api/v1/werkvoorraad");
|
||||
req.Headers.Add("X-Medewerker", "medewerker-2");
|
||||
req.Headers.Add("X-Rollen", "geen");
|
||||
Assert.Equal(HttpStatusCode.Forbidden, (await _client.SendAsync(req)).StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Me_reports_the_capability_only_for_a_behandelaar()
|
||||
{
|
||||
var behandelaar = new HttpRequestMessage(HttpMethod.Get, "/api/v1/me");
|
||||
behandelaar.Headers.Add("X-Medewerker", "medewerker-1");
|
||||
var caps = (await (await _client.SendAsync(behandelaar)).Content.ReadFromJsonAsync<MeDto>())!;
|
||||
Assert.Contains("aanvraag:beoordelen", caps.Capabilities);
|
||||
|
||||
var zorgverlener = (await (await _client.GetAsync("/api/v1/me")).Content.ReadFromJsonAsync<MeDto>())!;
|
||||
Assert.DoesNotContain("aanvraag:beoordelen", zorgverlener.Capabilities);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user