| 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 |