From aa378291f9cdbb2621a884f9db6be9f810362c5e Mon Sep 17 00:00:00 2001 From: mptyl Date: Mon, 29 Jun 2026 13:22:09 +0200 Subject: [PATCH] feat(frontend): collapsible group headers; resume/delete integration tests; English test name Co-Authored-By: Claude Sonnet 4.6 --- .../src/shell/AppShell.session-mgmt.test.tsx | 19 ++++++++++++++ frontend/src/shell/AppShell.tsx | 25 +++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/frontend/src/shell/AppShell.session-mgmt.test.tsx b/frontend/src/shell/AppShell.session-mgmt.test.tsx index 3b10eb7f..1c8b3699 100644 --- a/frontend/src/shell/AppShell.session-mgmt.test.tsx +++ b/frontend/src/shell/AppShell.session-mgmt.test.tsx @@ -3,6 +3,7 @@ import userEvent from "@testing-library/user-event"; import { http, HttpResponse } from "msw"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { server } from "../test/msw"; +import { FakeEventSource } from "../test/fakeEventSource"; import { AppShell } from "./AppShell"; function wrap() { @@ -16,6 +17,8 @@ const LIST = [ ]; beforeEach(() => { + FakeEventSource.instances = []; + (globalThis as any).EventSource = FakeEventSource; server.use( http.get("http://localhost:8787/sessions", () => HttpResponse.json(LIST)), http.get("http://localhost:8787/sessions/:id/documents", () => HttpResponse.json([ @@ -43,3 +46,19 @@ test("Archive toggle reveals archived sessions", async () => { await userEvent.click(await screen.findByRole("button", { name: /archive/i })); expect(await screen.findByText("Archiviata due")).toBeInTheDocument(); }); + +test("Resume from the panel activates the session and closes the panel", async () => { + let resumed: string | null = null; + server.use( + http.post("http://localhost:8787/sessions/:id/resume", ({ params }) => { + resumed = params.id as string; + return new HttpResponse(null, { status: 204 }); + }), + ); + wrap(); + await userEvent.click(await screen.findByText("Attiva uno")); + await screen.findByText("Domanda originale"); // panel open + await userEvent.click(screen.getByRole("button", { name: /resume/i })); + await waitFor(() => expect(resumed).toBe("s1")); + await waitFor(() => expect(screen.queryByText("Domanda originale")).not.toBeInTheDocument()); // panel closed +}); diff --git a/frontend/src/shell/AppShell.tsx b/frontend/src/shell/AppShell.tsx index 61675c9d..a543d6b8 100644 --- a/frontend/src/shell/AppShell.tsx +++ b/frontend/src/shell/AppShell.tsx @@ -37,6 +37,7 @@ export function AppShell() { const [showArchive, setShowArchive] = useState(false); const [renameTarget, setRenameTarget] = useState(null); const [deleteTarget, setDeleteTarget] = useState(null); + const [collapsedGroups, setCollapsedGroups] = useState>({}); const groups = useMemo( () => [...new Set(sessions.map((s) => s.group).filter((g): g is string => !!g))].sort(), @@ -195,13 +196,23 @@ export function AppShell() {
{groups.map((g) => (
-

{g}

- s.group === g)} - activeSessionId={activeSessionId} - onOpenPanel={openPanel} - menuFor={menuFor} - /> + + {!collapsedGroups[g] && ( + s.group === g)} + activeSessionId={activeSessionId} + onOpenPanel={openPanel} + menuFor={menuFor} + /> + )}
))}