From 80e2375e9325650c7f571aab174fc55e896497ab Mon Sep 17 00:00:00 2001 From: alejandrobailo Date: Mon, 29 Jun 2026 12:30:14 +0200 Subject: [PATCH] fix(ui): persist Lighthouse chat URL before notifications --- .../chat/lighthouse-v2-chat-page.test.tsx | 32 +++++++++++++++++++ .../chat/lighthouse-v2-chat-page.tsx | 20 +++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.test.tsx b/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.test.tsx index 333c4d668c..22186d87ef 100644 --- a/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.test.tsx +++ b/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.test.tsx @@ -3,6 +3,7 @@ import userEvent from "@testing-library/user-event"; import { type ReactNode } from "react"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { LIGHTHOUSE_V2_SESSIONS_CHANGED_EVENT } from "@/app/(prowler)/lighthouse/_lib/session-events"; import type { LighthouseV2Configuration, LighthouseV2Message, @@ -241,6 +242,37 @@ describe("LighthouseV2ChatPage", () => { replaceStateSpy.mockRestore(); }); + it("updates the URL before notifying session history listeners", async () => { + // Given + const user = userEvent.setup(); + const notifiedUrls: string[] = []; + const recordCurrentUrl = () => { + notifiedUrls.push(`${window.location.pathname}${window.location.search}`); + }; + window.addEventListener( + LIGHTHOUSE_V2_SESSIONS_CHANGED_EVENT, + recordCurrentUrl, + ); + renderPage(); + + try { + // When + await user.type( + screen.getByRole("textbox", { name: "Message" }), + ["Summarize findings", "{Enter}"].join(""), + ); + + // Then + await waitFor(() => expect(notifiedUrls.length).toBeGreaterThan(0)); + expect(notifiedUrls[0]).toBe("/lighthouse?session=session-1"); + } finally { + window.removeEventListener( + LIGHTHOUSE_V2_SESSIONS_CHANGED_EVENT, + recordCurrentUrl, + ); + } + }); + it("subscribes to the stream before sending the message (no replay buffer)", async () => { // Given const user = userEvent.setup(); diff --git a/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.tsx b/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.tsx index 7caf5ba727..4b31bb9760 100644 --- a/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.tsx +++ b/ui/app/(prowler)/lighthouse/_components/chat/lighthouse-v2-chat-page.tsx @@ -202,16 +202,12 @@ export function LighthouseV2ChatPage({ return null; } - setActiveSessionId(result.data.id); - notifyLighthouseV2SessionsChanged(); // Update the URL in place (not router.push) so the force-dynamic server // component is NOT re-run mid-submit. A re-run would change `key` in // page.tsx and remount this component, tearing down the open EventSource. - window.history.replaceState( - null, - "", - `/lighthouse?session=${encodeURIComponent(result.data.id)}`, - ); + replaceLighthouseV2SessionUrl(result.data.id); + setActiveSessionId(result.data.id); + notifyLighthouseV2SessionsChanged(); return result.data.id; }; @@ -321,7 +317,7 @@ export function LighthouseV2ChatPage({ setIsSubmitting(false); setLastSubmittedText(null); setStreamState(createInitialLighthouseV2StreamState()); - window.history.replaceState(null, "", "/lighthouse"); + replaceLighthouseV2SessionUrl(null); }; window.addEventListener(LIGHTHOUSE_V2_NEW_CHAT_EVENT, resetToNewChat); @@ -393,3 +389,11 @@ export function LighthouseV2ChatPage({ ); } + +function replaceLighthouseV2SessionUrl(sessionId: string | null) { + const url = sessionId + ? `/lighthouse?session=${encodeURIComponent(sessionId)}` + : "/lighthouse"; + + window.history.replaceState(window.history.state, "", url); +}