using Omika.App.Diagnostics; using Omika.App.Navigation; using Omika.Core.Observability; using Omika.Core.Observability.Diagnostic; namespace Omika.Tests.Observability; /// /// T18 (§73/§74/§75/§77) : une navigation logique génère EXACTEMENT un ScreenView ; /// le retour = nouvelle vue ; le refresh/même page ne multiplie pas les événements ; /// l'écran initial est émis une fois. L'émission est centralisée dans /// (jamais par ViewModel). /// public class ScreenUsageTelemetryTests { [Fact] public void TrackInitialScreen_EmitsSingleScreenView_ForCurrentPage() { var navigation = new NavigationService(); var capturing = new CapturingTelemetry(); var tracker = new ScreenUsageTelemetry(navigation, capturing, null); tracker.TrackInitialScreen(); OmikaEvent evt = Assert.Single(capturing.Events); Assert.Equal(TelemetryEventCodes.MobileScreenView, evt.EventCode); Assert.Equal(DiagnosticScreenCodes.Agenda, evt.ScreenCode); Assert.Null(evt.FeatureCode); } [Fact] public void Navigate_EmitsExactlyOneScreenView_ForTarget() { var navigation = new NavigationService(); var capturing = new CapturingTelemetry(); var tracker = new ScreenUsageTelemetry(navigation, capturing, null); tracker.TrackInitialScreen(); capturing.Clear(); navigation.NavigateTo(AppPage.SiteDetail); OmikaEvent evt = Assert.Single(capturing.Events); Assert.Equal(TelemetryEventCodes.MobileScreenView, evt.EventCode); Assert.Equal(DiagnosticScreenCodes.SiteDetail, evt.ScreenCode); } [Fact] public void Return_IsANewScreenView() { var navigation = new NavigationService(); var capturing = new CapturingTelemetry(); var tracker = new ScreenUsageTelemetry(navigation, capturing, null); tracker.TrackInitialScreen(); // AGENDA (1) navigation.NavigateTo(AppPage.SiteDetail); // SITE_DETAIL (2) navigation.GoBack(); // AGENDA (3) Assert.Equal(3, capturing.Events.Count); Assert.Equal(DiagnosticScreenCodes.Agenda, capturing.Events[0].ScreenCode); Assert.Equal(DiagnosticScreenCodes.SiteDetail, capturing.Events[1].ScreenCode); Assert.Equal(DiagnosticScreenCodes.Agenda, capturing.Events[2].ScreenCode); } [Fact] public void Refresh_OrSamePage_DoesNotEmitAnotherScreenView() { var navigation = new NavigationService(); var capturing = new CapturingTelemetry(); var tracker = new ScreenUsageTelemetry(navigation, capturing, null); tracker.TrackInitialScreen(); // AGENDA (1) navigation.NavigateTo(AppPage.SiteDetail); // SITE_DETAIL (2) // Même page (paramètre identique ou différent) : NavigationService ne lève // pas PageChanged (seulement ParameterChanged) → aucun ScreenView. navigation.NavigateTo(AppPage.SiteDetail); navigation.NavigateTo(AppPage.SiteDetail, new object()); Assert.Equal(2, capturing.Events.Count); } [Fact] public void Navigate_SetsCurrentScreenOnDiagnosticContext() { var navigation = new NavigationService(); var capturing = new CapturingTelemetry(); var context = new DiagnosticContext(new DiagnosticSession(), new DeviceInfoSnapshot()); var tracker = new ScreenUsageTelemetry(navigation, capturing, context); tracker.TrackInitialScreen(); navigation.NavigateTo(AppPage.InterventionDetail); Assert.Equal(DiagnosticScreenCodes.InterventionDetail, context.ScreenCode); } [Fact] public void UnknownPage_DoesNotEmit() { var navigation = new NavigationService(); var capturing = new CapturingTelemetry(); var tracker = new ScreenUsageTelemetry(navigation, capturing, null); // Aucune page inconnue n'est navigable, mais le tracker reste fail-open : // la navigation vers une page non résolue n'émet rien. tracker.TrackInitialScreen(); capturing.Clear(); navigation.NavigateTo(AppPage.Parametres); Assert.Single(capturing.Events); Assert.Equal(DiagnosticScreenCodes.Settings, capturing.Events[0].ScreenCode); } private sealed class CapturingTelemetry : IOmikaTelemetry { public List Events { get; } = []; public void Track(TelemetryEvent telemetryEvent) => Events.Add(telemetryEvent); public void Log(DiagnosticEvent diagnosticEvent) => Events.Add(diagnosticEvent); public void Clear() => Events.Clear(); } }