using Omika.Core.Observability; using Omika.Core.Observability.Diagnostic; namespace Omika.Tests.Observability.Diagnostic; public class TelemetryContextEnricherTests { [Fact] public void Track_EnrichesSessionTraceAndDevice() { var (enricher, capturing, context, trace) = Build(); Guid traceId; using (trace.BeginTrace()) { traceId = trace.CurrentTraceId!.Value; enricher.Track(new TelemetryEvent { EventCode = TelemetryEventCodes.MobileAppStarted }); } OmikaEvent captured = capturing.LastEvent!; Assert.Equal(context.SessionId, captured.SessionId); Assert.Equal(traceId, captured.TraceId); Assert.Equal("1.2.3", captured.AppVersion); Assert.Equal("TestPlatform", captured.Platform); } [Fact] public void Track_DoesNotOverrideExplicitValues() { var (enricher, capturing, _, _) = Build(); Guid explicitSession = Guid.NewGuid(); Guid explicitTrace = Guid.NewGuid(); enricher.Track(new TelemetryEvent { EventCode = TelemetryEventCodes.MobileAppStarted, SessionId = explicitSession, TraceId = explicitTrace }); Assert.Equal(explicitSession, capturing.LastEvent!.SessionId); Assert.Equal(explicitTrace, capturing.LastEvent!.TraceId); } [Fact] public void Log_EnrichesDiagnosticEvent() { var (enricher, capturing, _, _) = Build(); enricher.Log(new DiagnosticEvent { EventCode = TelemetryEventCodes.ApiRequestFailed }); Assert.Equal(TelemetryEventCodes.ApiRequestFailed, capturing.LastEvent!.EventCode); Assert.NotNull(capturing.LastEvent!.SessionId); } [Fact] public void EnrichesOptionalIdentity_WhenSet() { var (enricher, capturing, context, _) = Build(); context.DeviceId = "device-123"; context.ClientId = "client-456"; enricher.Track(new TelemetryEvent { EventCode = TelemetryEventCodes.MobileAppStarted }); Assert.Equal("device-123", capturing.LastEvent!.DeviceId); Assert.Equal("client-456", capturing.LastEvent!.ClientId); } [Fact] public void Track_EnrichesScreenCodeFromContext() { var (enricher, capturing, context, _) = Build(); context.ScreenCode = Omika.Core.Observability.DiagnosticScreenCodes.SiteDetail; enricher.Track(new TelemetryEvent { EventCode = TelemetryEventCodes.MobileAppStarted }); Assert.Equal(DiagnosticScreenCodes.SiteDetail, capturing.LastEvent!.ScreenCode); } [Fact] public void Track_DoesNotOverrideExplicitScreenCode() { var (enricher, capturing, context, _) = Build(); context.ScreenCode = DiagnosticScreenCodes.Agenda; enricher.Track(new TelemetryEvent { EventCode = TelemetryEventCodes.MobileScreenView, ScreenCode = DiagnosticScreenCodes.SiteDetail }); Assert.Equal(DiagnosticScreenCodes.SiteDetail, capturing.LastEvent!.ScreenCode); } [Fact] public async Task ScreenCode_DoesNotLeakIntoPreExistingBackgroundFlow() { var session = new DiagnosticSession(); var context = new DiagnosticContext(session, new DeviceInfoSnapshot()); // Boucle background lancée AVANT toute navigation : son ExecutionContext est // capturé à null, puis reste null malgré la navigation sur le fil principal (§64). string? seenByBackground = null; Task background = Task.Run(async () => { await Task.Delay(20); seenByBackground = context.ScreenCode; }); context.ScreenCode = DiagnosticScreenCodes.Agenda; await background; Assert.Null(seenByBackground); Assert.Equal(DiagnosticScreenCodes.Agenda, context.ScreenCode); } [Fact] public void Track_EnrichesAppBuildAndScreenDimensions() { var session = new DiagnosticSession(); var deviceInfo = new DeviceInfoSnapshot { AppVersion = "1.4.1", AppBuild = "10401", Platform = "Android", OperatingSystem = "Android", OperatingSystemVersion = "16", DeviceManufacturer = "Xiaomi", DeviceModel = "23113RKC6G", ScreenWidth = 1080, ScreenHeight = 2400, LogicalWidth = 393, LogicalHeight = 873, DisplayScale = 2.75 }; var context = new DiagnosticContext(session, deviceInfo); var trace = new TraceContext(); var capturing = new CapturingTelemetry(); var enricher = new TelemetryContextEnricher(capturing, context, trace); enricher.Track(new TelemetryEvent { EventCode = TelemetryEventCodes.MobileAppStarted }); OmikaEvent captured = capturing.LastEvent!; Assert.Equal("10401", captured.AppBuild); Assert.Equal(1080, captured.ScreenWidth); Assert.Equal(2400, captured.ScreenHeight); Assert.Equal(393, captured.LogicalWidth); Assert.Equal(873, captured.LogicalHeight); Assert.Equal(2.75, captured.DisplayScale); Assert.Equal("Xiaomi", captured.DeviceManufacturer); Assert.Equal("23113RKC6G", captured.DeviceModel); } private static (TelemetryContextEnricher Enricher, CapturingTelemetry Capturing, DiagnosticContext Context, TraceContext Trace) Build() { var session = new DiagnosticSession(); var deviceInfo = new DeviceInfoSnapshot { AppVersion = "1.2.3", Platform = "TestPlatform" }; var context = new DiagnosticContext(session, deviceInfo); var trace = new TraceContext(); var capturing = new CapturingTelemetry(); return (new TelemetryContextEnricher(capturing, context, trace), capturing, context, trace); } private sealed class CapturingTelemetry : IOmikaTelemetry { public OmikaEvent? LastEvent { get; private set; } public void Track(TelemetryEvent telemetryEvent) => LastEvent = telemetryEvent; public void Log(DiagnosticEvent diagnosticEvent) => LastEvent = diagnosticEvent; } }