Files
Omika/tests/Omika.Diagnostics.Tests/DiagnosticFilterOptionsTests.cs
T
2026-10-23 18:46:50 +02:00

131 lines
5.6 KiB
C#

using Omika.Diagnostics.Queries;
using Omika.Diagnostics.Tests.Fakes;
namespace Omika.Diagnostics.Tests;
/// <summary>
/// Tâche 12 — Options de filtre : conservation de la valeur active (C8/C9) et
/// comportement des valeurs distinctes (borne, tri, exclusion des vides).
/// </summary>
public class DiagnosticFilterOptionsTests
{
private static readonly DateTimeOffset From = new(2025, 1, 1, 0, 0, 0, TimeSpan.Zero);
// --------------------------- C8 : filtre EventCode conserve sa valeur ----
[Fact]
public void EnsureIncluded_KeepsActiveEventCodeAtFrontWithoutDuplicate()
{
IReadOnlyList<string> options = new[] { "OMK-API-HTTP-001", "OMK-API-HTTP-003" };
IReadOnlyList<string> result = DiagnosticFilterDefaults.EnsureIncluded(options, "OMK-WKR-SYNC-002");
Assert.Equal(3, result.Count);
Assert.Equal("OMK-WKR-SYNC-002", result[0]);
Assert.Equal("OMK-API-HTTP-001", result[1]);
Assert.Equal("OMK-API-HTTP-003", result[2]);
}
// ----------------------------- C9 : filtre version conserve sa valeur ----
[Fact]
public void EnsureIncluded_KeepsActiveVersionWithoutDuplicate()
{
IReadOnlyList<string> options = new[] { "1.0.0.0", "1.1.0.0" };
IReadOnlyList<string> result = DiagnosticFilterDefaults.EnsureIncluded(options, "2.0.0.0");
Assert.Equal(3, result.Count);
Assert.Contains("2.0.0.0", result);
Assert.Equal(1, result.Count(v => v == "2.0.0.0"));
}
[Fact]
public void EnsureIncluded_ReturnsSameListWhenAlreadyPresent()
{
IReadOnlyList<string> options = new[] { "1.0.0.0", "1.1.0.0" };
IReadOnlyList<string> result = DiagnosticFilterDefaults.EnsureIncluded(options, "1.0.0.0");
Assert.Same(options, result);
Assert.Equal(2, result.Count);
}
// ------------------------------------ Options : distinct, triées, bornées ----
[Fact]
public async Task GetFilterOptions_ReturnsDistinctSortedBoundedValues()
{
var repo = new FakeDiagnosticEventRepository();
await repo.InsertBatchAsync(new[]
{
DiagnosticTestData.Event(Guid.NewGuid(), "A", From.AddMinutes(1), component: "Zeta"),
DiagnosticTestData.Event(Guid.NewGuid(), "B", From.AddMinutes(2), component: "Alpha"),
DiagnosticTestData.Event(Guid.NewGuid(), "C", From.AddMinutes(3), component: "Alpha"),
DiagnosticTestData.Event(Guid.NewGuid(), "D", From.AddMinutes(4), component: null), // exclu (null)
DiagnosticTestData.Event(Guid.NewGuid(), "E", From.AddMinutes(5), component: " "), // exclu (vide)
});
IReadOnlyList<string> result = await repo.GetFilterOptionsAsync(
DiagnosticFilterDimension.Component, From, 10);
Assert.Equal(new[] { "Alpha", "Zeta" }, result);
}
[Fact]
public async Task GetFilterOptions_RespectsLimit()
{
var repo = new FakeDiagnosticEventRepository();
await repo.InsertBatchAsync(new[]
{
DiagnosticTestData.Event(Guid.NewGuid(), "A", From.AddMinutes(1), component: "C1"),
DiagnosticTestData.Event(Guid.NewGuid(), "B", From.AddMinutes(2), component: "C2"),
DiagnosticTestData.Event(Guid.NewGuid(), "C", From.AddMinutes(3), component: "C3"),
});
IReadOnlyList<string> result = await repo.GetFilterOptionsAsync(
DiagnosticFilterDimension.Component, From, 2);
Assert.Equal(2, result.Count);
}
// ---------------- T20 §3/§6 : options Component normalisées (une seule option) ----
[Fact]
public async Task GetFilterOptions_Component_NormalizesCaseAndWhitespace()
{
var repo = new FakeDiagnosticEventRepository();
await repo.InsertBatchAsync(new[]
{
DiagnosticTestData.Event(Guid.NewGuid(), "A", From.AddMinutes(1), component: "Omika.Api"),
DiagnosticTestData.Event(Guid.NewGuid(), "B", From.AddMinutes(2), component: "omika.api"),
DiagnosticTestData.Event(Guid.NewGuid(), "C", From.AddMinutes(3), component: "OMIKA.API"),
DiagnosticTestData.Event(Guid.NewGuid(), "D", From.AddMinutes(4), component: " Omika.Api "),
DiagnosticTestData.Event(Guid.NewGuid(), "E", From.AddMinutes(5), component: "Omika.Worker"),
});
IReadOnlyList<string> result = await repo.GetFilterOptionsAsync(
DiagnosticFilterDimension.Component, From, 10);
// 4 variantes du même composant + 1 autre = 2 options logiques (tri ascendant).
Assert.Equal(new[] { "Omika.Api", "Omika.Worker" }, result);
}
// ---------------- T20 §4/§6 : options ErrorCode normalisées (une seule option) ----
[Fact]
public async Task GetFilterOptions_ErrorCode_NormalizesCaseAndWhitespace()
{
var repo = new FakeDiagnosticEventRepository();
await repo.InsertBatchAsync(new[]
{
DiagnosticTestData.Event(Guid.NewGuid(), "A", From.AddMinutes(1), errorCode: "timeout"),
DiagnosticTestData.Event(Guid.NewGuid(), "B", From.AddMinutes(2), errorCode: "TIMEOUT"),
DiagnosticTestData.Event(Guid.NewGuid(), "C", From.AddMinutes(3), errorCode: " Timeout"),
DiagnosticTestData.Event(Guid.NewGuid(), "D", From.AddMinutes(4), errorCode: " timeout "),
DiagnosticTestData.Event(Guid.NewGuid(), "E", From.AddMinutes(5), errorCode: "CRASH"),
});
IReadOnlyList<string> result = await repo.GetFilterOptionsAsync(
DiagnosticFilterDimension.ErrorCode, From, 10);
// 4 variantes du même code + 1 autre = 2 options logiques (tri ascendant).
Assert.Equal(new[] { "CRASH", "TIMEOUT" }, result);
}
}