test(playwright): Audit Log non-API-no-cURL + drawer-close edge cases (Wave 4)
This commit is contained in:
@@ -765,4 +765,116 @@ public class AuditLogPageTests
|
||||
// The audit results grid never rendered for the unauthorized user.
|
||||
Assert.Equal(0, await page.Locator("[data-test='audit-results-grid']").CountAsync());
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task NonApiRow_Drawer_OmitsCopyAsCurl()
|
||||
{
|
||||
Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason);
|
||||
|
||||
// The Copy-as-cURL action is gated on AuditEventDetail.IsApiChannel, which
|
||||
// returns true only for ApiOutbound/ApiInbound. A DbOutbound row's drawer
|
||||
// must therefore render WITHOUT the cURL button — the negative of
|
||||
// CopyAsCurlButton_IsVisibleAndClickableForApiInbound. We seed one
|
||||
// DbOutbound row, open its drawer, and assert the drawer is open AND the
|
||||
// cURL button is absent.
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/wave4-audit2/{runId}/";
|
||||
var dbId = Guid.NewGuid();
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
await AuditDataSeeder.InsertAuditEventAsync(
|
||||
eventId: dbId,
|
||||
occurredAtUtc: now,
|
||||
channel: "DbOutbound",
|
||||
kind: "DbWrite",
|
||||
status: "Delivered",
|
||||
target: targetPrefix + "dbrow",
|
||||
durationMs: 17);
|
||||
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}/audit/log");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// Filter to the seeded row (contains-match), then Apply to populate the
|
||||
// grid — it stays empty until the user filters.
|
||||
await page.FillAsync("#audit-target", targetPrefix + "dbrow");
|
||||
await page.ClickAsync("[data-test='filter-apply']");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
var row = page.Locator($"[data-test='grid-row-{dbId}']");
|
||||
await Assertions.Expect(row).ToBeVisibleAsync();
|
||||
await row.ClickAsync();
|
||||
|
||||
// The drawer opens for the DbOutbound row, but the cURL action — gated
|
||||
// on IsApiChannel — is absent.
|
||||
await Assertions.Expect(page.Locator("[data-test='audit-drilldown-drawer']")).ToBeVisibleAsync();
|
||||
await Assertions.Expect(page.Locator("[data-test='copy-as-curl']")).ToHaveCountAsync(0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await AuditDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task Drawer_CloseControls_DismissTheDrawer()
|
||||
{
|
||||
Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason);
|
||||
|
||||
// The drawer offers two wired close paths — the header X
|
||||
// ([data-test='drawer-close']) and the footer Close button
|
||||
// ([data-test='drawer-close-footer']), both bound to HandleClose. We open
|
||||
// the drawer, dismiss via the X, re-open, then dismiss via the footer,
|
||||
// asserting the drawer is gone (count 0) after each.
|
||||
// Escape-to-close is NOT wired on AuditDrilldownDrawer (only
|
||||
// ExecutionDetailModal has a keydown handler); covering the X and
|
||||
// footer-Close paths that ARE wired.
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/wave4-audit2c/{runId}/";
|
||||
var apiId = Guid.NewGuid();
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
await AuditDataSeeder.InsertAuditEventAsync(
|
||||
eventId: apiId,
|
||||
occurredAtUtc: now,
|
||||
channel: "ApiOutbound",
|
||||
kind: "ApiCall",
|
||||
status: "Delivered",
|
||||
target: targetPrefix + "row",
|
||||
httpStatus: 200,
|
||||
durationMs: 42);
|
||||
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}/audit/log");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
await page.FillAsync("#audit-target", targetPrefix + "row");
|
||||
await page.ClickAsync("[data-test='filter-apply']");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
var row = page.Locator($"[data-test='grid-row-{apiId}']");
|
||||
var drawer = page.Locator("[data-test='audit-drilldown-drawer']");
|
||||
|
||||
// Open, then dismiss via the header X.
|
||||
await Assertions.Expect(row).ToBeVisibleAsync();
|
||||
await row.ClickAsync();
|
||||
await Assertions.Expect(drawer).ToBeVisibleAsync();
|
||||
await page.ClickAsync("[data-test='drawer-close']");
|
||||
await Assertions.Expect(drawer).ToHaveCountAsync(0);
|
||||
|
||||
// Re-open, then dismiss via the footer Close button.
|
||||
await row.ClickAsync();
|
||||
await Assertions.Expect(drawer).ToBeVisibleAsync();
|
||||
await page.ClickAsync("[data-test='drawer-close-footer']");
|
||||
await Assertions.Expect(drawer).ToHaveCountAsync(0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await AuditDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user