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

126 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Omika.App.Local.Abstractions;
using Omika.App.Local.Models;
using Omika.App.Local.Services;
using Omika.Core.Contracts.Mobile.Sync;
using Omika.Core.Contracts.Planning;
namespace Omika.Tests.Mobile.Local;
/// <summary>
/// Tests du service local de finalisation d'un rendez-vous : mise à jour SQLite du
/// statut « Fait » (jamais de suppression) + publication du changement d'état.
/// </summary>
public class RendezVousFinalisationLocalServiceTests
{
private sealed class FakeRendezVousRepository : ILocalRepository<LocalRendezVous>
{
public string TableName => "RendezVous";
private readonly Dictionary<Guid, LocalRendezVous> _items = [];
public void Seed(LocalRendezVous entity) => _items[entity.Id] = entity;
public Task UpsertAsync(LocalRendezVous entity, CancellationToken cancellationToken = default)
{
_items[entity.Id] = entity;
return Task.CompletedTask;
}
public Task<LocalRendezVous?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
=> Task.FromResult(_items.TryGetValue(id, out LocalRendezVous? entity) ? entity : null);
public Task<IReadOnlyList<LocalRendezVous>> GetAllAsync(CancellationToken cancellationToken = default)
=> Task.FromResult<IReadOnlyList<LocalRendezVous>>([.. _items.Values]);
public Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{
_items.Remove(id);
return Task.CompletedTask;
}
public Task ClearAsync(CancellationToken cancellationToken = default)
{
_items.Clear();
return Task.CompletedTask;
}
public Task<int> CountAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(_items.Count);
}
private static RendezVousDetailsDto DtoConfirmé(Guid guid)
=> new()
{
Id = guid.ToString("D"),
Titre = "RDV Client",
Statut = new Omika.Core.Contracts.Common.ReferenceValueDto
{
Key = "S.RDV.CONF",
Label = "Confirmé"
},
Debut = DateTime.Now.AddDays(-1),
Fin = DateTime.Now.AddDays(-1).AddHours(2)
};
[Fact]
public async Task MarquerFaitAsync_AppliqueStatutFaitLocalementEtPublie()
{
// Arrange : un rendez-vous local au statut « Confirmé ».
Guid rendezVousGuid = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");
var repository = new FakeRendezVousRepository();
repository.Seed(new LocalRendezVous
{
Id = rendezVousGuid,
PayloadJson = JsonSerializer.Serialize(DtoConfirmé(rendezVousGuid))
});
var notifier = new RendezVousStateNotifier();
RendezVousStateChange? published = null;
notifier.StateChanged += (_, change) => published = change;
var service = new RendezVousFinalisationLocalService(repository, notifier);
// Act
await service.MarquerFaitAsync(rendezVousGuid);
// Assert : la copie locale porte le statut « Fait » (GUID conservé).
LocalRendezVous? updated = await repository.GetByIdAsync(rendezVousGuid);
Assert.NotNull(updated);
RendezVousDetailsDto? dto = JsonSerializer.Deserialize<RendezVousDetailsDto>(updated!.PayloadJson);
Assert.Equal(RendezVousStatut.FaitKey, dto!.Statut?.Key);
Assert.Equal(RendezVousStatut.FaitLabel, dto.Statut?.Label);
Assert.Null(dto.Annulation);
// Assert : le changement d'état a été publié (propagation aux vues).
Assert.NotNull(published);
Assert.Equal(rendezVousGuid, published!.RendezVousGuid);
Assert.False(published.EstAnnule);
Assert.True(published.EstFait);
Assert.Equal(RendezVousStatut.FaitKey, published.StatutKey);
Assert.Equal(RendezVousStatut.FaitLabel, published.StatutLabel);
}
[Fact]
public async Task MarquerFaitAsync_RendezVousLocalIntrouvable_PublieToutDeMeme()
{
// Arrange : aucun rendez-vous dans le snapshot local (ex. agenda d'équipe).
Guid rendezVousGuid = Guid.NewGuid();
var notifier = new RendezVousStateNotifier();
RendezVousStateChange? published = null;
notifier.StateChanged += (_, change) => published = change;
var service = new RendezVousFinalisationLocalService(new FakeRendezVousRepository(), notifier);
// Act : ne doit pas lever d'exception.
await service.MarquerFaitAsync(rendezVousGuid);
// Assert : l'événement est publié malgré l'absence locale (UI immédiate).
Assert.NotNull(published);
Assert.Equal(rendezVousGuid, published!.RendezVousGuid);
Assert.True(published.EstFait);
}
}