using System.Reflection; using Omika.Core.Contracts.Common; using Omika.Core.Contracts.Configuration; using Omika.Core.Contracts.Mobile.Sync; using Omika.Core.Contracts.Organisation; using Omika.Core.Contracts.Planning; using Omika.Core.Domain.Commands; using Omika.Core.Domain.Entities.Organisation; using Omika.Core.Domain.ValueObjects; using Omika.Core.Interfaces; using Omika.Core.Interfaces.Mobile; using Omika.Core.Services; using Omika.Core.Domain; namespace Omika.Tests.Services; /// /// Tests unitaires de avec un fake /// en mémoire. Aucune base réelle. /// public class CollaborateurServiceTests { // ========================================================================= // SEARCH // ========================================================================= [Fact] public async Task SearchAsync_CallsRepositoryOnce() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest()); Assert.Equal(1, repo.SearchCallCount); } [Fact] public async Task SearchAsync_TransmitsPage() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { Page = 3 }); Assert.Equal(3, repo.LastSearchCriteria?.Page); } [Fact] public async Task SearchAsync_TransmitsPageSize() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { PageSize = 50 }); Assert.Equal(50, repo.LastSearchCriteria?.PageSize); } [Fact] public async Task SearchAsync_TransmitsSearch() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { Search = "test" }); Assert.Equal("test", repo.LastSearchCriteria?.Search); } [Fact] public async Task SearchAsync_TransmitsEquipeId() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { EquipeId = "equipe-1" }); Assert.Equal("equipe-1", repo.LastSearchCriteria?.EquipeId); } [Fact] public async Task SearchAsync_TransmitsActif() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { Actif = true }); Assert.True(repo.LastSearchCriteria?.Actif); } [Fact] public async Task SearchAsync_TransmitsEstArchive() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { EstArchive = true }); Assert.True(repo.LastSearchCriteria?.EstArchive); } [Fact] public async Task SearchAsync_TransmitsSortBy() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { SortBy = "Nom" }); Assert.Equal("Nom", repo.LastSearchCriteria?.SortBy); } [Fact] public async Task SearchAsync_TransmitsSortDescending() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.SearchAsync(new SearchCollaborateurRequest { SortDescending = true }); Assert.True(repo.LastSearchCriteria?.SortDescending); } [Fact] public async Task SearchAsync_TransmitsCancellationToken() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); using var cts = new CancellationTokenSource(); await service.SearchAsync(new SearchCollaborateurRequest(), cts.Token); Assert.Equal(cts.Token, repo.LastCancellationToken); } [Fact] public async Task SearchAsync_EmptyResult_ReturnsEmptyPage() { var repo = new FakeCollaborateurRepository { SearchResult = new PagedResult([], 1, 20, 0, 0) }; var service = CreateService(repo); PagedResult result = await service.SearchAsync( new SearchCollaborateurRequest()); Assert.Empty(result.Items); Assert.Equal(0, result.TotalCount); Assert.Equal(0, result.TotalPages); Assert.Equal(1, result.Page); Assert.Equal(20, result.PageSize); } [Fact] public async Task SearchAsync_SingleCollaborateur_MapsToSummaryDto() { var collaborateur = new Collaborateur { Nom = "Dupont", Prenom = "Jean", Code = "JD", Coordonnees = new ContactDetails { Email = "jean@example.com", Phone = "0102030405" }, Actif = true }; var repo = new FakeCollaborateurRepository { SearchResult = new PagedResult([collaborateur], 1, 20, 1, 1) }; var service = CreateService(repo); PagedResult result = await service.SearchAsync( new SearchCollaborateurRequest()); CollaborateurSummaryDto dto = Assert.Single(result.Items); Assert.Equal("Jean Dupont", dto.NomAffiche); Assert.Equal("JD", dto.Code); Assert.Equal("jean@example.com", dto.Email); Assert.Equal("0102030405", dto.Telephone); Assert.True(dto.Actif); } [Fact] public async Task SearchAsync_MultipleCollaborateurs_MapsAllToDtos() { var collaborateurList = new[] { new Collaborateur { Nom = "Alpha" }, new Collaborateur { Nom = "Beta" }, new Collaborateur { Nom = "Gamma" } }; var repo = new FakeCollaborateurRepository { SearchResult = new PagedResult(collaborateurList, 1, 20, 3, 1) }; var service = CreateService(repo); PagedResult result = await service.SearchAsync( new SearchCollaborateurRequest()); Assert.Equal(3, result.Items.Count); Assert.Equal(3, result.TotalCount); Assert.Equal("Alpha", result.Items[0].NomAffiche); Assert.Equal("Beta", result.Items[1].NomAffiche); Assert.Equal("Gamma", result.Items[2].NomAffiche); } [Fact] public async Task SearchAsync_PreservesTotalCount() { var repo = new FakeCollaborateurRepository { SearchResult = new PagedResult([], 2, 10, 42, 5) }; var service = CreateService(repo); PagedResult result = await service.SearchAsync( new SearchCollaborateurRequest()); Assert.Equal(42, result.TotalCount); Assert.Equal(2, result.Page); Assert.Equal(10, result.PageSize); Assert.Equal(5, result.TotalPages); } [Fact] public async Task SearchAsync_IdComesFromCollaborateurContractMapper() { var collaborateur = new Collaborateur { Nom = "Test" }; var expectedId = collaborateur.Id.ToString(); var repo = new FakeCollaborateurRepository { SearchResult = new PagedResult([collaborateur], 1, 20, 1, 1) }; var service = CreateService(repo); PagedResult result = await service.SearchAsync( new SearchCollaborateurRequest()); Assert.Equal(expectedId, result.Items[0].Id); } [Fact] public async Task SearchAsync_ServiceDoesNotRePaginate() { var repo = new FakeCollaborateurRepository { SearchResult = new PagedResult( [new Collaborateur { Nom = "A" }, new Collaborateur { Nom = "B" }], 3, 15, 100, 7) }; var service = CreateService(repo); PagedResult result = await service.SearchAsync( new SearchCollaborateurRequest { Page = 1, PageSize = 5 }); Assert.Equal(2, result.Items.Count); Assert.Equal(100, result.TotalCount); Assert.Equal(7, result.TotalPages); } // ========================================================================= // DETAIL // ========================================================================= [Fact] public async Task GetByIdAsync_TransmitsExactId() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.GetByIdAsync("test-id-123"); Assert.Equal("test-id-123", repo.LastDetailsId); } [Fact] public async Task GetByIdAsync_TransmitsCancellationToken() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); using var cts = new CancellationTokenSource(); await service.GetByIdAsync("42", cts.Token); Assert.Equal(cts.Token, repo.LastCancellationToken); } [Fact] public async Task GetByIdAsync_RepositoryReturnsNull_ReturnsNull() { var repo = new FakeCollaborateurRepository { DetailsResult = null }; var service = CreateService(repo); CollaborateurDetailsDto? result = await service.GetByIdAsync("999"); Assert.Null(result); } [Fact] public async Task GetByIdAsync_MapsToDetailsDto() { var collaborateur = new Collaborateur { Nom = "Dupont", Prenom = "Jean", Code = "JD", Civilite = new ReferenceValue("M.") { Key = "M" }, Statut = new ReferenceValue("Actif") { Key = "ACTIF" }, Coordonnees = new ContactDetails { Email = "jean@example.com" } }; var repo = new FakeCollaborateurRepository { DetailsResult = collaborateur }; var service = CreateService(repo); CollaborateurDetailsDto? result = await service.GetByIdAsync("42"); Assert.NotNull(result); Assert.Equal("Dupont", result.Nom); Assert.Equal("Jean", result.Prenom); Assert.Equal("JD", result.Code); Assert.Equal("M.", result.Civilite?.Label); Assert.Equal("Actif", result.Statut?.Label); Assert.Equal("jean@example.com", result.Coordonnees?.Email); } [Fact] public async Task GetByIdAsync_IdComesFromMapper() { var collaborateur = new Collaborateur { Nom = "Test" }; var expectedId = collaborateur.Id.ToString(); var repo = new FakeCollaborateurRepository { DetailsResult = collaborateur }; var service = CreateService(repo); CollaborateurDetailsDto? result = await service.GetByIdAsync("42"); Assert.NotNull(result); Assert.Equal(expectedId, result.Id); } [Fact] public async Task GetByIdAsync_NoGuidParsingInService() { var repo = new FakeCollaborateurRepository(); var service = CreateService(repo); await service.GetByIdAsync("not-a-guid-nor-int"); Assert.Equal("not-a-guid-nor-int", repo.LastDetailsId); } [Fact] public async Task GetByIdAsync_RepositoryException_Propagated() { var repo = new FakeCollaborateurRepository { ThrowOnDetails = new InvalidOperationException("Infrastructure error") }; var service = CreateService(repo); var ex = await Assert.ThrowsAsync( () => service.GetByIdAsync("42")); Assert.Equal("Infrastructure error", ex.Message); } // ========================================================================= // CREATE // ========================================================================= [Fact] public async Task CreateAsync_CallsRepositoryOnce() { var repo = new FakeCollaborateurRepository { CreateResult = new Collaborateur { Nom = "Nouveau" } }; var service = CreateService(repo); await service.CreateAsync(new CreateCollaborateurRequest { Nom = "Nouveau" }); Assert.Equal(1, repo.CreateCallCount); } [Fact] public async Task CreateAsync_MapsAllProperties() { var repo = new FakeCollaborateurRepository { CreateResult = new Collaborateur { Nom = "Nouveau" } }; var service = CreateService(repo); await service.CreateAsync(new CreateCollaborateurRequest { Code = "JD", Nom = "Dupont", Prenom = "Jean", CiviliteKey = "M", StatutKey = "ACTIF", Email = "jean@example.com", Telephone = "0102030405", Mobile = "0607080910", Fonction = "Développeur", SocieteId = "societe-1", CouleurPlanning = "#FF0000", Actif = true }); Assert.Equal("JD", repo.LastCreateCommand!.Code); Assert.Equal("Dupont", repo.LastCreateCommand!.Nom); Assert.Equal("Jean", repo.LastCreateCommand!.Prenom); Assert.Equal("M", repo.LastCreateCommand!.CiviliteKey); Assert.Equal("ACTIF", repo.LastCreateCommand!.StatutKey); Assert.Equal("jean@example.com", repo.LastCreateCommand!.Email); Assert.Equal("0102030405", repo.LastCreateCommand!.Telephone); Assert.Equal("0607080910", repo.LastCreateCommand!.Mobile); Assert.Equal("Développeur", repo.LastCreateCommand!.Fonction); Assert.Equal("societe-1", repo.LastCreateCommand!.SocieteId); Assert.Equal("#FF0000", repo.LastCreateCommand!.CouleurPlanning); Assert.True(repo.LastCreateCommand!.Actif); } [Fact] public async Task CreateAsync_ResultMappedToDetails() { var repo = new FakeCollaborateurRepository { CreateResult = new Collaborateur { Nom = "Nouveau" } }; var service = CreateService(repo); CollaborateurDetailsDto result = await service.CreateAsync(new CreateCollaborateurRequest { Nom = "Nouveau" }); Assert.Equal("Nouveau", result.Nom); } [Fact] public async Task CreateAsync_CancellationTokenTransmitted() { var repo = new FakeCollaborateurRepository { CreateResult = new Collaborateur { Nom = "Nouveau" } }; var service = CreateService(repo); using var cts = new CancellationTokenSource(); await service.CreateAsync(new CreateCollaborateurRequest { Nom = "Nouveau" }, cts.Token); Assert.Equal(cts.Token, repo.LastCreateCancellationToken); } [Fact] public async Task CreateAsync_ExceptionPropagated() { var repo = new FakeCollaborateurRepository { ThrowOnCreate = new InvalidOperationException("Panne") }; var service = CreateService(repo); var ex = await Assert.ThrowsAsync( () => service.CreateAsync(new CreateCollaborateurRequest { Nom = "Nouveau" })); Assert.Equal("Panne", ex.Message); } // ========================================================================= // UPDATE // ========================================================================= [Fact] public async Task UpdateAsync_MapsAllProperties() { var repo = new FakeCollaborateurRepository { UpdateResult = new Collaborateur { Nom = "Updated" } }; var service = CreateService(repo); await service.UpdateAsync("42", new UpdateCollaborateurRequest { Code = "JD", Nom = "Updated", CiviliteKey = "M", StatutKey = "ACTIF" }); Assert.Equal(1, repo.UpdateCallCount); Assert.Equal("42", repo.LastUpdateId); Assert.Equal("JD", repo.LastUpdateCommand!.Code); Assert.Equal("Updated", repo.LastUpdateCommand!.Nom); Assert.Equal("M", repo.LastUpdateCommand!.CiviliteKey); Assert.Equal("ACTIF", repo.LastUpdateCommand!.StatutKey); } [Fact] public async Task UpdateAsync_NullsPreserved() { var repo = new FakeCollaborateurRepository { UpdateResult = new Collaborateur { Nom = "X" } }; var service = CreateService(repo); await service.UpdateAsync("42", new UpdateCollaborateurRequest()); Assert.Null(repo.LastUpdateCommand!.CiviliteKey); Assert.Null(repo.LastUpdateCommand!.StatutKey); } [Fact] public async Task UpdateAsync_RepoReturnsNull_ThrowsKeyNotFound() { var repo = new FakeCollaborateurRepository { UpdateResult = null }; var service = CreateService(repo); await Assert.ThrowsAsync( () => service.UpdateAsync("42", new UpdateCollaborateurRequest())); } [Fact] public async Task UpdateAsync_IdTransmittedExactly() { var repo = new FakeCollaborateurRepository { UpdateResult = new Collaborateur { Nom = "XY" } }; var service = CreateService(repo); await service.UpdateAsync("my-guid-123", new UpdateCollaborateurRequest()); Assert.Equal("my-guid-123", repo.LastUpdateId); } [Fact] public async Task UpdateAsync_CancellationTokenTransmitted() { var repo = new FakeCollaborateurRepository { UpdateResult = new Collaborateur { Nom = "X" } }; var service = CreateService(repo); using var cts = new CancellationTokenSource(); await service.UpdateAsync("42", new UpdateCollaborateurRequest(), cts.Token); Assert.Equal(cts.Token, repo.LastUpdateCancellationToken); } [Fact] public async Task UpdateAsync_ExceptionPropagated() { var repo = new FakeCollaborateurRepository { ThrowOnUpdate = new InvalidOperationException("Panne") }; var service = CreateService(repo); var ex = await Assert.ThrowsAsync( () => service.UpdateAsync("42", new UpdateCollaborateurRequest())); Assert.Equal("Panne", ex.Message); } // ========================================================================= // ARCHIVE // ========================================================================= [Fact] public async Task ArchiveAsync_TruePropagated() { var repo = new FakeCollaborateurRepository { ArchiveResult = true }; var service = CreateService(repo); bool result = await service.ArchiveAsync("42"); Assert.True(result); Assert.Equal(1, repo.ArchiveCallCount); } [Fact] public async Task ArchiveAsync_False_ReturnsFalse() { var repo = new FakeCollaborateurRepository { ArchiveResult = false }; var service = CreateService(repo); bool result = await service.ArchiveAsync("42"); Assert.False(result); } [Fact] public async Task ArchiveAsync_IdTransmittedExactly() { var repo = new FakeCollaborateurRepository { ArchiveResult = true }; var service = CreateService(repo); await service.ArchiveAsync("my-guid-123"); Assert.Equal("my-guid-123", repo.LastArchiveId); } [Fact] public async Task ArchiveAsync_CancellationTokenTransmitted() { var repo = new FakeCollaborateurRepository { ArchiveResult = true }; var service = CreateService(repo); using var cts = new CancellationTokenSource(); await service.ArchiveAsync("42", cts.Token); Assert.Equal(cts.Token, repo.LastArchiveCancellationToken); } [Fact] public async Task ArchiveAsync_ExceptionPropagated() { var repo = new FakeCollaborateurRepository { ThrowOnArchive = new InvalidOperationException("Panne") }; var service = CreateService(repo); var ex = await Assert.ThrowsAsync( () => service.ArchiveAsync("42")); Assert.Equal("Panne", ex.Message); } // ========================================================================= // ARCHITECTURE // ========================================================================= [Fact] public void Service_ImplementsICollaborateurService() { Assert.True(typeof(ICollaborateurService).IsAssignableFrom(typeof(CollaborateurService))); } [Fact] public void Service_DependsOnICollaborateurRepository() { var type = typeof(CollaborateurService); bool hasRepoParam = type.GetConstructors() .Any(c => c.GetParameters() .Any(p => p.ParameterType == typeof(ICollaborateurRepository))); Assert.True(hasRepoParam, "CollaborateurService doit dépendre de ICollaborateurRepository."); } [Fact] public void Service_HasNoOmikaDataReferences() { var type = typeof(CollaborateurService); var refs = GetReferencedTypes(type); Assert.DoesNotContain(refs, t => t.Namespace is not null && t.Namespace.StartsWith("Omika.Data")); } [Fact] public void Service_HasNoBatikReferences() { var type = typeof(CollaborateurService); var refs = GetReferencedTypes(type); Assert.DoesNotContain(refs, t => t.Name.Contains("Batik", StringComparison.OrdinalIgnoreCase)); } [Fact] public void Service_HasNoHfsqlReferences() { var type = typeof(CollaborateurService); var refs = GetReferencedTypes(type); Assert.DoesNotContain(refs, t => t.Name.Contains("Row", StringComparison.OrdinalIgnoreCase) && t.Namespace is not null && (t.Namespace.Contains("HfSql", StringComparison.OrdinalIgnoreCase) || t.Namespace.Contains("Models.Omika", StringComparison.OrdinalIgnoreCase))); } [Fact] public void Service_HasNoSqlStatements() { string source = ReadSourceFile(typeof(CollaborateurService)); Assert.DoesNotContain("SELECT ", source, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("FROM ", source, StringComparison.OrdinalIgnoreCase); } [Fact] public void Service_HasNoApplicationRuntimeContext() { var type = typeof(CollaborateurService); var refs = GetReferencedTypes(type); Assert.DoesNotContain(refs, t => t.Name.Contains("ApplicationRuntimeContext", StringComparison.OrdinalIgnoreCase)); } [Fact] public void Service_HasNoDatabaseSchemaVersion() { var type = typeof(CollaborateurService); var refs = GetReferencedTypes(type); Assert.DoesNotContain(refs, t => t.Name.Contains("DatabaseSchemaVersion", StringComparison.OrdinalIgnoreCase)); } [Fact] public void Service_HasNoOdbcReferences() { var type = typeof(CollaborateurService); var refs = GetReferencedTypes(type); Assert.DoesNotContain(refs, t => t.Namespace is not null && t.Namespace.StartsWith("System.Data.Odbc", StringComparison.Ordinal)); } // ========================================================================= // HELPERS // ========================================================================= private static CollaborateurService CreateService(FakeCollaborateurRepository repo) => new CollaborateurService( repo, new FakeIdentityResolver(), new FakeRendezVousService(), new FakeParametreMetierRepository()); private sealed class FakeRendezVousService : IRendezVousService { public Task> SearchAsync(SearchRendezVousRequest request, CancellationToken cancellationToken = default) => Task.FromResult(new PagedResult([], 1, 20, 0, 0)); public Task> SearchDetailsAsync(SearchRendezVousRequest request, CancellationToken cancellationToken = default) => Task.FromResult(new PagedResult([], 1, 20, 0, 0)); public Task GetByIdAsync(string id, CancellationToken cancellationToken = default) => Task.FromResult(null); public Task CreateAsync(CreateRendezVousRequest request, CancellationToken cancellationToken = default, AuditActor? auteur = null) => throw new NotSupportedException(); public Task UpdateAsync(string id, UpdateRendezVousRequest request, CancellationToken cancellationToken = default, AuditActor? auteur = null) => throw new NotSupportedException(); public Task CancelAsync(string id, AnnulationRendezVousDto annulation, CancellationToken cancellationToken = default, AuditActor? auteur = null) => Task.CompletedTask; public Task ArchiveAsync(string id, CancellationToken cancellationToken = default, AuditActor? auteur = null) => Task.CompletedTask; public Task SetTempsValideAsync(string rendezVousId, string collaborateurId, bool tempsValide, CancellationToken cancellationToken = default, AuditActor? auteur = null) => Task.FromResult(true); } private sealed class FakeParametreMetierRepository : IParametreMetierRepository { public IReadOnlyList Items { get; set; } = []; public Task> GetAllAsync(CancellationToken cancellationToken = default) => Task.FromResult(Items); } private sealed class FakeIdentityResolver : IMobileEntityIdentityResolver { public Guid CreateCanonicalIdentity(string entityType, PhysicalEntityIdentity physical) => physical.Guid ?? Guid.Empty; public PhysicalEntityIdentity? ResolvePhysicalIdentity(string entityType, Guid publicGuid) => null; public bool IsCanonical(string entityType, Guid publicGuid) => publicGuid != Guid.Empty; } private static IEnumerable GetReferencedTypes(Type type) { var members = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) .Select(m => m.DeclaringType) .Where(t => t is not null) .Cast(); var parameters = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .SelectMany(m => m.GetParameters()) .Select(p => p.ParameterType); var returnTypes = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Select(m => m.ReturnType); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Select(p => p.PropertyType); var ctorParams = type.GetConstructors() .SelectMany(c => c.GetParameters()) .Select(p => p.ParameterType); return members.Concat(parameters).Concat(returnTypes).Concat(properties).Concat(ctorParams); } private static string ReadSourceFile(Type type) { string baseDir = AppDomain.CurrentDomain.BaseDirectory; var dir = new DirectoryInfo(baseDir); while (dir != null && !File.Exists(Path.Combine(dir.FullName, "Omika.slnx"))) dir = dir.Parent; string root = dir?.FullName ?? baseDir; return File.ReadAllText(Path.Combine(root, "src", "Omika.Core", "Services", type.Name + ".cs")); } // ========================================================================= // FAKE REPOSITORY // ========================================================================= private sealed class FakeCollaborateurRepository : ICollaborateurRepository { public int SearchCallCount { get; private set; } public int DetailsCallCount { get; private set; } public int UpdateCallCount { get; private set; } public int ArchiveCallCount { get; private set; } public int CreateCallCount { get; private set; } public CollaborateurSearchCriteria? LastSearchCriteria { get; private set; } public string? LastDetailsId { get; private set; } public string? LastUpdateId { get; private set; } public string? LastArchiveId { get; private set; } public CollaborateurUpdateCommand? LastUpdateCommand { get; private set; } public CollaborateurCreateCommand? LastCreateCommand { get; private set; } public CancellationToken LastUpdateCancellationToken { get; private set; } public CancellationToken LastArchiveCancellationToken { get; private set; } public CancellationToken LastCreateCancellationToken { get; private set; } public CancellationToken LastCancellationToken { get; private set; } public PagedResult? SearchResult { get; set; } public Collaborateur? DetailsResult { get; set; } public Collaborateur? UpdateResult { get; set; } public Collaborateur? CreateResult { get; set; } public bool ArchiveResult { get; set; } public Exception? ThrowOnSearch { get; set; } public Exception? ThrowOnDetails { get; set; } public Exception? ThrowOnUpdate { get; set; } public Exception? ThrowOnArchive { get; set; } public Exception? ThrowOnCreate { get; set; } public Task CreateAsync( CollaborateurCreateCommand command, CancellationToken cancellationToken = default) { CreateCallCount++; LastCreateCommand = command; LastCreateCancellationToken = cancellationToken; if (ThrowOnCreate is not null) throw ThrowOnCreate; return Task.FromResult(CreateResult ?? new Collaborateur { Nom = command.Nom }); } public Task> SearchAsync( CollaborateurSearchCriteria criteria, CancellationToken cancellationToken = default) { SearchCallCount++; LastSearchCriteria = criteria; LastCancellationToken = cancellationToken; if (ThrowOnSearch is not null) throw ThrowOnSearch; return Task.FromResult(SearchResult ?? new PagedResult([], 1, 20, 0, 0)); } public Task> SearchDetailsAsync( CollaborateurSearchCriteria criteria, CancellationToken cancellationToken = default) { SearchCallCount++; LastSearchCriteria = criteria; LastCancellationToken = cancellationToken; if (ThrowOnSearch is not null) throw ThrowOnSearch; return Task.FromResult(SearchResult ?? new PagedResult([], 1, 20, 0, 0)); } public Task GetDetailsAsync( string id, CancellationToken cancellationToken = default) { DetailsCallCount++; LastDetailsId = id; LastCancellationToken = cancellationToken; if (ThrowOnDetails is not null) throw ThrowOnDetails; return Task.FromResult(DetailsResult); } public Task GetUtilisateurByCollaborateurAsync( string collaborateurId, CancellationToken cancellationToken = default) => Task.FromResult(null); public Task GetParametreSystemeValueAsync(string code, CancellationToken cancellationToken = default) => Task.FromResult(null); public Task UpdateAsync( string id, CollaborateurUpdateCommand command, CancellationToken cancellationToken = default) { UpdateCallCount++; LastUpdateId = id; LastUpdateCommand = command; LastUpdateCancellationToken = cancellationToken; if (ThrowOnUpdate is not null) throw ThrowOnUpdate; return Task.FromResult(UpdateResult); } public Task ArchiveAsync( string id, CancellationToken cancellationToken = default) { ArchiveCallCount++; LastArchiveId = id; LastArchiveCancellationToken = cancellationToken; if (ThrowOnArchive is not null) throw ThrowOnArchive; return Task.FromResult(ArchiveResult); } public Task> GetSocieteIdsAsync(long collaborateurId, CancellationToken cancellationToken = default) => Task.FromResult>([]); public Task> GetAllowedCollaborateurIdsAsync(long collaborateurId, bool includeSocietePrincipale, bool includeSocietes, bool includeEquipe, CancellationToken cancellationToken = default) => Task.FromResult>([]); } }