using System.Linq; using System.Threading; using Avalonia; using Avalonia.Controls; using Avalonia.Headless; using Avalonia.VisualTree; using Omika.App.Local.Abstractions; using Omika.App.Local.Models; using Omika.App.ViewModels; using Omika.App.Views; using Xunit; namespace Omika.Tests.Mobile; /// /// Test 1 (régression inscription) : l'écran d'inscription doit toujours /// exposer la saisie manuelle (TextBox) et le bouton « S'inscrire », en plus du /// scan QR. Construit la vue réelle sur le backend Skia headless et vérifie la /// présence effective des contrôles dans l'arbre visuel. /// /// /// Session Avalonia headless : la classe rejoint la collection /// « ApplicationRuntimeContext » afin qu'aucune autre session headless (ni aucun /// test construisant une vue Avalonia) ne s'exécute en parallèle — le /// localisateur d'Avalonia est global au processus. /// [Collection("ApplicationRuntimeContext")] public sealed class LicenseActivationViewConstructionTests : IDisposable { private readonly HeadlessUnitTestSession _session; public LicenseActivationViewConstructionTests() { _session = HeadlessUnitTestSession.StartNew(typeof(EnrollmentViewTestAppBuilder)); } public void Dispose() => _session.Dispose(); private sealed class FakeEnrollmentService : IEnrollmentService { public Task LoadAsync(CancellationToken ct = default) => Task.FromResult(null); public Task EnrollAsync(string qrContent, CancellationToken ct = default) => Task.FromResult(EnrollmentResult.Failed("refusée")); public Task ClearAsync(CancellationToken ct = default) => Task.CompletedTask; } private sealed class FakeQrScanner : IEnrollmentQrScanner { public Task ScanAsync(IQrScannerPreviewSink? previewSink, CancellationToken ct = default) => Task.FromResult(null); } [Fact] public void Vue_SaisieManuelle_TextBoxEtBoutonSinscrire_Presents() { _session.Dispatch(() => { var viewModel = new LicenseActivationViewModel(new FakeEnrollmentService(), new FakeQrScanner()); var view = new LicenseActivationView { DataContext = viewModel }; Assert.NotNull(view.Content); Control[] descendants = view.GetVisualDescendants().OfType().ToArray(); // Champ de saisie manuelle présent et lié à ManualEnrollmentCode. TextBox? textBox = descendants.OfType() .FirstOrDefault(t => t.Name == "ManualEnrollmentTextBox"); Assert.NotNull(textBox); // Bouton « S'inscrire » présent. Button? enrollButton = descendants.OfType