using Omika.Diagnostics.Tasks; using Omika.Diagnostics.Tests.Fakes; using Omika.Diagnostics.Web.Pages; namespace Omika.Diagnostics.Tests; /// /// T25 — Tâches de traitement : statuts, mapping d'affichage « traité / non traité » /// () et contrat du repository (fake, miroir du Npgsql). /// public class DiagnosticTaskTests { private static DiagnosticTaskRecord MakeTask(string status) => new() { Id = 1, GroupUrlIdentifier = "group", Title = "T", Status = status, CreatedByUsername = "alice", CreatedAtUtc = DateTimeOffset.UtcNow, UpdatedAtUtc = DateTimeOffset.UtcNow }; // ------------------------------------------------------ statuts ---------------- [Theory] [InlineData("Todo", DiagnosticTaskStatuses.Todo)] [InlineData("todo", DiagnosticTaskStatuses.Todo)] [InlineData("inprogress", DiagnosticTaskStatuses.InProgress)] [InlineData("RESOLVED", DiagnosticTaskStatuses.Resolved)] [InlineData("rejected", DiagnosticTaskStatuses.Rejected)] public void Status_Normalize_IsCaseInsensitive(string raw, string expected) => Assert.Equal(expected, DiagnosticTaskStatuses.Normalize(raw)); [Fact] public void Status_Unknown_FallsBackToTodo() => Assert.Equal(DiagnosticTaskStatuses.Todo, DiagnosticTaskStatuses.Normalize("Inconnu")); [Fact] public void Status_TerminalAndOpen() { Assert.True(DiagnosticTaskStatuses.IsTerminal(DiagnosticTaskStatuses.Resolved)); Assert.True(DiagnosticTaskStatuses.IsTerminal(DiagnosticTaskStatuses.Rejected)); Assert.False(DiagnosticTaskStatuses.IsTerminal(DiagnosticTaskStatuses.Todo)); Assert.False(DiagnosticTaskStatuses.IsTerminal(DiagnosticTaskStatuses.InProgress)); Assert.True(DiagnosticTaskStatuses.IsOpen(DiagnosticTaskStatuses.Todo)); Assert.True(DiagnosticTaskStatuses.IsOpen(DiagnosticTaskStatuses.InProgress)); Assert.False(DiagnosticTaskStatuses.IsOpen(DiagnosticTaskStatuses.Resolved)); } // -------------------------------------- mapping « traité / non traité » -------- [Fact] public void Treatment_NoTask_IsATraiter() { Assert.Equal("À traiter", UiTaskContext.TreatmentLabel(null)); Assert.Equal("badge badge--danger", UiTaskContext.TreatmentClass(null)); } [Fact] public void Treatment_OpenTask_IsEnCours() { Assert.Equal("En cours", UiTaskContext.TreatmentLabel(MakeTask(DiagnosticTaskStatuses.Todo))); Assert.Equal("En cours", UiTaskContext.TreatmentLabel(MakeTask(DiagnosticTaskStatuses.InProgress))); Assert.Equal("badge badge--warning", UiTaskContext.TreatmentClass(MakeTask(DiagnosticTaskStatuses.InProgress))); } [Fact] public void Treatment_Resolved_IsTraite() { Assert.Equal("Traité", UiTaskContext.TreatmentLabel(MakeTask(DiagnosticTaskStatuses.Resolved))); Assert.Equal("badge badge--success", UiTaskContext.TreatmentClass(MakeTask(DiagnosticTaskStatuses.Resolved))); } [Fact] public void Treatment_Rejected_IsRejete() { Assert.Equal("Rejeté", UiTaskContext.TreatmentLabel(MakeTask(DiagnosticTaskStatuses.Rejected))); Assert.Equal("badge badge--muted", UiTaskContext.TreatmentClass(MakeTask(DiagnosticTaskStatuses.Rejected))); } // ------------------------------------------------------ repository ------------- [Fact] public async Task Repository_Create_AndUnique() { var repo = new FakeDiagnosticTaskRepository(); DiagnosticTaskRecord? created = await repo.CreateAsync( "grp-1", "Titre", null, null, DiagnosticTaskStatuses.Todo, "alice", null); Assert.NotNull(created); Assert.Equal(1, created.Id); Assert.Equal(DiagnosticTaskStatuses.Todo, created.Status); Assert.Null(created.ResolvedAtUtc); // Doublon : même signature → null. DiagnosticTaskRecord? duplicate = await repo.CreateAsync( "grp-1", "Autre", null, null, DiagnosticTaskStatuses.Todo, "alice", null); Assert.Null(duplicate); } [Fact] public async Task Repository_CreateTerminal_SetsResolvedAt() { var repo = new FakeDiagnosticTaskRepository(); DiagnosticTaskRecord? created = await repo.CreateAsync( "grp-1", "Titre", null, "cause", DiagnosticTaskStatuses.Resolved, "alice", "bob"); Assert.NotNull(created); Assert.Equal(DiagnosticTaskStatuses.Resolved, created.Status); Assert.NotNull(created.ResolvedAtUtc); Assert.Equal("bob", created.AssigneeUsername); } [Fact] public async Task Repository_Update_SetsAndClearsResolvedAt() { var repo = new FakeDiagnosticTaskRepository(); await repo.CreateAsync("grp-1", "Titre", null, null, DiagnosticTaskStatuses.Todo, "alice", null); bool resolved = await repo.UpdateAsync( 1, "Titre", null, "cause", DiagnosticTaskStatuses.Resolved, null); Assert.True(resolved); DiagnosticTaskRecord? task = await repo.GetByIdAsync(1); Assert.NotNull(task); Assert.Equal(DiagnosticTaskStatuses.Resolved, task!.Status); Assert.Equal("cause", task.Cause); Assert.NotNull(task.ResolvedAtUtc); // Retour en statut ouvert → la date de résolution est effacée. await repo.UpdateAsync(1, "Titre", null, "cause", DiagnosticTaskStatuses.InProgress, null); task = await repo.GetByIdAsync(1); Assert.Equal(DiagnosticTaskStatuses.InProgress, task!.Status); Assert.Null(task.ResolvedAtUtc); } }