Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user