返回 DeepSeek-Reasonix
browser-first-open.test.tsx
根目录 / desktop / frontend / src / __tests__ / browser-first-open.test.tsx
1 import assert from "node:assert/strict";
2 import React, { act } from "react";
3 import { JSDOM } from "jsdom";
4 import type { BrowserTabView, DesktopBrowserHost } from "../lib/browserHost";
5 import type { ReasonixDesktopHost } from "../lib/desktopHost";
6
7 const dom = new JSDOM("<div id='root'></div>");
8 Object.assign(globalThis, { window: dom.window, document: dom.window.document, IS_REACT_ACT_ENVIRONMENT: true });
9 let receive: ((tabs: BrowserTabView[]) => void) | undefined;
10 const browser = { list: async () => [], onTabs: (callback: typeof receive) => { receive = callback; return () => { receive = undefined; }; } } as DesktopBrowserHost;
11 window.reasonixDesktop = { browser, invoke: async () => undefined, native: { window: {}, clipboard: {}, onServiceState: () => () => {} } } as unknown as ReasonixDesktopHost;
12 const [{ createRoot }, { useBrowserFirstOpen }] = await Promise.all([import("react-dom/client"), import("../app-runtime/useBrowserFirstOpen")]);
13 let reveals = 0;
14 function Fixture({ turn = "turn-1" }: { turn?: string }) { useBrowserFirstOpen("task", turn, () => reveals++, "session"); return null; }
15 const root = createRoot(document.getElementById("root")!);
16 const rows: BrowserTabView[] = [];
17 async function add(id: string, taskId = "task", sessionId = "session") { rows.push({ id, taskId, sessionId } as BrowserTabView); await act(async () => receive?.([...rows])); }
18 try {
19 await act(async () => root.render(<Fixture />));
20 await add("background", "other"); assert.equal(reveals, 0);
21 await add("stale", "task", "old-session"); assert.equal(reveals, 0);
22 await add("first"); assert.equal(reveals, 1);
23 await add("second"); assert.equal(reveals, 1, "closing the panel does not allow a second reveal in the same turn");
24 await act(async () => root.render(<Fixture turn="turn-2" />));
25 await add("next-turn"); assert.equal(reveals, 2);
26 console.log("browser first open: foreground session, one reveal per turn, and background isolation passed");
27 } finally { await act(async () => root.unmount()); dom.window.close(); }
28
28 lines Plain Text