BIO-019: GET /stamdata/{table}?peildatum= called DateOnly.Parse
directly, which throws FormatException on anything unparseable — an
unhandled 500 (leaking exception detail in Development) instead of
the 400-with-problem-details every other bad-input check in this file
returns. §3c named backend/Stamdata's 71.7% branch coverage (BL-005)
as the weak spot this bug lived in.
Switched to DateOnly.TryParse; an unparseable value now returns
Results.Problem(detail: ..., statusCode: 400), matching the shape the
upload/change-request endpoints already use. Endpoint doc gained
.ProducesProblem(400), so the OpenAPI doc + generated client were
regenerated and committed in this same diff (RB-09's note records a
prior incident where a response-shape change shipped without this and
the drift went unnoticed).
No FE change needed: libs/beheer's stamdata adapter already funnels
every call through runSubmit, which folds any thrown ApiException
(now including this 400) into a generic Result error — ADR-0001's
"the FE renders the decision" already covers "the server rejected
this input".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
79 lines
3.1 KiB
C#
79 lines
3.1 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using BigRegister.Api.Contracts;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
|
|
namespace BigRegister.Tests;
|
|
|
|
/// <summary>
|
|
/// The stamdata maintenance reads (ADR-0004): admin-only, generic (schema + rows), and the
|
|
/// valid-time peildatum filter. The editor consumes these; the edit itself lands as a PR.
|
|
/// </summary>
|
|
public class StamdataEndpointTests(TestWebApplicationFactory factory) : IClassFixture<TestWebApplicationFactory>
|
|
{
|
|
private readonly HttpClient _client = factory.CreateClient();
|
|
|
|
private HttpRequestMessage Req(HttpMethod method, string path, string? role = null)
|
|
{
|
|
var req = new HttpRequestMessage(method, path);
|
|
if (role is not null) req.Headers.Add("X-Role", role);
|
|
return req;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Stamdata_reads_are_admin_only()
|
|
{
|
|
Assert.Equal(HttpStatusCode.Forbidden, (await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata"))).StatusCode);
|
|
Assert.Equal(HttpStatusCode.Forbidden, (await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata/professions", role: "drafter"))).StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Table_list_exposes_the_reflected_schema()
|
|
{
|
|
var res = await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata", role: "admin"));
|
|
res.EnsureSuccessStatusCode();
|
|
var tables = (await res.Content.ReadFromJsonAsync<List<StamdataTableSummaryDto>>())!;
|
|
var professions = tables.Single(t => t.Id == "professions");
|
|
Assert.True(professions.Temporal);
|
|
Assert.True(professions.Columns[0].IsKey);
|
|
Assert.Equal("program", professions.Columns[0].Name);
|
|
Assert.Contains(professions.Columns, c => c.Name == "geldigVan" && c.Type == "date");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Table_returns_all_rows_without_a_peildatum()
|
|
{
|
|
var res = await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata/professions", role: "admin"));
|
|
res.EnsureSuccessStatusCode();
|
|
var table = (await res.Content.ReadFromJsonAsync<StamdataTableDto>())!;
|
|
Assert.Equal(5, table.Rows.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Peildatum_before_the_seed_windows_hides_every_row()
|
|
{
|
|
// Seed mappings start 2000-01-01; a 1999 peildatum yields none (valid-time filter works).
|
|
var res = await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata/professions?peildatum=1999-01-01", role: "admin"));
|
|
res.EnsureSuccessStatusCode();
|
|
var table = (await res.Content.ReadFromJsonAsync<StamdataTableDto>())!;
|
|
Assert.Empty(table.Rows);
|
|
}
|
|
|
|
/// RB-16/BIO-019: DateOnly.Parse used to throw FormatException on unparseable input,
|
|
/// surfacing as an unhandled 500 instead of the 400-with-problem-details every other
|
|
/// bad-input check in this endpoint file returns.
|
|
[Fact]
|
|
public async Task Unparseable_peildatum_is_400_not_500()
|
|
{
|
|
var res = await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata/professions?peildatum=not-a-date", role: "admin"));
|
|
Assert.Equal(HttpStatusCode.BadRequest, res.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Unknown_table_is_404()
|
|
{
|
|
var res = await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/stamdata/nope", role: "admin"));
|
|
Assert.Equal(HttpStatusCode.NotFound, res.StatusCode);
|
|
}
|
|
}
|