返回 DeepSeek-Reasonix
anchored-popover-lifecycle.mjs
根目录 / desktop / frontend / bench / anchored-popover-lifecycle.mjs
1 #!/usr/bin/env node
2
3 import assert from "node:assert/strict";
4 import { copyFile, mkdtemp, rm } from "node:fs/promises";
5 import { createRequire } from "node:module";
6 import { tmpdir } from "node:os";
7 import path from "node:path";
8 import { fileURLToPath } from "node:url";
9 import { createServer } from "vite";
10
11 const frontendDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
12 process.env.PLAYWRIGHT_BROWSERS_PATH = !process.env.PLAYWRIGHT_BROWSERS_PATH || process.env.PLAYWRIGHT_BROWSERS_PATH === ".pw-browsers"
13 ? path.join(frontendDir, ".pw-browsers")
14 : process.env.PLAYWRIGHT_BROWSERS_PATH;
15 const { chromium, _electron } = await import("playwright");
16 const electronEngine = process.argv.includes("--electron");
17 const electronHome = electronEngine ? await mkdtemp(path.join(tmpdir(), "reasonix-popover-electron-")) : "";
18 const server = await createServer({
19 root: frontendDir,
20 server: { host: "127.0.0.1", port: 0, hmr: false },
21 logLevel: "error",
22 plugins: [{
23 name: "popover-test-favicon",
24 configureServer(vite) {
25 vite.middlewares.use((req, res, next) => {
26 if (req.url !== "/favicon.ico") return next();
27 res.statusCode = 204;
28 res.end();
29 });
30 },
31 }],
32 });
33 await server.listen();
34
35 let browser;
36 let electronApp;
37 try {
38 const address = server.httpServer.address();
39 if (!address || typeof address === "string") throw new Error("popover test server did not expose a port");
40 const url = `http://127.0.0.1:${address.port}/?mock=demo&bench=1`;
41 let page;
42 if (electronEngine) {
43 const main = path.join(electronHome, "main.cjs");
44 await copyFile(path.join(frontendDir, "bench/transcript-layout-electron.cjs"), main);
45 const electronRequire = createRequire(path.join(frontendDir, "../electron/package.json"));
46 electronApp = await _electron.launch({
47 executablePath: electronRequire("electron"), args: [main],
48 env: { ...process.env, REASONIX_LAYOUT_URL: url },
49 });
50 page = await electronApp.firstWindow();
51 } else {
52 browser = await chromium.launch({ headless: true, executablePath: process.env.CHROME_EXECUTABLE });
53 page = await browser.newPage({ viewport: { width: 1600, height: 1000 } });
54 }
55 const errors = [];
56 page.on("pageerror", error => errors.push(error.message));
57 page.on("console", message => { if (message.type() === "error") errors.push(message.text()); });
58 await page.addInitScript(() => localStorage.setItem("reasonix-lang", "en"));
59 await page.goto(url);
60 await page.locator("#composer-input").waitFor({ state: "visible" });
61 await page.evaluate(() => {
62 window.__reasonixPopoverCornerSamples = [];
63 const sample = () => {
64 const menu = document.querySelector(".modelsw__menu");
65 if (menu instanceof HTMLElement && getComputedStyle(menu).visibility === "visible") {
66 const rect = menu.getBoundingClientRect();
67 if (rect.left <= 8.5 && rect.top <= 8.5) window.__reasonixPopoverCornerSamples.push({ left: rect.left, top: rect.top });
68 }
69 window.__reasonixPopoverFrame = requestAnimationFrame(sample);
70 };
71 sample();
72 });
73
74 const input = page.locator("#composer-input");
75 await input.fill("/mock-ask");
76 await page.locator(".modelsw__trigger:visible").click();
77 await page.locator(".modelsw__menu").waitFor({ state: "visible" });
78 await input.press("Enter");
79 await page.locator(".prompt-shelf--ask").waitFor({ state: "visible" });
80 assert.equal(await page.locator(".modelsw__menu").count(), 0, "decision takeover removes the model menu");
81 assert.deepEqual(await page.evaluate(() => window.__reasonixPopoverCornerSamples), [], "model menu never flashes in the top-left corner");
82
83 await page.getByRole("button", { name: "Stop task" }).click();
84 await page.locator("#composer-input").waitFor({ state: "visible" });
85 assert.equal(await page.locator(".modelsw__menu").count(), 0, "model menu stays closed after the composer returns");
86 assert.equal(await page.locator(".modelsw__trigger").getAttribute("aria-expanded"), "false");
87 await page.evaluate(() => cancelAnimationFrame(window.__reasonixPopoverFrame));
88 assert.deepEqual(errors, []);
89 console.log(`PASS ${electronEngine ? "Electron" : "Chromium"} decision takeover closes model popover without corner flash or reopen`);
90 } finally {
91 await browser?.close();
92 await electronApp?.close();
93 await server.close();
94 if (electronHome) await rm(electronHome, { recursive: true, force: true });
95 }
96
96 lines Plain Text