167 lines
7.2 KiB
C#
167 lines
7.2 KiB
C#
using System.Text.Json;
|
|
using Omika.App.Local.Abstractions;
|
|
using Omika.App.Local.Models;
|
|
using Omika.App.Local.Services;
|
|
using Omika.Core.Contracts.Common;
|
|
using Omika.Core.Contracts.Planning;
|
|
|
|
namespace Omika.Tests.Mobile.Local;
|
|
|
|
/// <summary>
|
|
/// Tests des bornes de plage du service Agenda : chargement d'une journée ou
|
|
/// d'une semaine avec une seule opération locale et des bornes robustes.
|
|
/// </summary>
|
|
public class AgendaServiceRangeTests : LocalTestBase
|
|
{
|
|
private readonly AgendaService _service;
|
|
|
|
public AgendaServiceRangeTests()
|
|
{
|
|
_service = new AgendaService(
|
|
RendezVousRepository, ClientRepository, SiteRepository, InterventionRepository, CollaborateurRepository, ApiClient, SessionService);
|
|
}
|
|
|
|
private static LocalRendezVous CreateRendezVous(
|
|
Guid id,
|
|
DateTime debut,
|
|
DateTime fin,
|
|
string titre,
|
|
bool estArchive = false)
|
|
{
|
|
var dto = new RendezVousDetailsDto
|
|
{
|
|
Id = id.ToString(),
|
|
Titre = titre,
|
|
Debut = debut,
|
|
Fin = fin,
|
|
Statut = new ReferenceValueDto { Label = "Planifié" },
|
|
EstArchive = estArchive
|
|
};
|
|
return new LocalRendezVous
|
|
{
|
|
Id = id,
|
|
PayloadJson = JsonSerializer.Serialize(dto),
|
|
UpdatedAtUtc = DateTimeOffset.UtcNow
|
|
};
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Plage_BornesJournee_00h00Inclus_23h59Inclus_LendemainExclu()
|
|
{
|
|
// Arrange
|
|
DateTime jour = new(2026, 8, 12);
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), jour.Date, jour.Date.AddHours(1), "00:00"));
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), jour.Date.AddHours(23).AddMinutes(59), jour.Date.AddHours(23).AddMinutes(59).AddMinutes(1), "23:59"));
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), jour.AddDays(1).Date, jour.AddDays(1).Date.AddHours(1), "lendemain 00:00"));
|
|
|
|
// Act : plage d'un jour, borne fin exclue (lendemain 00:00).
|
|
IReadOnlyList<AgendaItem> result = await _service.GetRendezVousForRangeAsync(jour.Date, jour.Date.AddDays(1));
|
|
|
|
// Assert : 00:00 inclus, 23:59 inclus (via borne < lendemain 00:00), lendemain exclu.
|
|
Assert.Equal(2, result.Count);
|
|
Assert.Contains(result, x => x.Titre == "00:00");
|
|
Assert.Contains(result, x => x.Titre == "23:59");
|
|
Assert.DoesNotContain(result, x => x.Titre == "lendemain 00:00");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Plage_BornesSemaine_LundiInclus_DimancheInclus_LundiSuivantExclu()
|
|
{
|
|
// Arrange : 2026-08-10 est un lundi.
|
|
DateTime lundi = new(2026, 8, 10);
|
|
DateTime dimanche = lundi.AddDays(6);
|
|
DateTime lundiSuivant = lundi.AddDays(7);
|
|
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), lundi.Date, lundi.Date.AddHours(1), "lundi"));
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), dimanche.Date.AddHours(23).AddMinutes(59), dimanche.Date.AddHours(23).AddMinutes(59).AddMinutes(1), "dimanche"));
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), lundiSuivant.Date, lundiSuivant.Date.AddHours(1), "lundi suivant"));
|
|
|
|
// Act : lundi inclus → dimanche inclus, lundi suivant exclu.
|
|
IReadOnlyList<AgendaItem> result = await _service.GetRendezVousForRangeAsync(lundi, lundiSuivant);
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Count);
|
|
Assert.Contains(result, x => x.Titre == "lundi");
|
|
Assert.Contains(result, x => x.Titre == "dimanche");
|
|
Assert.DoesNotContain(result, x => x.Titre == "lundi suivant");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Plage_RendezVousPlusieursJours_VisibleChaqueJourDeSonIntervalle()
|
|
{
|
|
// Arrange : un rendez-vous groupé sur plusieurs jours (12 → 14/08).
|
|
DateTime debut = new(2026, 8, 12, 8, 0, 0);
|
|
DateTime fin = new(2026, 8, 14, 17, 0, 0);
|
|
Guid id = Guid.NewGuid();
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(id, debut, fin, "chantier 3 jours"));
|
|
|
|
// Act / Assert : présent sur CHAQUE journée de l'intervalle…
|
|
foreach (DateTime jour in new[] { debut.Date, debut.Date.AddDays(1), fin.Date })
|
|
{
|
|
IReadOnlyList<AgendaItem> result = await _service.GetRendezVousForRangeAsync(jour, jour.AddDays(1));
|
|
AgendaItem item = Assert.Single(result);
|
|
Assert.Equal("chantier 3 jours", item.Titre);
|
|
Assert.True(item.CouvreLeJour(jour));
|
|
}
|
|
|
|
// … et absent des journées hors intervalle.
|
|
Assert.Empty(await _service.GetRendezVousForRangeAsync(fin.Date.AddDays(1), fin.Date.AddDays(2)));
|
|
Assert.Empty(await _service.GetRendezVousForRangeAsync(debut.Date.AddDays(-2), debut.Date.AddDays(-1)));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Plage_RendezVousCommenceAvantLaPlageMaisLaCouvre_ResteVisible()
|
|
{
|
|
// Arrange : un chantier commencé le 10/08 et fini le 20/08.
|
|
await RendezVousRepository.UpsertAsync(
|
|
CreateRendezVous(Guid.NewGuid(), new DateTime(2026, 8, 10, 8, 0, 0), new DateTime(2026, 8, 20, 17, 0, 0), "long"));
|
|
|
|
// Act : plage du 14 au 21/08 — le rendez-vous commence AVANT la plage.
|
|
IReadOnlyList<AgendaItem> result = await _service.GetRendezVousForRangeAsync(
|
|
new DateTime(2026, 8, 14), new DateTime(2026, 8, 21));
|
|
|
|
// Assert : il est conservé car il couvre encore la plage.
|
|
AgendaItem item = Assert.Single(result);
|
|
Assert.Equal("long", item.Titre);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Plage_JourneeUnique_RetourneLesRendezVousDuJour()
|
|
{
|
|
// Arrange
|
|
DateTime jour = new(2026, 8, 12);
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), jour.AddHours(9), jour.AddHours(10), "A"));
|
|
await RendezVousRepository.UpsertAsync(CreateRendezVous(Guid.NewGuid(), jour.AddDays(1).AddHours(9), jour.AddDays(1).AddHours(10), "B"));
|
|
|
|
// Act
|
|
IReadOnlyList<AgendaItem> result = await _service.GetRendezVousForDayAsync(jour);
|
|
|
|
// Assert : GetRendezVousForDayAsync délègue à la plage d'un jour.
|
|
AgendaItem item = Assert.Single(result);
|
|
Assert.Equal("A", item.Titre);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Règle métier : un rendez-vous ARCHIVÉ ne monte jamais dans le mobile. Une
|
|
/// copie locale peut subsister (snapshot antérieur au filtre serveur, données
|
|
/// déjà synchronisées) : l'agenda ne doit jamais l'afficher.
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task Plage_RendezVousArchive_NApparaitPas()
|
|
{
|
|
// Arrange : un rendez-vous courant et un rendez-vous archivé, même jour.
|
|
DateTime jour = new(2026, 8, 12);
|
|
await RendezVousRepository.UpsertAsync(
|
|
CreateRendezVous(Guid.NewGuid(), jour.AddHours(9), jour.AddHours(10), "courant"));
|
|
await RendezVousRepository.UpsertAsync(
|
|
CreateRendezVous(Guid.NewGuid(), jour.AddHours(14), jour.AddHours(15), "archivé", estArchive: true));
|
|
|
|
// Act
|
|
IReadOnlyList<AgendaItem> result = await _service.GetRendezVousForDayAsync(jour);
|
|
|
|
// Assert : seul le rendez-vous courant subsiste.
|
|
AgendaItem item = Assert.Single(result);
|
|
Assert.Equal("courant", item.Titre);
|
|
}
|
|
}
|