返回 DeepSeek-Reasonix
automation-surface-layout.test.ts
根目录 / desktop / frontend / src / __tests__ / automation-surface-layout.test.ts
1 import assert from "node:assert/strict";
2 import { readFileSync } from "node:fs";
3 import { JSDOM } from "jsdom";
4
5 const read = (path: string) => readFileSync(new URL(path, import.meta.url), "utf8");
6 const app = read("../AppRuntime.tsx");
7 const isolation = read("../lib/useManagementWorkspace.ts");
8 const shell = read("../components/ManagementPageShell.tsx");
9 const css = read("../components/ManagementPageShell.css");
10 const heartbeat = read("../custom/features/heartbeat/HeartbeatPanel.tsx");
11 const warmth = read("../lib/useWarmTerminalPanel.ts");
12 const sessionComposition = read("../app-runtime/useAppSessionComposition.ts");
13 const chromeCommands = read("../app-runtime/useAppChromeCommands.ts");
14 const palette = read("../app-runtime/usePaletteCommands.tsx");
15
16 // The shared full-window shell replaces the old chat-pane projection. Background
17 // geometry and component identity survive while all workspace input is inert.
18 assert.match(sessionComposition, /useManagementWorkspace\(layoutRef, managementActive\)/);
19 assert.match(isolation, /workspace\.inert = true/);
20 assert.match(isolation, /workspace\.inert = false/);
21 assert.doesNotMatch(app, /mainView === "automation"/);
22 // Actual focus and hit-testing of background controls are covered by
23 // bench/dock-view-state.mjs; the ancestor owns isolation regardless of JSX position.
24 assert.match(css, /\.management-screen \{[^}]*position: fixed;[^}]*inset: 0;/);
25 assert.match(shell, /hidden=\{!active\} inert=\{!active\}/);
26 assert.match(palette, /if \(managementActive\) ports\.returnToWorkspace\(\)/);
27 assert.match(heartbeat, /<ManagementPageShell active=\{active\}/);
28 assert.match(css, /management-titlebar-height: 48px/);
29 assert.match(app, /useWarmTerminalPanel\(shell.terminalPanelOpen, shell.terminalResizing, !shell.managementActive\)/);
30 assert.match(warmth, /if \(open\) setMounted\(true\)/);
31 assert.match(warmth, /if \(!open \|\| !visible\) \{\s*setFitEnabled\(false\)/s);
32
33 // Exercise the selector actually used by App against the header actually emitted
34 // by the shared shell. A class rename must not silently break native double-click.
35 const selector = chromeCommands.match(/const onChromeSurface = target\?\.closest\("([^"]+)"\)/)![1];
36 const headerClass = shell.match(/<header className="([^"]+)"/)![1];
37 const dom = new JSDOM(`<section><header class="${headerClass}"></header><main><button>Back</button></main></section>`);
38 assert(dom.window.document.querySelector("header")!.closest(selector));
39 assert.equal(dom.window.document.querySelector("button")!.closest(selector), null);
40 assert.match(chromeCommands, /input\.platform === "darwin"/);
41 assert.match(chromeCommands, /input\.windowsFrameless \|\| input\.platform/);
42 assert.match(chromeCommands, /target\?\.closest\("button, input, textarea, select, a,/);
43 dom.window.close();
44 console.log("PASS shared management geometry, input isolation, terminal retention and native titlebar dispatch");
45
45 lines TYPESCRIPT