Files
Omika/tests/Omika.Tests/Mobile/Local/CollaborateursViewModelTests.cs
2026-10-23 18:46:50 +02:00

190 lines
6.4 KiB
C#

using System.Text.Json;
using Omika.App.Local.Models;
using Omika.App.Local.Services;
using Omika.App.Navigation;
using Omika.App.ViewModels;
using Omika.Core.Contracts.Organisation;
namespace Omika.Tests.Mobile.Local;
/// <summary>
/// Tests du ViewModel de la liste des collaborateurs : chargement local,
/// états vide/erreur, recherche locale et navigation vers la fiche
/// Collaborateur par identité publique. Aucun appel API.
/// </summary>
public class CollaborateursViewModelTests : LocalTestBase
{
private readonly CollaborateursViewModel _viewModel;
private readonly NavigationService _navigation;
public CollaborateursViewModelTests()
{
var service = new CollaborateurLocalService(CollaborateurRepository, RendezVousRepository, ContextInterventionCacheRepository, ApiClient, SessionService);
_navigation = new NavigationService();
_viewModel = new CollaborateursViewModel(service, _navigation);
}
private static LocalCollaborateur CreateCollaborateur(
Guid id,
string? nom = null,
string? prenom = null,
string? code = null,
string? statut = null,
string? email = null)
{
var dto = new CollaborateurDetailsDto
{
Id = id.ToString(),
Nom = nom,
Prenom = prenom,
Code = code,
Statut = statut is null ? null : new Omika.Core.Contracts.Common.ReferenceValueDto { Label = statut },
Coordonnees = email is null ? null : new Omika.Core.Contracts.Common.ContactDetailsDto { Email = email }
};
return new LocalCollaborateur
{
Id = id,
PayloadJson = JsonSerializer.Serialize(dto),
UpdatedAtUtc = DateTimeOffset.UtcNow
};
}
[Fact]
public async Task Load_ChargementPuisListe()
{
// Arrange
Guid collaborateurId = Guid.NewGuid();
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(collaborateurId, "Dupont", "Jean", "C001"));
// Act
await _viewModel.LoadCommand.ExecuteAsync(null);
// Assert : après chargement, liste affichée et chargement terminé.
Assert.False(_viewModel.IsLoading);
Assert.True(_viewModel.HasCollaborateurs);
var item = Assert.Single(_viewModel.Collaborateurs);
Assert.Equal(collaborateurId, item.CollaborateurGuid);
}
[Fact]
public async Task Load_ListeVide_EmptyState()
{
// Act
await _viewModel.LoadCommand.ExecuteAsync(null);
// Assert : liste vide sans erreur.
Assert.False(_viewModel.IsLoading);
Assert.False(_viewModel.HasCollaborateurs);
Assert.True(_viewModel.IsEmpty);
Assert.Null(_viewModel.ErrorMessage);
}
[Fact]
public async Task Load_Erreur_MessageAffiche()
{
// Arrange : un payload invalide ne provoque pas d'erreur (ignoré).
await CollaborateurRepository.UpsertAsync(new LocalCollaborateur
{
Id = Guid.NewGuid(),
PayloadJson = "not-json",
UpdatedAtUtc = DateTimeOffset.UtcNow
});
// Act
await _viewModel.LoadCommand.ExecuteAsync(null);
// Assert : l'entrée invalide est ignorée, liste vide sans erreur.
Assert.False(_viewModel.IsLoading);
Assert.False(_viewModel.HasCollaborateurs);
Assert.True(_viewModel.IsEmpty);
Assert.Null(_viewModel.ErrorMessage);
}
[Fact]
public async Task Recherche_FiltreParNom()
{
// Arrange
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(Guid.NewGuid(), "Dupont", "Jean", "C001"));
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(Guid.NewGuid(), "Martin", "Paul", "C002"));
await _viewModel.LoadCommand.ExecuteAsync(null);
// Act
_viewModel.SearchText = "dupont";
// Assert : la recherche filtre par nom (insensible à la casse).
var item = Assert.Single(_viewModel.Collaborateurs);
Assert.Equal("Jean Dupont", item.DisplayName);
}
[Fact]
public async Task Recherche_SansResultat_ListeVide()
{
// Arrange
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(Guid.NewGuid(), "Dupont", "Jean", "C001"));
await _viewModel.LoadCommand.ExecuteAsync(null);
// Act
_viewModel.SearchText = "introuvable";
// Assert : aucun résultat.
Assert.Empty(_viewModel.Collaborateurs);
Assert.False(_viewModel.HasCollaborateurs);
}
[Fact]
public async Task Recherche_Reinitialise_RetourneTous()
{
// Arrange
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(Guid.NewGuid(), "Dupont", "Jean", "C001"));
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(Guid.NewGuid(), "Martin", "Paul", "C002"));
await _viewModel.LoadCommand.ExecuteAsync(null);
// Act : recherche puis réinitialisation.
_viewModel.SearchText = "dupont";
Assert.Single(_viewModel.Collaborateurs);
_viewModel.SearchText = string.Empty;
// Assert : tous les collaborateurs sont de nouveau affichés.
Assert.Equal(2, _viewModel.Collaborateurs.Count);
}
[Fact]
public async Task OpenCollaborateur_NavigueVersDetail()
{
// Arrange
Guid collaborateurId = Guid.NewGuid();
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(collaborateurId, "Dupont", "Jean", "C001"));
await _viewModel.LoadCommand.ExecuteAsync(null);
// Act
_viewModel.OpenCollaborateurCommand.Execute(_viewModel.Collaborateurs[0]);
// Assert : navigation vers la fiche Collaborateur avec le GUID public.
Assert.Equal(AppPage.CollaborateurDetail, _navigation.CurrentPage);
Assert.Equal(collaborateurId, _navigation.CurrentParameter);
}
[Fact]
public async Task OpenCollaborateur_Null_NeNaviguePas()
{
// Act
_viewModel.OpenCollaborateurCommand.Execute(null);
// Assert
Assert.Equal(AppPage.Home, _navigation.CurrentPage);
}
[Fact]
public async Task FonctionneOffline_SansAppelApi()
{
// Arrange : aucune dépendance réseau, uniquement SQLite local.
await CollaborateurRepository.UpsertAsync(CreateCollaborateur(Guid.NewGuid(), "Dupont", "Jean", "C001"));
// Act
await _viewModel.LoadCommand.ExecuteAsync(null);
// Assert
Assert.True(_viewModel.HasCollaborateurs);
}
}