using System.Text.RegularExpressions; using BigRegister.Api.Contracts; using BigRegister.Api.Data; using BigRegister.Domain.Letters; namespace BigRegister.Tests; /// /// WP-25's fence against drift between the backend renderer and the FE letter /// canvas: a golden-file snapshot of a fixed brief + template, and a class-parity /// check that every `letter`-prefixed class the renderer emits exists in the /// shared `public/letter.css` contract. Neither test launches a browser. /// public class LetterHtmlTests { private static BriefEntity FixtureBrief() => new() { BriefId = "golden-brief-1", Owner = "golden", Beroep = "arts", TemplateId = "besluit-arts", DrafterId = BriefStore.DrafterId, Placeholders = new[] { new PlaceholderDefDto("naam_zorgverlener", "Naam zorgverlener", true), new PlaceholderDefDto("datum", "Datum", true), new PlaceholderDefDto("reden_besluit", "Reden besluit", false), }, Sections = new() { new("aanhef", "Aanhef", true, new List { new("freeText", "aanhef-1", new RichTextBlockDto(new[] { new ParagraphDto(new[] { new RichTextNodeDto("text", Text: "Geachte heer/mevrouw "), new RichTextNodeDto("placeholder", Key: "naam_zorgverlener"), new RichTextNodeDto("text", Text: ","), }), })), }, Locked: true), new("kern", "Kern van het besluit", true, new List { new("freeText", "kern-1", new RichTextBlockDto(new[] { new ParagraphDto(new[] { new RichTextNodeDto("text", Text: "Op ") }), new ParagraphDto(new RichTextNodeDto[] { new("text", Text: "Eerste punt: "), new("placeholder", Key: "reden_besluit"), }, List: "bullet"), new ParagraphDto(new RichTextNodeDto[] { new("text", Text: "Tweede punt"), }, List: "bullet"), })), }), new("slot", "Slot", false, new List { new("freeText", "slot-1", new RichTextBlockDto(new[] { new ParagraphDto(new[] { new RichTextNodeDto("text", Text: "Met vriendelijke groet,") }), })), }, Locked: true), }, Status = new BriefStatusDto("draft"), }; private static readonly OrgTemplateDto Template = new( "cibg-registers", "BIG-register", "Retouradres: Postbus 00000, 2500 AA Den Haag", LogoDocumentId: null, "BIG-register · Postbus 00000, 2500 AA Den Haag · 070 000 00 00 · info@voorbeeld.example", "Dit is een gegenereerd voorbeelddocument uit de register-reference PoC. Alle gegevens zijn fictief.", "A. de Vries", "Hoofd Registratie, BIG-register", "Met vriendelijke groet,", new MarginsDto(25, 20, 20, 25), Version: 1); private const string At = "2026-07-05T12:00:00.0000000+00:00"; private static readonly string GoldenPath = Path.Combine(AppContext.BaseDirectory, "LetterHtml.golden.html"); [Fact] public void Render_matches_the_golden_file() { var html = LetterHtml.Render(FixtureBrief(), Template, At, watermark: true); var golden = File.ReadAllText(GoldenPath); Assert.Equal(golden, html); } [Fact] public void Every_letter_prefixed_class_exists_in_letter_css() { var html = LetterHtml.Render(FixtureBrief(), Template, At, watermark: true); var classes = Regex.Matches(html, "class=\"([^\"]+)\"") .SelectMany(m => m.Groups[1].Value.Split(' ')) .Where(c => c.StartsWith("letter")) .Distinct(); Assert.NotEmpty(classes); Assert.All(classes, c => Assert.Contains($".{c}", LetterHtml.StyleSheet)); } }