Files
atomic-design-poc/backend/tests/BigRegister.Tests/FeatureFlagTests.cs
T
ehoandClaude Sonnet 5 8560746d15 refactor: strip WP-/RB- ticket refs from backend (RD-19)
The backend half of the sweep RD-18 did for the front end. git blame
holds the provenance and stays correct when the code moves; the
comment names a closed ticket and tells the reader nothing the
sentence around it does not.

public/letter.css and LetterHtml.golden.html change together, because
the renderer inlines the CSS and the golden file snapshots the
result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 21:48:08 +02:00

73 lines
2.8 KiB
C#

using System.Net;
using System.Net.Http.Json;
using BigRegister.Api.Contracts;
using BigRegister.Domain.Features;
using Microsoft.AspNetCore.Mvc.Testing;
namespace BigRegister.Tests;
/// Runtime feature flags — catalog in code, admin-toggled, server-enforced.
public class FeatureFlagTests(TestWebApplicationFactory factory) : IClassFixture<TestWebApplicationFactory>
{
private readonly HttpClient _client = factory.CreateClient();
private HttpRequestMessage Admin(HttpMethod method, string path, object? body = null)
{
var req = new HttpRequestMessage(method, path) { Headers = { { "X-Role", "admin" } } };
if (body is not null) req.Content = JsonContent.Create(body);
return req;
}
[Fact]
public void The_catalog_has_unique_keys()
{
var keys = FeatureFlags.Catalog.Select(f => f.Key).ToList();
Assert.Equal(keys.Count, keys.Distinct().Count());
Assert.All(FeatureFlags.Catalog, f => Assert.False(string.IsNullOrWhiteSpace(f.Key)));
}
[Fact]
public async Task Get_flags_returns_the_catalog()
{
var flags = await _client.GetFromJsonAsync<List<FeatureFlagDto>>("/api/v1/flags");
Assert.Contains(flags!, f => f.Key == FeatureFlags.InschrijvingOpen);
}
[Fact]
public async Task Toggling_is_admin_only_and_an_unknown_key_is_404()
{
// Non-admin (no X-Role → drafter) may not toggle.
var denied = await _client.PutAsJsonAsync(
$"/api/v1/admin/flags/{FeatureFlags.InschrijvingOpen}", new { enabled = false });
Assert.Equal(HttpStatusCode.Forbidden, denied.StatusCode);
// Admin, unknown flag → 404.
var unknown = await _client.SendAsync(Admin(HttpMethod.Put, "/api/v1/admin/flags/does-not-exist", new { enabled = true }));
Assert.Equal(HttpStatusCode.NotFound, unknown.StatusCode);
}
[Fact]
public async Task Closing_inschrijving_blocks_a_registratie_then_reopening_allows_it()
{
try
{
// Off → POST /aanvragen for a registratie is refused.
(await _client.SendAsync(Admin(HttpMethod.Put, $"/api/v1/admin/flags/{FeatureFlags.InschrijvingOpen}", new { enabled = false })))
.EnsureSuccessStatusCode();
var blocked = await _client.PostAsJsonAsync("/api/v1/aanvragen", new { type = "registratie" });
Assert.Equal(HttpStatusCode.Forbidden, blocked.StatusCode);
// On → allowed again.
(await _client.SendAsync(Admin(HttpMethod.Put, $"/api/v1/admin/flags/{FeatureFlags.InschrijvingOpen}", new { enabled = true })))
.EnsureSuccessStatusCode();
var ok = await _client.PostAsJsonAsync("/api/v1/aanvragen", new { type = "registratie" });
Assert.Equal(HttpStatusCode.Created, ok.StatusCode);
}
finally
{
// Leave the flag on (shared DB across this class).
await _client.SendAsync(Admin(HttpMethod.Put, $"/api/v1/admin/flags/{FeatureFlags.InschrijvingOpen}", new { enabled = true }));
}
}
}