190 lines
6.4 KiB
C#
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);
|
|
}
|
|
}
|