From 0dbad22967c78934cfea79df085fa5eee6ca0cd1 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 1 Aug 2026 22:39:31 -0700 Subject: [PATCH] Improve empty attack history guidance Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 27bb1063-02b1-4e82-a704-cedc542aa446 --- frontend/e2e/history.spec.ts | 31 +++++++++ frontend/src/App.test.tsx | 38 ++++++++++ frontend/src/App.tsx | 2 + .../components/History/AttackHistory.test.tsx | 69 +++++++++++++++++-- .../src/components/History/AttackHistory.tsx | 29 ++++++-- 5 files changed, 160 insertions(+), 9 deletions(-) diff --git a/frontend/e2e/history.spec.ts b/frontend/e2e/history.spec.ts index dbe62b9616..18e7ef09fc 100644 --- a/frontend/e2e/history.spec.ts +++ b/frontend/e2e/history.spec.ts @@ -344,3 +344,34 @@ test.describe("Attack History Filters", () => { await expect(page.getByTestId("attack-row-atk-page-000")).toBeVisible({ timeout: 5_000 }); }); }); + +test.describe("Attack History empty state", () => { + test("guides keyboard users to target configuration and preserves Back navigation", async ({ page }) => { + await mockHistoryAPIs(page, { attacks: [] }); + await page.route(/\/api\/targets(?:\?|$)/, async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify({ + items: [], + pagination: { limit: 200, has_more: false, next_cursor: null, prev_cursor: null }, + }), + }); + }); + + await page.goto("/history"); + + const configureTargetButton = page.getByRole("button", { name: "Configure target" }); + await expect(configureTargetButton).toBeVisible(); + await configureTargetButton.focus(); + await expect(configureTargetButton).toBeFocused(); + await configureTargetButton.press("Enter"); + + await expect(page).toHaveURL(/\/config$/); + await expect(page.getByRole("heading", { level: 1, name: "Target Configuration" })).toBeVisible(); + + await page.goBack(); + await expect(page).toHaveURL(/\/history$/); + await expect(page.getByRole("button", { name: "Configure target" })).toBeVisible(); + }); +}); diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 9f5df1d3be..cc7ad97cfd 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -210,14 +210,28 @@ jest.mock("./components/History/AttackHistory", () => { onOpenAttack, filters, onFiltersChange, + activeTarget, + onNavigate, }: { onOpenAttack: (attackResultId: string) => void; filters: Record; onFiltersChange: (filters: Record) => void; + activeTarget: unknown; + onNavigate: (view: string) => void; }) => { return (
{JSON.stringify(filters)} + {activeTarget ? "yes" : "no"} + {activeTarget ? ( + + ) : ( + + )} + )}
) : (