diff --git a/frontend/src/shell/AppShell.session-mgmt.test.tsx b/frontend/src/shell/AppShell.session-mgmt.test.tsx index 77e20f88..a12b58e9 100644 --- a/frontend/src/shell/AppShell.session-mgmt.test.tsx +++ b/frontend/src/shell/AppShell.session-mgmt.test.tsx @@ -590,6 +590,54 @@ test("deleting another session does not invalidate a pending Resume", async () = expect(screen.getByTestId("session-item-s1")).toHaveAttribute("data-active", "true"); }); +test("deleting active A preserves a pending Resume for different session B", async () => { + const other = { + ...LIST[0], id: "s3", question: "Attiva tre", group: null, + created_at: "2026-01-03T00:00:00Z", + }; + const s3ResumeGate = deferred(); + const s3ResumeStarted = deferred(); + server.use( + http.get("http://localhost:8787/sessions", () => HttpResponse.json([LIST[0], other])), + http.post("http://localhost:8787/sessions/:id/resume", async ({ params }) => { + const id = params.id as string; + if (id === "s3") { + s3ResumeStarted.resolve(); + await s3ResumeGate.promise; + } + return resumeResult(id); + }), + http.get("http://localhost:8787/sessions/:id", ({ params }) => + HttpResponse.json({ id: params.id, status: "open", phase: params.id === "s3" ? 3 : 1 })), + http.delete("http://localhost:8787/sessions/:id", ({ params }) => { + expect(params.id).toBe("s1"); + return new HttpResponse(null, { status: 204 }); + }), + ); + wrap(); + + await userEvent.click(await screen.findByText("Attiva uno")); + await userEvent.click(await screen.findByRole("button", { name: /resume/i })); + await waitFor(() => expect(FakeEventSource.instances).toHaveLength(1)); + const sourceA = FakeEventSource.instances[0]; + expect(screen.getByTestId("session-item-s1")).toHaveAttribute("data-active", "true"); + + await userEvent.click(screen.getByText("Attiva tre")); + await userEvent.click(await screen.findByRole("button", { name: /resume/i })); + await s3ResumeStarted.promise; + screen.getByRole("checkbox", { name: "Select Attiva uno" }).focus(); + await userEvent.keyboard(" "); + await userEvent.click(await screen.findByRole("button", { name: "Delete 1 selected sessions" })); + await waitFor(() => expect(sourceA.closed).toBe(true)); + expect(screen.getByTestId("session-item-s1")).toHaveAttribute("data-active", "false"); + + s3ResumeGate.resolve(); + + await waitFor(() => expect(FakeEventSource.instances).toHaveLength(2)); + expect(FakeEventSource.instances[1].url).toContain("/sessions/s3/events"); + expect(screen.getByTestId("session-item-s3")).toHaveAttribute("data-active", "true"); +}); + test("a failed Delete does not invalidate a pending Resume for its target", async () => { const resumeGate = deferred(); const resumeStarted = deferred(); diff --git a/frontend/src/shell/AppShell.tsx b/frontend/src/shell/AppShell.tsx index 58036829..ea583353 100644 --- a/frontend/src/shell/AppShell.tsx +++ b/frontend/src/shell/AppShell.tsx @@ -247,7 +247,7 @@ export function AppShell() { ); const deletedActiveSession = deletedIds.has(activeSessionIdRef.current ?? ""); const deletedResumeTarget = deletedIds.has(latestResumeIntentRef.current?.id ?? ""); - if (deletedActiveSession || deletedResumeTarget) invalidateResumeIntent(); + if (deletedResumeTarget) invalidateResumeIntent(); if (deletedIds.has(panelSession?.id ?? "")) setPanelSession(null); if (deletedActiveSession) { resetSession(); selectActiveSession(null); } setSelectedSessionIds((current) => new Set([...current].filter((id) => !deletedIds.has(id))));