admin: reclaim the desktop header, move pause and log out to the sidebar
the header row survives only on narrow screens; on desktop its lone occupant, log out, joins pause in the sidebar footer, both full width. pause leaves the query detail page's related actions, where a global control had no business, and its hand-rolled duration dropdown becomes a react-aria menu with real keyboard navigation, dismissal and positioning.
This commit is contained in:
@@ -214,12 +214,45 @@ test("mount probe reveals the logout button and a failed logout surfaces inline"
|
||||
|
||||
renderShell();
|
||||
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Log out" }));
|
||||
// Both renderings are mounted; the viewport paints the sidebar one on WIDE
|
||||
// and the header one below it.
|
||||
await waitFor(() => expect(screen.getAllByRole("button", { name: "Log out" })).toHaveLength(2));
|
||||
const aside = document.querySelector("aside") as HTMLElement;
|
||||
fireEvent.click(within(aside).getByRole("button", { name: "Log out" }));
|
||||
|
||||
await screen.findByText("Rate limited. Try again in 7s.");
|
||||
await within(aside).findByText("Rate limited. Try again in 7s.");
|
||||
expect(screen.getByRole("heading", { name: "Overview" })).toBeTruthy();
|
||||
});
|
||||
|
||||
test("Log out sits in the sidebar on wide, and only in the header below it", async () => {
|
||||
stubFetch((url) =>
|
||||
url === "/api/auth/login"
|
||||
? new Response(JSON.stringify({ error: "password required" }), {
|
||||
status: 401,
|
||||
headers: { "content-type": "application/json" },
|
||||
})
|
||||
: null,
|
||||
);
|
||||
renderShell();
|
||||
await screen.findByRole("heading", { name: "Overview" });
|
||||
|
||||
const aside = document.querySelector("aside") as HTMLElement;
|
||||
const header = document.querySelector("header") as HTMLElement;
|
||||
await waitFor(() => expect(within(aside).getByRole("button", { name: "Log out" })).toBeTruthy());
|
||||
expect(within(header).getByRole("button", { name: "Log out" })).toBeTruthy();
|
||||
// The header is the narrow rendering now: the Menu button is its only nav.
|
||||
expect(within(header).getByRole("button", { name: "Menu" })).toBeTruthy();
|
||||
|
||||
// In the sidebar the control precedes the version label rather than crowding it.
|
||||
const version = within(aside).getByText(/^nxdns v/);
|
||||
const logout = within(aside).getByRole("button", { name: "Log out" });
|
||||
expect(logout.compareDocumentPosition(version) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
||||
// The drawer keeps no third copy: the header already carries the narrow one.
|
||||
fireEvent.click(within(header).getByRole("button", { name: "Menu" }));
|
||||
const drawer = document.getElementById("mobile-nav") as HTMLElement;
|
||||
expect(within(drawer).queryByRole("button", { name: "Log out" })).toBeNull();
|
||||
});
|
||||
|
||||
test("the header carries no protection display at all any more", async () => {
|
||||
renderShell();
|
||||
await screen.findByRole("heading", { name: "Overview" });
|
||||
|
||||
Reference in New Issue
Block a user