feat(centralui): execution-chain tree view on the Audit Log page
This commit is contained in:
@@ -429,6 +429,88 @@ public class AuditLogPageTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DrillInToExecutionChain_RendersTree_AndNodeClickFiltersGrid()
|
||||
{
|
||||
// Audit Log ParentExecutionId feature, Task 10: the drawer's "View
|
||||
// execution chain" action opens /audit/execution-tree?executionId={id}.
|
||||
// We seed a spawner row + a child row, open the child's drawer, click
|
||||
// "View execution chain", assert the tree renders BOTH executions, then
|
||||
// click the spawner node and assert the Audit Log grid filters to it.
|
||||
if (!await AuditDataSeeder.IsAvailableAsync())
|
||||
{
|
||||
throw new InvalidOperationException("MSSQL unavailable; see FilterNarrowing test for setup instructions.");
|
||||
}
|
||||
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/exec-chain-tree/{runId}/";
|
||||
var parentExecutionId = Guid.NewGuid();
|
||||
var childExecutionId = Guid.NewGuid();
|
||||
var spawnerEventId = Guid.NewGuid();
|
||||
var childEventId = Guid.NewGuid();
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
// Spawner execution's own row.
|
||||
await AuditDataSeeder.InsertAuditEventAsync(
|
||||
eventId: spawnerEventId,
|
||||
occurredAtUtc: now,
|
||||
channel: "ApiInbound",
|
||||
kind: "InboundRequest",
|
||||
status: "Delivered",
|
||||
target: targetPrefix + "spawner",
|
||||
executionId: parentExecutionId,
|
||||
httpStatus: 200,
|
||||
durationMs: 7);
|
||||
|
||||
// Child (spawned) row — links to the spawner via ParentExecutionId.
|
||||
await AuditDataSeeder.InsertAuditEventAsync(
|
||||
eventId: childEventId,
|
||||
occurredAtUtc: now,
|
||||
channel: "ApiOutbound",
|
||||
kind: "ApiCall",
|
||||
status: "Delivered",
|
||||
target: targetPrefix + "child",
|
||||
executionId: childExecutionId,
|
||||
parentExecutionId: parentExecutionId,
|
||||
httpStatus: 200,
|
||||
durationMs: 13);
|
||||
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
|
||||
// Open the child row's drawer via its ExecutionId filter.
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}/audit/log?executionId={childExecutionId}");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
var childRow = page.Locator($"[data-test='grid-row-{childEventId}']");
|
||||
await Assertions.Expect(childRow).ToBeVisibleAsync();
|
||||
await childRow.ClickAsync();
|
||||
|
||||
// "View execution chain" opens the tree view.
|
||||
var viewChain = page.Locator("[data-test='view-execution-chain']");
|
||||
await Assertions.Expect(viewChain).ToBeVisibleAsync();
|
||||
await viewChain.ClickAsync();
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// The tree page rendered both executions as nodes.
|
||||
Assert.Contains($"executionId={childExecutionId}", page.Url);
|
||||
await Assertions.Expect(page.Locator($"[data-test='tree-node-{parentExecutionId}']")).ToBeVisibleAsync();
|
||||
await Assertions.Expect(page.Locator($"[data-test='tree-node-{childExecutionId}']")).ToBeVisibleAsync();
|
||||
|
||||
// Clicking the spawner node's link filters the Audit Log to its rows.
|
||||
await page.Locator($"[data-test='tree-node-link-{parentExecutionId}']").ClickAsync();
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
Assert.Contains($"executionId={parentExecutionId}", page.Url);
|
||||
await Assertions.Expect(page.Locator($"[data-test='grid-row-{spawnerEventId}']")).ToBeVisibleAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
await AuditDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NotificationsPage_RendersAuditDrillInLinkPattern()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user