fix(ui): unify Session navigation and restore uniform tab borders
This commit is contained in:
@@ -95,7 +95,7 @@ test("Back and Core navigation preserve a Memory draft until the editor cancels
|
||||
act(() => window.history.back());
|
||||
await waitFor(() => expect(new URLSearchParams(window.location.search).get("thoth_route")).toBe("administration/memory"));
|
||||
expect(within(page).getByLabelText("Title")).toHaveValue("Keep this draft");
|
||||
await userEvent.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(page).toBeVisible();
|
||||
expect(confirm).not.toHaveBeenCalled();
|
||||
confirm.mockReturnValue(true);
|
||||
@@ -138,7 +138,7 @@ test("option A has one collapsible global context and preserves the Core draft a
|
||||
await userEvent.click(screen.getByRole("button", { name: "Memory" }));
|
||||
expect(await screen.findByRole("main", { name: "Memory management" })).toBeVisible();
|
||||
expect(screen.queryByRole("textbox", { name: /new question/i })).not.toBeInTheDocument();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(screen.getByRole("textbox", { name: /new question/i })).toBe(composer);
|
||||
expect(composer).toHaveValue("Keep my original Core question");
|
||||
});
|
||||
@@ -149,7 +149,7 @@ test("invalid remembered choices do not silently fall back and gate both Core an
|
||||
window.history.replaceState(null, "", "/?thoth_route=administration/memory");
|
||||
renderShell();
|
||||
await screen.findByText(/Unavailable saved choices are not replaced/);
|
||||
expect(screen.getByRole("button", { name: "New session" })).toBeDisabled();
|
||||
expect(screen.getByRole("button", { name: "Session" })).toBeDisabled();
|
||||
expect(screen.queryByRole("main", { name: "Memory management" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("textbox", { name: /new question/i })).not.toBeInTheDocument();
|
||||
await userEvent.selectOptions(screen.getByRole("combobox", { name: "Workspace" }), "alpha");
|
||||
@@ -193,7 +193,7 @@ test("dirty Memory blocks workspace and model changes, including after a failed
|
||||
await userEvent.click(within(page).getByRole("button", { name: "Save card" }));
|
||||
await waitFor(() => expect(saveAttempts).toBe(1));
|
||||
expect(await within(page).findByRole("alert")).toBeVisible();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(page).toBeVisible();
|
||||
expect(within(page).getByLabelText("Title")).toHaveValue("Do not lose this");
|
||||
});
|
||||
@@ -245,12 +245,12 @@ test("a successful Memory save releases the navigation guard and the context loc
|
||||
await userEvent.click(screen.getByRole("button", { name: /Working context/ }));
|
||||
await userEvent.click(within(page).getByRole("button", { name: "Save card" }));
|
||||
expect(screen.getByRole("combobox", { name: "Model" })).toBeDisabled();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(page).toBeVisible();
|
||||
await act(async () => release());
|
||||
await within(page).findByText("Saved and indexed.");
|
||||
expect(screen.getByRole("combobox", { name: "Model" })).toBeEnabled();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(await screen.findByRole("textbox", { name: /new question/i })).toBeVisible();
|
||||
});
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ describe("authenticated shell permissions", () => {
|
||||
test("hides administrative navigation from a session user", async () => {
|
||||
renderShell({ subject: "user-1", isAdmin: false, roles: ["user"], permissions: ["session.use"] });
|
||||
|
||||
expect(await screen.findByRole("button", { name: "New session" })).toBeInTheDocument();
|
||||
expect(await screen.findByRole("button", { name: "Session" })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Administration" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Database" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Workspace" })).not.toBeInTheDocument();
|
||||
|
||||
@@ -105,7 +105,7 @@ test("starts on the core activity after a hard refresh even if metadata manageme
|
||||
await expandAdministration();
|
||||
|
||||
const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" });
|
||||
expect(within(sessionNavigation).getByRole("button", { name: "New session" }))
|
||||
expect(within(sessionNavigation).getByRole("button", { name: "Session" }))
|
||||
.toHaveAttribute("aria-current", "page");
|
||||
expect(within(sessionNavigation).getByRole("button", { name: "Database" }))
|
||||
.not.toHaveAttribute("aria-current");
|
||||
@@ -118,7 +118,7 @@ test("replaces the core conversation while keeping the session navigation", asyn
|
||||
|
||||
const conversationColumn = screen.getByTestId("conversation-column");
|
||||
const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" });
|
||||
const newSession = within(sessionNavigation).getByRole("button", { name: "New session" });
|
||||
const newSession = within(sessionNavigation).getByRole("button", { name: "Session" });
|
||||
const databaseManagement = within(sessionNavigation).getByRole("button", { name: "Database" });
|
||||
|
||||
expect(newSession).toHaveAttribute("aria-current", "page");
|
||||
@@ -146,6 +146,7 @@ test("replaces the core conversation while keeping the session navigation", asyn
|
||||
});
|
||||
|
||||
test("keeps a live core session connected while returning from database management", async () => {
|
||||
let resumes = 0;
|
||||
server.use(
|
||||
http.get("/api/sessions", () => HttpResponse.json([{
|
||||
id: "s1",
|
||||
@@ -160,10 +161,10 @@ test("keeps a live core session connected while returning from database manageme
|
||||
archived: false,
|
||||
active: true,
|
||||
}])),
|
||||
http.post("/api/sessions/:id/resume", ({ params }) => HttpResponse.json({
|
||||
http.post("/api/sessions/:id/resume", ({ params }) => { resumes++; return HttpResponse.json({
|
||||
id: params.id,
|
||||
alreadyActive: true,
|
||||
})),
|
||||
}); }),
|
||||
http.get("/api/sessions/:id", ({ params }) => HttpResponse.json({
|
||||
id: params.id,
|
||||
status: "open",
|
||||
@@ -185,13 +186,19 @@ test("keeps a live core session connected while returning from database manageme
|
||||
expect(FakeEventSource.instances).toHaveLength(1);
|
||||
|
||||
expect(session).toBeVisible();
|
||||
await userEvent.click(session);
|
||||
expect(screen.queryByRole("button", { name: "Return to session" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "New session" })).not.toBeInTheDocument();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("main", { name: "Database management" })).not.toBeInTheDocument();
|
||||
});
|
||||
expect(source.closed).toBe(false);
|
||||
expect(FakeEventSource.instances).toHaveLength(1);
|
||||
expect(resumes).toBe(1);
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(source.closed).toBe(false);
|
||||
expect(resumes).toBe(1);
|
||||
});
|
||||
|
||||
test("hides the complete administrative navigation from a regular user", () => {
|
||||
@@ -208,7 +215,7 @@ test("hides the complete administrative navigation from a regular user", () => {
|
||||
|
||||
renderShell();
|
||||
|
||||
expect(screen.getByRole("button", { name: "New session" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Session" })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Administration" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Workspace" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Database" })).not.toBeInTheDocument();
|
||||
@@ -256,7 +263,7 @@ test("requires saving or cancelling a dirty database form before leaving", async
|
||||
await userEvent.clear(schema);
|
||||
await userEvent.type(schema, "reporting");
|
||||
|
||||
const newSession = screen.getByRole("button", { name: "New session" });
|
||||
const newSession = screen.getByRole("button", { name: "Session" });
|
||||
await userEvent.click(newSession);
|
||||
|
||||
expect(confirm).not.toHaveBeenCalled();
|
||||
|
||||
@@ -47,9 +47,11 @@ beforeEach(() => {
|
||||
);
|
||||
});
|
||||
|
||||
test("New session starts prewarm without delaying composer focus", async () => {
|
||||
test("Session prepares a new question without creating a session before submission", async () => {
|
||||
let prewarmStarted = false;
|
||||
const create = vi.fn(() => HttpResponse.json({ id: "unexpected" }));
|
||||
server.use(
|
||||
http.post("/api/sessions", create),
|
||||
http.post("/api/runtime/prewarm", async () => {
|
||||
prewarmStarted = true;
|
||||
await delay(100);
|
||||
@@ -58,16 +60,18 @@ test("New session starts prewarm without delaying composer focus", async () => {
|
||||
);
|
||||
renderShell();
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: /^new session$/i }));
|
||||
await userEvent.click(screen.getByRole("button", { name: /^Session$/i }));
|
||||
|
||||
const composer = await screen.findByRole("textbox", { name: /new question/i });
|
||||
await waitFor(() => expect(prewarmStarted).toBe(true));
|
||||
await waitFor(() => expect(composer).toHaveFocus());
|
||||
expect(composer).toHaveAttribute("data-awaiting-input", "true");
|
||||
expect(composer).toHaveClass("thot-awaiting-input");
|
||||
expect(create).not.toHaveBeenCalled();
|
||||
expect(screen.getAllByRole("button", { name: "Session" })).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("a known preprocessing requirement disables New session", async () => {
|
||||
test("a known preprocessing requirement disables Session when no session is open", async () => {
|
||||
server.use(
|
||||
http.get("/api/workspaces/default/preprocessing", () => HttpResponse.json({
|
||||
schemaVersion: 1,
|
||||
@@ -81,7 +85,7 @@ test("a known preprocessing requirement disables New session", async () => {
|
||||
);
|
||||
renderShell();
|
||||
|
||||
const newSession = screen.getByRole("button", { name: "New session" });
|
||||
const newSession = screen.getByRole("button", { name: "Session" });
|
||||
await waitFor(() => expect(newSession).toBeDisabled());
|
||||
expect(newSession).toHaveAttribute("data-navigation-state", "unavailable");
|
||||
await waitFor(() => expect(newSession).toHaveAttribute("title", "Catalog revision 18 is not indexed."));
|
||||
@@ -110,6 +114,10 @@ test("records the prompt without central duplication, then opens the live log",
|
||||
phase: "F1",
|
||||
text: "How many patients?",
|
||||
});
|
||||
// Clicking the unified navigation while creation is pending must not discard
|
||||
// its operation token or the provisional transcript.
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(useSessionStore.getState().activityLog[0]?.text).toBe("How many patients?");
|
||||
releaseCreate();
|
||||
await waitFor(() => expect(FakeEventSource.instances).toHaveLength(1));
|
||||
act(() => FakeEventSource.instances[0].emit({ type: "text_delta", text: "Inspecting cohort" }));
|
||||
@@ -211,7 +219,7 @@ test("opens Workspace management from the right sidebar without interrupting the
|
||||
const workArea = screen.getByTestId("conversation-column");
|
||||
const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" });
|
||||
const workspaceManagement = within(sessionNavigation).getByRole("button", { name: "Workspace" });
|
||||
const newSession = within(sessionNavigation).getByRole("button", { name: "New session" });
|
||||
const newSession = within(sessionNavigation).getByRole("button", { name: "Session" });
|
||||
expect(workArea).toContainElement(dialog);
|
||||
expect(sessionNavigation).not.toContainElement(dialog);
|
||||
expect(screen.getByTestId("app-shell")).toHaveAttribute("data-activity-layout", "closed");
|
||||
@@ -222,7 +230,7 @@ test("opens Workspace management from the right sidebar without interrupting the
|
||||
expect(newSession).toHaveAttribute("data-navigation-state", "available");
|
||||
expect(newSession).not.toHaveAttribute("aria-current");
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
await waitFor(() => expect(screen.queryByRole("main", { name: "Workspace management" })).not.toBeInTheDocument());
|
||||
expect(newSession).toHaveAttribute("aria-current", "page");
|
||||
expect(newSession).toHaveAttribute("data-navigation-state", "current");
|
||||
@@ -240,7 +248,7 @@ test("does not block the shell when the DWH is unavailable at startup", async ()
|
||||
);
|
||||
renderShell();
|
||||
|
||||
expect(await screen.findByRole("button", { name: "New session" })).toBeVisible();
|
||||
expect(await screen.findByRole("button", { name: "Session" })).toBeVisible();
|
||||
expect(screen.queryByRole("button", { name: "Administration" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("heading", { name: "Connection unavailable" })).not.toBeInTheDocument();
|
||||
expect(healthChecks).toBe(0);
|
||||
|
||||
@@ -136,7 +136,7 @@ test("Pi management preserves the open session summary and the model activity ti
|
||||
const workArea = screen.getByTestId("conversation-column");
|
||||
const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" });
|
||||
const piManagement = within(sessionNavigation).getByRole("button", { name: "Pi configuration" });
|
||||
const newSession = within(sessionNavigation).getByRole("button", { name: "New session" });
|
||||
const newSession = within(sessionNavigation).getByRole("button", { name: "Session" });
|
||||
expect(workArea).toContainElement(dialog);
|
||||
expect(sessionNavigation).not.toContainElement(dialog);
|
||||
expect(piManagement).toHaveAttribute("aria-current", "page");
|
||||
@@ -147,7 +147,9 @@ test("Pi management preserves the open session summary and the model activity ti
|
||||
const preservedSummary = document.querySelector('[aria-label="Session summary"]');
|
||||
expect(preservedSummary).toHaveAttribute("aria-hidden", "true");
|
||||
expect(preservedSummary).toHaveTextContent("Attiva uno");
|
||||
await user.click(screen.getByRole("button", { name: "Return to session" }));
|
||||
// A cold document panel is not a running session. Reopen it from its row;
|
||||
// the unified Session action would prepare a new question instead.
|
||||
await user.click(screen.getByTestId("session-item-s1"));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole("complementary", { name: "Session summary" })).toHaveTextContent("Domanda originale");
|
||||
});
|
||||
@@ -160,7 +162,7 @@ test("Pi management preserves the open session summary and the model activity ti
|
||||
await screen.findByRole("button", { name: "Show model activity" });
|
||||
act(() => useSessionStore.getState().setLastUserEntry({ kind: "input", text: "Preserved activity" }));
|
||||
await user.click(screen.getByRole("button", { name: "Pi configuration" }));
|
||||
await user.click(await screen.findByRole("button", { name: "Return to session" }));
|
||||
await user.click(await screen.findByRole("button", { name: "Session" }));
|
||||
await waitFor(() => expect(screen.queryByRole("heading", { name: "Pi management" })).not.toBeInTheDocument());
|
||||
await user.click(screen.getByRole("button", { name: "Show model activity" }));
|
||||
expect(await screen.findByRole("heading", { name: "Model activity" })).toBeVisible();
|
||||
@@ -190,8 +192,10 @@ test("administrators can explicitly switch to all sessions and see owners", asyn
|
||||
expect(mySessions).toHaveAttribute("tabindex", "0");
|
||||
expect(mySessions).toHaveAttribute("data-tab-state", "active");
|
||||
expect(mySessions).toHaveClass("bg-[oklch(var(--nav-active))]");
|
||||
expect(mySessions).toHaveClass("border-b-0");
|
||||
expect(allSessions).toHaveClass("border-b-0");
|
||||
expect(mySessions).toHaveClass("border", "px-[11px]", "py-[3px]");
|
||||
expect(allSessions).toHaveClass("border", "px-[11px]", "py-[3px]");
|
||||
expect(mySessions).not.toHaveClass("border-b-0", "border-b-2", "-mb-px");
|
||||
expect(tablist).not.toHaveClass("border-b");
|
||||
expect(allSessions).toHaveAttribute("aria-selected", "false");
|
||||
expect(allSessions).toHaveAttribute("aria-controls", "session-scope-panel");
|
||||
expect(allSessions).toHaveAttribute("tabindex", "-1");
|
||||
@@ -403,7 +407,7 @@ test("New session closes an open session detail panel", async () => {
|
||||
wrap();
|
||||
await userEvent.click(await screen.findByText("Attiva uno")); // cold session → panel opens
|
||||
await screen.findByText("Domanda originale");
|
||||
await userEvent.click(screen.getByRole("button", { name: /^new session$/i }));
|
||||
await userEvent.click(screen.getByRole("button", { name: /^Session$/i }));
|
||||
await waitFor(() => expect(screen.queryByText("Domanda originale")).not.toBeInTheDocument());
|
||||
expect(screen.getByText(/type your question/i)).toBeInTheDocument();
|
||||
});
|
||||
@@ -822,7 +826,7 @@ test("starting a new question invalidates a pending Resume intent", async () =>
|
||||
await userEvent.click(await screen.findByText("Attiva uno"));
|
||||
await userEvent.click(await screen.findByRole("button", { name: /resume/i }));
|
||||
await resumeStarted.promise;
|
||||
await userEvent.click(screen.getByRole("button", { name: /^new session$/i }));
|
||||
await userEvent.click(screen.getByRole("button", { name: /^Session$/i }));
|
||||
expect(await screen.findByText(/type your question/i)).toBeInTheDocument();
|
||||
|
||||
resumeGate.resolve();
|
||||
|
||||
@@ -61,7 +61,7 @@ interface AppShellProps {
|
||||
const SESSION_SCOPES: readonly SessionScope[] = ["mine", "all"];
|
||||
|
||||
function sessionScopeTabClass(selected: boolean): string {
|
||||
const base = "relative -mb-px flex h-8 w-full cursor-pointer items-center justify-center rounded-t-md border border-b-0 px-2 text-xs font-semibold tracking-[0.005em] outline-none focus-visible:z-10 focus-visible:ring-3 focus-visible:ring-[oklch(var(--nav-active-border)/0.28)]";
|
||||
const base = "relative flex min-h-[38px] w-full cursor-pointer items-center justify-center rounded-md border px-[11px] py-[3px] text-xs font-semibold tracking-[0.005em] outline-none focus-visible:z-10 focus-visible:ring-3 focus-visible:ring-[oklch(var(--nav-active-border)/0.28)]";
|
||||
return selected
|
||||
? `${base} border-[oklch(var(--nav-active-border))] bg-[oklch(var(--nav-active))] text-[oklch(var(--nav-active-foreground))] hover:bg-[oklch(var(--nav-active-hover))]`
|
||||
: `${base} border-border bg-card text-muted-foreground hover:border-muted-foreground/45 hover:bg-muted/55 hover:text-foreground`;
|
||||
@@ -638,6 +638,8 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
deliveredToastCountRef.current = sessionToasts.length;
|
||||
}, [sessionToasts]);
|
||||
const sessionViewOpen = Boolean(activeSessionId) || creatingSession;
|
||||
const canReturnToCurrentSession = creatingSession || (Boolean(activeSessionId) && !finalized && !activeSession?.archived);
|
||||
const sessionActionUnavailable = !canReturnToCurrentSession && (preprocessingBlocksNewSession || !workingContext.ready || administrationBusy);
|
||||
const working = sessionViewOpen && !pendingWidget && agentActive;
|
||||
// The workflow bar runs only while the harness works, not while a finalized
|
||||
// session sits idle or a gate awaits the reviewer (pendingWidget).
|
||||
@@ -965,19 +967,21 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
</div>
|
||||
|
||||
<div className="thot-session-navigation__primary-controls">
|
||||
{activeSurface !== "core" && <Button variant="outline" size="sm" className="w-full" onClick={() => navigate({ surface: "core" })}>{t("Return to session")}</Button>}
|
||||
<Button
|
||||
variant={currentNavigation === "core" ? "navigationActive" : "outline"}
|
||||
size="sm"
|
||||
className="w-full min-w-0 max-w-full gap-[0.25rem] px-[0.75rem]"
|
||||
aria-current={currentNavigation === "core" ? "page" : undefined}
|
||||
data-navigation-state={preprocessingBlocksNewSession || !workingContext.ready || administrationBusy
|
||||
data-navigation-state={sessionActionUnavailable
|
||||
? "unavailable"
|
||||
: currentNavigation === "core" ? "current" : "available"}
|
||||
disabled={preprocessingBlocksNewSession || !workingContext.ready || administrationBusy}
|
||||
title={preprocessingBlocksNewSession ? preprocessingQuery.data?.detail : undefined}
|
||||
onClick={startNewSession}
|
||||
>{t("New session")}</Button>
|
||||
disabled={sessionActionUnavailable}
|
||||
title={sessionActionUnavailable && preprocessingBlocksNewSession ? preprocessingQuery.data?.detail : undefined}
|
||||
onClick={() => {
|
||||
if (canReturnToCurrentSession) navigate({ surface: "core" });
|
||||
else startNewSession();
|
||||
}}
|
||||
>{t("Session")}</Button>
|
||||
{isAdmin && (
|
||||
<Accordion.Root
|
||||
value={adminNavigationValue}
|
||||
@@ -1075,7 +1079,7 @@ export function AppShell({ canLogout }: AppShellProps) {
|
||||
role="tablist"
|
||||
aria-label={t("Session scope")}
|
||||
aria-orientation="horizontal"
|
||||
className="grid grid-cols-2 border-b border-border"
|
||||
className="grid grid-cols-2 gap-1"
|
||||
>
|
||||
<button
|
||||
ref={(node) => { sessionScopeTabRefs.current.mine = node; }}
|
||||
|
||||
@@ -29,7 +29,7 @@ export function NavSessions({
|
||||
if (sessions.length === 0) {
|
||||
return (
|
||||
<p className="px-1 py-6 text-center text-xs text-muted-foreground">
|
||||
{translate("No sessions yet.")} <span className="font-medium text-foreground">{translate("Start with New session.")}</span>
|
||||
{translate("No sessions yet.")} <span className="font-medium text-foreground">{translate("Start with Session.")}</span>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ test("full controls change locale/theme and follow fullscreen entry, exit, Esc,
|
||||
expect(within(header).getByRole("button", { name: "Analyst" })).toBeInTheDocument();
|
||||
expect(within(header).queryByRole("button", { name: /admin|settings/i })).not.toBeInTheDocument();
|
||||
await userEvent.selectOptions(within(header).getByRole("combobox", { name: "Interface language" }), "it");
|
||||
expect(await screen.findByRole("button", { name: "Nuova sessione" })).toBeInTheDocument();
|
||||
expect(await screen.findByRole("button", { name: "Sessione" })).toBeInTheDocument();
|
||||
await userEvent.selectOptions(within(header).getByRole("combobox", { name: "Lingua dell’interfaccia" }), "en");
|
||||
await userEvent.click(within(header).getByRole("button", { name: "Use dark theme" }));
|
||||
expect(document.documentElement).toHaveAttribute("data-bs-theme", "dark");
|
||||
@@ -130,7 +130,7 @@ test("legacy embedded consumes the portal state and supplies no duplicate contro
|
||||
select.dataset.lang = "it";
|
||||
document.body.append(select);
|
||||
render(<App />);
|
||||
expect(await screen.findByRole("button", { name: "Nuova sessione" })).toBeInTheDocument();
|
||||
expect(await screen.findByRole("button", { name: "Sessione" })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("banner", { name: /application|intestazione/i })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /fullscreen|tema|Log out/i })).not.toBeInTheDocument();
|
||||
act(() => { document.documentElement.setAttribute("data-bs-theme", "light"); });
|
||||
@@ -160,8 +160,8 @@ test("reload restores only an authorized session document panel without resuming
|
||||
expect(resume).not.toHaveBeenCalled();
|
||||
expect(FakeEventSource.instances).toHaveLength(0);
|
||||
expect(readRememberedSession(user)).toBe("saved");
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "New session" })).toBeEnabled());
|
||||
await userEvent.click(screen.getByRole("button", { name: "New session" }));
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "Session" })).toBeEnabled());
|
||||
await userEvent.click(screen.getByRole("button", { name: "Session" }));
|
||||
expect(readRememberedSession(user)).toBeNull();
|
||||
});
|
||||
|
||||
@@ -172,7 +172,7 @@ test("reload ignores a session absent from the authorized list and isolates prin
|
||||
expect(readRememberedSession(user)).toBeNull();
|
||||
window.history.replaceState(null, "", "/");
|
||||
render(<App />);
|
||||
await screen.findByRole("button", { name: "New session" });
|
||||
await screen.findByRole("button", { name: "Session" });
|
||||
await waitFor(() => expect(readRememberedSession(user)).toBeNull());
|
||||
expect(screen.queryByRole("button", { name: "Resume" })).not.toBeInTheDocument();
|
||||
expect(FakeEventSource.instances).toHaveLength(0);
|
||||
|
||||
Reference in New Issue
Block a user