Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
using Omika.Diagnostics.Models;
|
||||
using Omika.Diagnostics.Tests.Fakes;
|
||||
using Omika.Diagnostics.Web.Pages;
|
||||
|
||||
namespace Omika.Diagnostics.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Tâche T13-G — Tests PageModel multi-clients (G25-G32) : conservation des filtres
|
||||
/// dans /Diagnostics, pagination, détail, libellé NULL, non-confusion du serveur
|
||||
/// Worker, variation des statistiques Dashboard/Telemetry par client. PageModels
|
||||
/// testés sans HttpContext (constructeur repository uniquement, cf. infra T13-F).
|
||||
/// </summary>
|
||||
public class DiagnosticMultiClientPageModelTests
|
||||
{
|
||||
private const string ClientA = "DEMO-CLIENT-A";
|
||||
private const string ClientB = "DEMO-CLIENT-B";
|
||||
private const string ClientC = "DEMO-CLIENT-C";
|
||||
private const string ApiA = "API-A-01";
|
||||
private const string WkrA = "WORKER-A-01";
|
||||
|
||||
private static readonly DateTimeOffset From = new(2025, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
|
||||
private static DiagnosticEventRecord Ev(
|
||||
long id,
|
||||
string eventCode = "TEST",
|
||||
string? client = null,
|
||||
string? server = null,
|
||||
string? environment = null,
|
||||
DateTimeOffset? ts = null,
|
||||
string level = "Info",
|
||||
string? component = null,
|
||||
Guid? operationId = null)
|
||||
{
|
||||
DiagnosticEventRecord record = DiagnosticTestData.Event(Guid.NewGuid(), eventCode, ts ?? From, component: component, level: level);
|
||||
record.Id = id;
|
||||
record.ClientCode = client;
|
||||
record.ServerInstance = server;
|
||||
record.Environment = environment;
|
||||
record.OperationId = operationId;
|
||||
return record;
|
||||
}
|
||||
|
||||
// --------------------------- G25 : filtre Client conservé ------------------
|
||||
[Fact]
|
||||
public async Task G25_DiagnosticsModel_SelectedClientIsPreserved()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
await repo.InsertBatchAsync(new[]
|
||||
{
|
||||
Ev(1, client: ClientA, server: ApiA, environment: "Production"),
|
||||
Ev(2, client: ClientB, server: "API-B-01", environment: "Production")
|
||||
});
|
||||
|
||||
var model = new DiagnosticsModel(repo) { ClientCode = ClientA };
|
||||
await model.OnGetAsync();
|
||||
|
||||
DiagnosticEventRecord record = Assert.Single(model.Items);
|
||||
Assert.Equal(ClientA, record.ClientCode);
|
||||
Assert.Equal(ClientA, model.ClientCode);
|
||||
}
|
||||
|
||||
// --------------------------- G26 : pagination conserve 3 filtres -----------
|
||||
[Fact]
|
||||
public void G26_DiagnosticsModel_RoutePreservesAllThreeFilters()
|
||||
{
|
||||
var model = new DiagnosticsModel(new FakeDiagnosticEventRepository())
|
||||
{
|
||||
ClientCode = ClientA,
|
||||
ServerInstance = WkrA,
|
||||
Environment = "Production"
|
||||
};
|
||||
|
||||
Dictionary<string, string> route = model.Route(3);
|
||||
|
||||
Assert.Equal("3", route["pageNumber"]);
|
||||
Assert.Equal(ClientA, route["clientCode"]);
|
||||
Assert.Equal(WkrA, route["serverInstance"]);
|
||||
Assert.Equal("Production", route["environment"]);
|
||||
}
|
||||
|
||||
// --------------------------- G27 : détail affiche les 3 valeurs ------------
|
||||
[Fact]
|
||||
public async Task G27_DiagnosticsDetail_ShowsDeploymentContext()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
DiagnosticEventRecord record = Ev(42, client: ClientA, server: ApiA, environment: "Production");
|
||||
await repo.InsertBatchAsync(new[] { record });
|
||||
|
||||
var model = new DiagnosticsDetailModel(repo);
|
||||
Microsoft.AspNetCore.Mvc.IActionResult result = await model.OnGetAsync(42);
|
||||
|
||||
Assert.IsType<Microsoft.AspNetCore.Mvc.RazorPages.PageResult>(result);
|
||||
Assert.NotNull(model.Event);
|
||||
Assert.Equal(ClientA, model.Event!.ClientCode);
|
||||
Assert.Equal(ApiA, model.Event.ServerInstance);
|
||||
Assert.Equal("Production", model.Event.Environment);
|
||||
}
|
||||
|
||||
// --------------------------- G28 : NULL → « Non renseigné » ----------------
|
||||
[Fact]
|
||||
public async Task G28_NullContext_RendersNonRenseigneAndLoadsWithoutCrash()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
DiagnosticEventRecord record = Ev(7, client: null, server: null, environment: null);
|
||||
await repo.InsertBatchAsync(new[] { record });
|
||||
|
||||
var model = new DiagnosticsDetailModel(repo);
|
||||
Microsoft.AspNetCore.Mvc.IActionResult result = await model.OnGetAsync(7);
|
||||
|
||||
// Le détail se charge sans planter et l'événement NULL reste lisible.
|
||||
Assert.IsType<Microsoft.AspNetCore.Mvc.RazorPages.PageResult>(result);
|
||||
Assert.NotNull(model.Event);
|
||||
Assert.Null(model.Event!.ClientCode);
|
||||
|
||||
// L'UI affichera « Non renseigné » pour chacune des trois valeurs NULL.
|
||||
Assert.Equal("Non renseigné", UiDeploymentContext.Value(model.Event.ClientCode));
|
||||
Assert.Equal("Non renseigné", UiDeploymentContext.Value(model.Event.ServerInstance));
|
||||
Assert.Equal("Non renseigné", UiDeploymentContext.Value(model.Event.Environment));
|
||||
}
|
||||
|
||||
// --------------------------- G29 : serveur Worker ≠ serveur API ------------
|
||||
[Fact]
|
||||
public async Task G29_WorkerOccurrence_ShowsWorkerServerNotApiServer()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
Guid operationId = Guid.NewGuid();
|
||||
await repo.InsertBatchAsync(new[]
|
||||
{
|
||||
Ev(1, "OMK-API-HTTP-001", ClientA, ApiA, "Production", operationId: operationId, component: "Omika.Api"),
|
||||
Ev(2, "OMK-WKR-SYNC-001", ClientA, WkrA, "Production", operationId: operationId, component: "Omika.Worker")
|
||||
});
|
||||
|
||||
var model = new TracesModel(repo) { OperationId = operationId.ToString() };
|
||||
await model.OnGetAsync();
|
||||
|
||||
Assert.Equal(2, model.Timeline.Count);
|
||||
DiagnosticEventRecord worker = model.Timeline.Single(e => e.Component == "Omika.Worker");
|
||||
|
||||
Assert.Equal(WkrA, worker.ServerInstance);
|
||||
Assert.NotEqual(ApiA, worker.ServerInstance);
|
||||
}
|
||||
|
||||
// --------------------------- G30 : dashboard varie par client --------------
|
||||
[Fact]
|
||||
public async Task G30_Dashboard_StatsVaryByClient()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
DateTimeOffset now = DateTimeOffset.UtcNow;
|
||||
await repo.InsertBatchAsync(new[]
|
||||
{
|
||||
Ev(1, client: ClientA, server: ApiA, environment: "Production", ts: now.AddMinutes(-30)),
|
||||
Ev(2, client: ClientA, server: ApiA, environment: "Production", ts: now.AddMinutes(-20)),
|
||||
Ev(3, client: ClientA, server: WkrA, environment: "Production", ts: now.AddMinutes(-10)),
|
||||
Ev(4, client: ClientB, server: "API-B-01", environment: "Production", ts: now.AddMinutes(-5))
|
||||
});
|
||||
|
||||
var aModel = new IndexModel(repo) { ClientCode = ClientA };
|
||||
await aModel.OnGetAsync();
|
||||
|
||||
var bModel = new IndexModel(repo) { ClientCode = ClientB };
|
||||
await bModel.OnGetAsync();
|
||||
|
||||
// Les statistiques changent réellement selon le client.
|
||||
Assert.Equal(3, aModel.TotalEvents);
|
||||
Assert.Equal(1, bModel.TotalEvents);
|
||||
Assert.NotEqual(aModel.TotalEvents, bModel.TotalEvents);
|
||||
}
|
||||
|
||||
// --------------------------- G31 : Telemetry filtre Client -----------------
|
||||
[Fact]
|
||||
public async Task G31_Telemetry_ClientFilterModifiesDataset()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
DateTimeOffset now = DateTimeOffset.UtcNow;
|
||||
await repo.InsertBatchAsync(new[]
|
||||
{
|
||||
Ev(1, client: ClientA, server: ApiA, environment: "Production", ts: now.AddMinutes(-30)),
|
||||
Ev(2, client: ClientA, server: WkrA, environment: "Production", ts: now.AddMinutes(-20)),
|
||||
Ev(3, client: ClientB, server: "API-B-01", environment: "Production", ts: now.AddMinutes(-10)),
|
||||
Ev(4, client: ClientC, server: "API-C-DEV-01", environment: "Development", ts: now.AddMinutes(-5))
|
||||
});
|
||||
|
||||
var aModel = new TelemetryModel(repo) { ClientCode = ClientA };
|
||||
await aModel.OnGetAsync();
|
||||
|
||||
var cModel = new TelemetryModel(repo) { ClientCode = ClientC };
|
||||
await cModel.OnGetAsync();
|
||||
|
||||
Assert.Equal(2, aModel.TotalEvents);
|
||||
Assert.Equal(1, cModel.TotalEvents);
|
||||
Assert.NotEqual(aModel.TotalEvents, cModel.TotalEvents);
|
||||
}
|
||||
|
||||
// --------------------------- G32 : Telemetry Client + Environment ----------
|
||||
[Fact]
|
||||
public async Task G32_Telemetry_ClientAndEnvironmentAreCombinable()
|
||||
{
|
||||
var repo = new FakeDiagnosticEventRepository();
|
||||
DateTimeOffset now = DateTimeOffset.UtcNow;
|
||||
await repo.InsertBatchAsync(new[]
|
||||
{
|
||||
Ev(1, client: ClientB, server: "API-B-01", environment: "Production", ts: now.AddMinutes(-30)),
|
||||
Ev(2, client: ClientB, server: "API-B-01", environment: "Production", ts: now.AddMinutes(-20)),
|
||||
Ev(3, client: ClientB, server: "API-B-STG-01", environment: "Staging", ts: now.AddMinutes(-10))
|
||||
});
|
||||
|
||||
var prodModel = new TelemetryModel(repo) { ClientCode = ClientB, Environment = "Production" };
|
||||
await prodModel.OnGetAsync();
|
||||
|
||||
var stagingModel = new TelemetryModel(repo) { ClientCode = ClientB, Environment = "Staging" };
|
||||
await stagingModel.OnGetAsync();
|
||||
|
||||
Assert.Equal(2, prodModel.TotalEvents);
|
||||
Assert.Equal(1, stagingModel.TotalEvents);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user