using Avalonia;
using Avalonia.Headless;
using Omika.App.Local.Abstractions;
using Omika.App.Local.Models;
using Omika.App.Navigation;
using Omika.App.Services;
using Omika.App.ViewModels;
using Omika.App.Views;
using Omika.Core.Contracts.Common;
using Omika.Core.Contracts.Mobile.Interventions;
using Omika.Core.Contracts.Mobile.Sync;
using Omika.Tests.Mobile;
namespace Omika.Tests.Mobile.Local;
///
/// Tests de construction de la vue Interventions (régression runtime du
/// micro-lot 36 : la page doit pouvoir être construite avec zéro donnée,
/// sans exception d'InitializeComponent ni de binding).
///
///
/// La construction d'une vue Avalonia exige les services de plateforme : les
/// tests s'exécutent donc DANS une session Avalonia headless (sinon ils échouent
/// sur « Unable to locate Avalonia.Platform.IPlatformRenderInterface »), et la
/// classe rejoint la collection « ApplicationRuntimeContext » pour ne jamais
/// s'exécuter en parallèle d'une autre session headless.
///
[Collection("ApplicationRuntimeContext")]
public class InterventionsViewConstructionTests : IDisposable
{
private readonly HeadlessUnitTestSession _session =
HeadlessUnitTestSession.StartNew(typeof(LayoutTestAppBuilder));
public void Dispose() => _session.Dispose();
[Fact]
public void InterventionsView_Constructible_SansException()
{
// Dispatch générique : cette surcharge ATTEND la fin de l'action, ce qui
// n'est pas le cas de Dispatch(Action) — les assertions seraient alors
// évaluées hors du test.
_session.Dispatch(
() =>
{
var view = new InterventionsView();
Assert.NotNull(view);
Assert.NotNull(view.Content);
return true;
},
CancellationToken.None).GetAwaiter().GetResult();
}
[Fact]
public void InterventionsView_AvecViewModelVide_AucuneException()
{
_session.Dispatch(
() =>
{
var viewModel = new InterventionsViewModel(
new FakeInterventionService(),
new FakeParametreMetierService(),
new NavigationService(),
new PermissionService(),
Omika.Core.Observability.NullTelemetryService.Instance);
var view = new InterventionsView { DataContext = viewModel };
Assert.NotNull(view.Content);
return true;
},
CancellationToken.None).GetAwaiter().GetResult();
}
private sealed class FakeInterventionService : IInterventionLocalService
{
public Task> GetInterventionsAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task GetInterventionByIdAsync(Guid interventionGuid, CancellationToken cancellationToken = default)
=> Task.FromResult(null);
public Task CreateAsync(InterventionSyncPayload payload, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task UpdateAsync(Guid interventionGuid, InterventionSyncPayload payload, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task ArchiveAsync(Guid interventionGuid, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task> SearchAsync(MobileInterventionSearchRequest request, CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task> GetLastSearchAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task> GetPinnedAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task SetPinnedAsync(Guid interventionGuid, bool isPinned, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
public Task RefreshPinnedAsync(CancellationToken cancellationToken = default)
=> Task.CompletedTask;
public Task RefreshInterventionAsync(Guid interventionGuid, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
private sealed class FakeParametreMetierService : IParametreMetierLocalService
{
public Task> GetTypeTempsAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task GetTypeTempsParametresAsync(string typeTempsKey, CancellationToken ct = default)
=> Task.FromResult(null);
public Task GetTypeRdvParametresAsync(string typeRdvKey, CancellationToken ct = default)
=> Task.FromResult(null);
public Task GetStatutRdvParametresAsync(string statutRdvKey, CancellationToken ct = default)
=> Task.FromResult(null);
public Task> GetInterventionTypesAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetInterventionEtatsAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetDossierTypesAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetDossierStatutsAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetClientTypesAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetClientStatutsAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetSiteTypesAsync(CancellationToken ct = default)
=> Task.FromResult>([]);
public Task> GetTypeSignatairesAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
}
private sealed class FakeClientService : IClientLocalService
{
public Task> GetClientsAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task GetClientByIdAsync(Guid clientGuid, CancellationToken cancellationToken = default)
=> Task.FromResult(null);
}
private sealed class FakeSiteService : ISiteLocalService
{
public Task> GetSitesAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task GetSiteByIdAsync(Guid siteGuid, CancellationToken cancellationToken = default)
=> Task.FromResult(null);
}
private sealed class FakeCollaborateurService : ICollaborateurLocalService
{
public Task> GetCollaborateursAsync(CancellationToken cancellationToken = default)
=> Task.FromResult>([]);
public Task GetCollaborateurByIdAsync(Guid collaborateurGuid, CancellationToken cancellationToken = default)
=> Task.FromResult(null);
}
}