admin: live query detail becomes a modal, live/history and period pickers become tabs and radios, client delete confirms in a dialog
the streamed-query detail panel is now a rac modal dialog with focus containment and restore. the live/history switch is rac tabs driven by the url, the overview period picker is a rac radio group, and the clients delete flow uses the shared confirm dialog; an authority turn keeps the dialog open and withdraws only the destructive action.
This commit is contained in:
@@ -12,6 +12,7 @@ import { createAppRouter } from "@/routes";
|
||||
import { health } from "@/lib/healthFixture";
|
||||
import type { Client, Coverage, QueriesPage, QueryRow } from "@/lib/types";
|
||||
import { queryRow } from "@/features/provenance/provenanceFixture";
|
||||
import { FakeEventSource } from "./fakeEventSource";
|
||||
|
||||
function client(id: number, ip: string, name: string, learnedName: string): Client {
|
||||
return {
|
||||
@@ -544,6 +545,40 @@ test("the policy simulation is reachable from the header, with no rows to click
|
||||
expect(history.location.pathname).toBe("/activity/test");
|
||||
});
|
||||
|
||||
test("the mode switch is a tab list whose selection is the url, and it keeps the filters", async () => {
|
||||
// Live opens a stream as soon as its panel mounts, so the switch cannot be
|
||||
// exercised without one; the fake stands in for the browser's EventSource.
|
||||
vi.stubGlobal(
|
||||
"EventSource",
|
||||
class {
|
||||
constructor(url: string) {
|
||||
return new FakeEventSource(url) as unknown as EventSource;
|
||||
}
|
||||
},
|
||||
);
|
||||
const { history } = renderPage("/activity?mode=history&domain=ads&blocked=true");
|
||||
await screen.findByText("ads.example");
|
||||
|
||||
const tabs = within(screen.getByRole("tablist", { name: "Activity mode" }));
|
||||
expect(tabs.getAllByRole("tab").map((tab) => tab.textContent)).toEqual(["History", "Live"]);
|
||||
expect(tabs.getByRole("tab", { name: "History", selected: true })).toBeTruthy();
|
||||
expect(tabs.getByRole("tab", { name: "Live", selected: false })).toBeTruthy();
|
||||
|
||||
fireEvent.click(tabs.getByRole("tab", { name: "Live" }));
|
||||
|
||||
await waitFor(() => expect(history.location.search).toContain("mode=live"));
|
||||
// The investigation survives the switch: both filters are still in the URL.
|
||||
expect(history.location.search).toContain("domain=ads");
|
||||
expect(history.location.search).toContain("blocked=true");
|
||||
expect(
|
||||
within(screen.getByRole("tablist", { name: "Activity mode" })).getByRole("tab", {
|
||||
name: "Live",
|
||||
selected: true,
|
||||
}),
|
||||
).toBeTruthy();
|
||||
expect(await screen.findByText(/these filters apply to history only/)).toBeTruthy();
|
||||
});
|
||||
|
||||
test("Clear empties the url as well as the form", async () => {
|
||||
const { history } = renderPage("/activity?mode=history&domain=ads&blocked=true");
|
||||
await screen.findByText("ads.example");
|
||||
|
||||
Reference in New Issue
Block a user