using System.Text.RegularExpressions; using Omika.App.Navigation; using Omika.Core.Observability; namespace Omika.Tests.Observability; /// /// T18 (§71/§72) : le mapping AppPage → ScreenCode est total, stable, au format /// UPPER_SNAKE_CASE ASCII, sans identifiant métier, sans nom technique de Page/ViewModel. /// public partial class DiagnosticScreenMappingTests { [Fact] public void Resolve_EveryAppPage_HasScreenCode() { foreach (AppPage page in Enum.GetValues()) { Assert.True( DiagnosticScreenMapping.Resolve(page) is not null, $"AppPage.{page} n'a pas de ScreenCode : le mapping doit être TOTAL sur l'énumération."); } } [Fact] public void Resolve_ProducesCatalogValues() { var catalog = new HashSet(DiagnosticScreenCodes.All, StringComparer.Ordinal); foreach (AppPage page in Enum.GetValues()) { string code = DiagnosticScreenMapping.Resolve(page)!; Assert.Contains(code, catalog); } } [Fact] public void Resolve_Agenda_ReturnsAgenda() { Assert.Equal(DiagnosticScreenCodes.Agenda, DiagnosticScreenMapping.Resolve(AppPage.Home)); } [Fact] public void Resolve_SiteDetail_ReturnsSiteDetail() { Assert.Equal(DiagnosticScreenCodes.SiteDetail, DiagnosticScreenMapping.Resolve(AppPage.SiteDetail)); } [Fact] public void Resolve_InterventionSearch_ReturnsInterventionSearch() { Assert.Equal(DiagnosticScreenCodes.InterventionSearch, DiagnosticScreenMapping.Resolve(AppPage.Interventions)); } [Fact] public void ScreenCodes_AreUppercaseSnakeCaseAscii_WithoutIds() { var regex = UppercaseSnake(); foreach (string code in DiagnosticScreenCodes.All) { Assert.Matches(regex, code); // §72 : aucun ID métier dynamique (site/rendez-vous/intervention/user/GUID). Assert.DoesNotContain('-', code); // pas de GUID Assert.DoesNotContain(code, char.IsDigit); // pas de numéro d'ID Assert.DoesNotContain(code, char.IsLower); // pas de casse libre } } [GeneratedRegex("^[A-Z][A-Z0-9_]*$")] private static partial Regex UppercaseSnake(); }