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

306 lines
13 KiB
C#

using System.Text.Json;
using Omika.App.Local.Abstractions;
using Omika.App.Local.Infrastructure;
using Omika.App.Local.Models;
using Omika.App.Local.Services;
using Omika.Core.Contracts.Clients;
using Omika.Core.Contracts.Interventions;
using Omika.Core.Contracts.Mobile.Bootstrap;
using Omika.Core.Contracts.Mobile.Documents;
using Omika.Core.Contracts.Mobile.Interventions;
using Omika.Core.Contracts.Mobile.License;
using Omika.Core.Contracts.Mobile.Snapshot;
using Omika.Core.Contracts.Mobile.Sync;
using Omika.Core.Contracts.Organisation;
using Omika.Core.Contracts.Sites;
namespace Omika.Tests.Mobile.Local;
public sealed class InterventionContextualRelationsTests : LocalTestBase
{
[Fact]
public async Task ClientDetail_IgnoreLaTableInterventionHistorique()
{
Guid clientId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await ClientRepository.UpsertAsync(Client(clientId, "Client A"));
await InterventionRepository.UpsertAsync(LocalIntervention(interventionId, clientId: clientId));
var service = new ClientLocalService(ClientRepository, DossierRepository, ContextInterventionCacheRepository, ClientStateRepository, ApiClient);
ClientDetail? result = await service.GetClientByIdAsync(clientId);
Assert.NotNull(result);
Assert.False(result.InterventionsCacheAvailable);
Assert.Empty(result.Interventions);
}
[Fact]
public async Task ClientRefreshOnline_RechercheParClientId_EtNeTouchePasInterventionCache()
{
Guid clientId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await ClientRepository.UpsertAsync(Client(clientId, "Client A"));
var api = new RecordingApiClient([Result(Intervention(interventionId, clientId: clientId))]);
var service = new ClientLocalService(ClientRepository, DossierRepository, ContextInterventionCacheRepository, ClientStateRepository, api);
ClientDetail? result = await service.RefreshClientInterventionsAsync(clientId);
Assert.NotNull(result);
Assert.Equal(clientId.ToString(), api.LastSearchRequest?.ClientId);
Assert.Null(api.LastSearchRequest?.SiteId);
Assert.Null(api.LastSearchRequest?.CollaborateurId);
var intervention = Assert.Single(result.Interventions);
Assert.Equal(interventionId, intervention.InterventionGuid);
Assert.Null(await InterventionCacheRepository.GetByIdAsync(interventionId));
}
[Fact]
public async Task ClientOffline_AvecCache_AfficheLeCache()
{
Guid clientId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await ClientRepository.UpsertAsync(Client(clientId, "Client A"));
await ContextInterventionCacheRepository.ReplaceAsync(
InterventionContextTypes.Client,
clientId,
[Intervention(interventionId, clientId: clientId)]);
var service = new ClientLocalService(ClientRepository, DossierRepository, ContextInterventionCacheRepository, ClientStateRepository, ApiClient);
ClientDetail? result = await service.GetClientByIdAsync(clientId);
Assert.NotNull(result);
Assert.True(result.InterventionsCacheAvailable);
Assert.Equal(interventionId, Assert.Single(result.Interventions).InterventionGuid);
}
[Fact]
public async Task ClientOffline_SansCache_NeDeclarePasZeroCommeCertitude()
{
Guid clientId = Guid.NewGuid();
await ClientRepository.UpsertAsync(Client(clientId, "Client A"));
var service = new ClientLocalService(ClientRepository, DossierRepository, ContextInterventionCacheRepository, ClientStateRepository, ApiClient);
ClientDetail? result = await service.GetClientByIdAsync(clientId);
Assert.NotNull(result);
Assert.False(result.InterventionsCacheAvailable);
Assert.Empty(result.Interventions);
}
[Fact]
public async Task SiteRefreshOnline_RechercheParSiteId()
{
Guid siteId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await SiteRepository.UpsertAsync(Site(siteId, "Site A"));
var api = new RecordingApiClient([Result(Intervention(interventionId, siteId: siteId))]);
var service = new SiteLocalService(SiteRepository, ClientRepository, PersonneRepository, RendezVousRepository, InterventionRepository, ContextInterventionCacheRepository, SiteStateRepository, api);
SiteDetail? result = await service.RefreshSiteInterventionsAsync(siteId);
Assert.NotNull(result);
Assert.Equal(siteId.ToString(), api.LastSearchRequest?.SiteId);
Assert.Null(api.LastSearchRequest?.ClientId);
Assert.Null(api.LastSearchRequest?.CollaborateurId);
Assert.Equal(interventionId, Assert.Single(result.Interventions).InterventionGuid);
}
[Fact]
public async Task CollaborateurRefreshOnline_RechercheParCollaborateurId()
{
Guid collaborateurId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await CollaborateurRepository.UpsertAsync(Collaborateur(collaborateurId));
var api = new RecordingApiClient([Result(Intervention(interventionId, collaborateurId: collaborateurId))]);
var service = new CollaborateurLocalService(CollaborateurRepository, RendezVousRepository, ContextInterventionCacheRepository, api, SessionService);
CollaborateurDetail? result = await service.RefreshCollaborateurInterventionsAsync(collaborateurId);
Assert.NotNull(result);
Assert.Equal(collaborateurId.ToString(), api.LastSearchRequest?.CollaborateurId);
Assert.Null(api.LastSearchRequest?.ClientId);
Assert.Null(api.LastSearchRequest?.SiteId);
Assert.Equal(interventionId, Assert.Single(result.Interventions).InterventionGuid);
}
[Fact]
public async Task RechercheContextuelle_NeModifiePasDerniereRechercheNiFavoris()
{
Guid clientId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await ClientRepository.UpsertAsync(Client(clientId, "Client A"));
await InterventionCacheRepository.UpsertAsync(new CachedIntervention
{
Id = interventionId,
PayloadJson = JsonSerializer.Serialize(Intervention(interventionId, clientId: clientId)),
IsInLastSearch = false,
IsPinned = true
});
var api = new RecordingApiClient([Result(Intervention(interventionId, clientId: clientId))]);
var service = new ClientLocalService(ClientRepository, DossierRepository, ContextInterventionCacheRepository, ClientStateRepository, api);
await service.RefreshClientInterventionsAsync(clientId);
CachedIntervention? cached = await InterventionCacheRepository.GetByIdAsync(interventionId);
Assert.NotNull(cached);
Assert.False(cached.IsInLastSearch);
Assert.True(cached.IsPinned);
}
[Fact]
public async Task ListesPrincipales_NeDeclenchentAucuneRechercheIntervention()
{
var api = new RecordingApiClient([]);
await ClientRepository.UpsertAsync(Client(Guid.NewGuid(), "Client A"));
await SiteRepository.UpsertAsync(Site(Guid.NewGuid(), "Site A"));
await CollaborateurRepository.UpsertAsync(Collaborateur(Guid.NewGuid()));
var clientService = new ClientLocalService(ClientRepository, DossierRepository, ContextInterventionCacheRepository, ClientStateRepository, api);
var siteService = new SiteLocalService(SiteRepository, ClientRepository, PersonneRepository, RendezVousRepository, InterventionRepository, ContextInterventionCacheRepository, SiteStateRepository, api);
var collaborateurService = new CollaborateurLocalService(CollaborateurRepository, RendezVousRepository, ContextInterventionCacheRepository, api, SessionService);
await clientService.GetClientsAsync();
await siteService.GetSitesAsync();
await collaborateurService.GetCollaborateursAsync();
Assert.Equal(0, api.SearchCalls);
}
[Fact]
public async Task InterventionContextuelle_OuvreLeDetailDepuisPayloadJson()
{
Guid clientId = Guid.NewGuid();
Guid interventionId = Guid.NewGuid();
await ClientRepository.UpsertAsync(Client(clientId, "Client A"));
await ContextInterventionCacheRepository.ReplaceAsync(
InterventionContextTypes.Client,
clientId,
[Intervention(interventionId, clientId: clientId, reference: "INT-CTX")]);
var service = new InterventionLocalService(
InterventionRepository, ClientRepository, SiteRepository, DossierRepository,
RendezVousRepository, DocumentMetadataRepository, CollaborateurRepository,
OutboxService, ReconciliationService, ApiClient, InterventionCacheRepository,
ContextInterventionCacheRepository, Database);
InterventionDetail? detail = await service.GetInterventionByIdAsync(interventionId);
Assert.NotNull(detail);
Assert.Equal("INT-CTX", detail.Reference);
Assert.Equal(clientId, detail.ClientGuid);
}
private static LocalClient Client(Guid id, string nom)
=> new()
{
Id = id,
PayloadJson = JsonSerializer.Serialize(new ClientDetailsDto { Id = id.ToString(), Nom = nom }),
UpdatedAtUtc = DateTimeOffset.UtcNow
};
private static LocalSite Site(Guid id, string nom)
=> new()
{
Id = id,
PayloadJson = JsonSerializer.Serialize(new SiteDetailsDto { Id = id.ToString(), Nom = nom }),
UpdatedAtUtc = DateTimeOffset.UtcNow
};
private static LocalCollaborateur Collaborateur(Guid id)
=> new()
{
Id = id,
PayloadJson = JsonSerializer.Serialize(new CollaborateurDetailsDto { Id = id.ToString(), Nom = "Dupont", Prenom = "Jean" }),
UpdatedAtUtc = DateTimeOffset.UtcNow
};
private static InterventionDetailsDto Intervention(
Guid id,
Guid? clientId = null,
Guid? siteId = null,
Guid? collaborateurId = null,
string reference = "INT-001")
=> new()
{
Id = id.ToString(),
Reference = reference,
Titre = "Intervention",
ClientId = clientId?.ToString(),
SiteId = siteId?.ToString(),
CollaborateurIds = collaborateurId is null ? [] : [collaborateurId.Value.ToString()],
EstArchive = false
};
private static LocalIntervention LocalIntervention(Guid id, Guid? clientId = null)
=> new()
{
Id = id,
ClientId = clientId,
PayloadJson = JsonSerializer.Serialize(Intervention(id, clientId: clientId)),
UpdatedAtUtc = DateTimeOffset.UtcNow
};
private static MobileInterventionSearchResult Result(InterventionDetailsDto detail)
=> new() { Detail = detail };
private sealed class RecordingApiClient : IMobileApiClient
{
private readonly IReadOnlyList<MobileInterventionSearchResult> _results;
public RecordingApiClient(IReadOnlyList<MobileInterventionSearchResult> results)
{
_results = results;
}
public string? AccessToken { get; set; }
public int SearchCalls { get; private set; }
public MobileInterventionSearchRequest? LastSearchRequest { get; private set; }
public Task<IReadOnlyList<MobileInterventionSearchResult>> SearchInterventionsAsync(
MobileInterventionSearchRequest request,
CancellationToken cancellationToken = default)
{
SearchCalls++;
LastSearchRequest = request;
return Task.FromResult(_results);
}
public Task<MobileLicenseSessionResponse> ActivateAsync(LicenseActivateRequest request, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<MobileLicenseSessionResponse> ValidateAsync(LicenseValidateRequest request, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<MobileLicenseSessionResponse> GetDevelopmentSessionAsync(string deviceId, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<MobileBootstrapResponse> GetBootstrapAsync(CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<SyncOperationReceipt> SendOperationAsync(SyncOperation operation, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<SyncStatusResponse> GetStatusAsync(Guid operationId, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<MobileSnapshotResponse> GetSnapshotAsync(CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<IReadOnlyList<MobileInterventionSearchResult>> GetInterventionsByIdsAsync(MobileInterventionsByIdsRequest request, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<DocumentDownloadResponse> DownloadDocumentAsync(Guid documentGuid, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
public Task<DocumentUploadResponse> UploadDocumentAsync(DocumentUploadRequest request, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
}
}