Three seams WP-71 documented but left unguarded.
Deletes the FE's isHerregistratieEligible and isStatusConsistent — both
uncalled, the first dead by its own doc-comment. Their tests used fixtures
completely disjoint from the backend's (the backend even had an exact-window
boundary case the FE lacked), so the two sides could diverge indefinitely
without failing anything. CLAUDE.md's policy of keeping server-owned rules
as FE "reference impls" is what kept them alive, so it is amended: the FE may
mirror a server-supplied value for instant feedback, never reimplement the
algorithm. registration.policy.ts keeps its three live exports.
check-seam.sh now also guards the Besluit tag list — the C# enum and the TS
BESLUIT_TAGS array are identical ordered name lists with nothing linking
them, and Enum.TryParse fails at request time rather than build time. Anchored
on the full declaration so it avoids the "greps all matches" trap WP-69 hit.
The phone-format divergence turned out to be real, not latent as recorded:
the backend returned 422 for +31612345678 and (06) 12345678, both of which
the FE's own parseTelefoonnummer accepts. A grep check would have compared
the shared ^0\d{9}$ regex and reported all clear — the difference was in
stripping. RejectPhoneChange now strips what the FE strips, pinned by a
contract test.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
55 lines
2.6 KiB
C#
55 lines
2.6 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using BigRegister.Api.Contracts;
|
|
|
|
namespace BigRegister.Tests.Acceptance;
|
|
|
|
/// <summary>
|
|
/// Contract test for the FE/BE seam on phone-number stripping (WP-75). Both sides share
|
|
/// the same format regex (<c>^0\d{9}$</c>) but, until this test, diverged on what they
|
|
/// strip before checking it: the FE's <c>parseTelefoonnummer</c>
|
|
/// (registratie/domain/value-objects/telefoonnummer.ts) also drops parentheses and maps a
|
|
/// leading <c>+31</c> to a leading <c>0</c>; <see cref="BigRegister.Domain.Submissions.SubmissionRules.RejectPhoneChange"/>
|
|
/// used to strip only spaces and dashes. This was latent, not live — the FE always sends
|
|
/// its already-normalised value over the wire — but a crafted/future caller posting a raw,
|
|
/// FE-valid number would hit a backend that disagrees with the FE about what's valid. The
|
|
/// backend is the authority (ADR-0001), so it must agree with the FE on every FE-valid input.
|
|
/// </summary>
|
|
public class PhoneFormatContractTests(TestWebApplicationFactory factory) : IClassFixture<TestWebApplicationFactory>
|
|
{
|
|
private readonly HttpClient _client = factory.CreateClient();
|
|
|
|
private Task<HttpResponseMessage> PostChangeRequest(string telefoon) =>
|
|
_client.PostAsJsonAsync("/api/v1/change-requests", new ChangeRequestRequest(telefoon));
|
|
|
|
[Fact]
|
|
public async Task A_leading_plus31_is_accepted_like_the_frontends_normalised_form()
|
|
{
|
|
// Given a phone number in international form — parseTelefoonnummer maps a leading
|
|
// "+31" to "0" and accepts it (it becomes "0612345678", 10 digits starting 0).
|
|
|
|
// When it is posted to the backend exactly as the user typed it (not FE-normalised)...
|
|
var res = await PostChangeRequest("+31612345678");
|
|
|
|
// Then the backend must agree it's valid, not reject it as malformed.
|
|
res.EnsureSuccessStatusCode();
|
|
var body = (await res.Content.ReadFromJsonAsync<ReferentieResponse>())!;
|
|
Assert.NotNull(body.Referentie);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Parentheses_around_the_area_code_are_accepted_like_the_frontend()
|
|
{
|
|
// Given a phone number with the area code in parentheses — parseTelefoonnummer strips
|
|
// "()" along with spaces/dashes and accepts it (it becomes "0612345678").
|
|
|
|
// When it is posted to the backend exactly as the user typed it...
|
|
var res = await PostChangeRequest("(06) 12345678");
|
|
|
|
// Then the backend must agree it's valid, not reject it as malformed.
|
|
res.EnsureSuccessStatusCode();
|
|
var body = (await res.Content.ReadFromJsonAsync<ReferentieResponse>())!;
|
|
Assert.NotNull(body.Referentie);
|
|
}
|
|
}
|