返回 DeepSeek-Reasonix
crash-overlay-restart.test.ts
根目录 / desktop / frontend / src / __tests__ / crash-overlay-restart.test.ts
1 // Run: tsx src/__tests__/crash-overlay-restart.test.ts
2
3 import { JSDOM } from "jsdom";
4 import { buildCrashPayload, paintCrashOverlay } from "../lib/crash";
5 import { t } from "../lib/i18n";
6 import { installDesktopHostStub } from "./desktopHostStub";
7
8 let passed = 0;
9 let failed = 0;
10 function ok(value: boolean, label: string) {
11 if (value) {
12 process.stdout.write(` PASS ${label}\n`);
13 passed += 1;
14 } else {
15 process.stdout.write(` FAIL ${label}\n`);
16 failed += 1;
17 }
18 }
19
20 const dom = new JSDOM("<!doctype html><html><body></body></html>", { url: "http://localhost/" });
21 (globalThis as any).document = dom.window.document;
22 (globalThis as any).HTMLElement = dom.window.HTMLElement;
23 let reloads = 0;
24 // jsdom's Location.reload is unforgeable, so the overlay sees a plain window
25 // whose reload the test can count.
26 (globalThis as any).window = {
27 location: { reload: () => { reloads += 1; } },
28 setTimeout: (cb: () => void, ms: number) => setTimeout(cb, ms),
29 };
30
31 const flush = () => new Promise((resolve) => setTimeout(resolve, 0));
32
33 function restartButton(): HTMLButtonElement | undefined {
34 const overlay = document.getElementById("crash-overlay");
35 return Array.from(overlay?.querySelectorAll("button") ?? []).find(
36 (button) => button.textContent === t("crash.restart"),
37 ) as HTMLButtonElement | undefined;
38 }
39
40 async function main() {
41 console.log("\nCrash overlay restart");
42
43 let restarts = 0;
44 const stub = installDesktopHostStub({
45 ReportCrash: async () => {},
46 RestartApplication: async () => { restarts += 1; },
47 });
48 paintCrashOverlay(buildCrashPayload("react", new Error("render exploded")));
49 const button = restartButton();
50 ok(button !== undefined, "the crash overlay offers a restart action");
51 button?.click();
52 await flush();
53 ok(restarts === 1, "restart asks the desktop host to relaunch the application");
54 ok(reloads === 0, "a host relaunch that succeeds does not also reload the renderer");
55 stub.uninstall();
56
57 reloads = 0;
58 const rejecting = installDesktopHostStub({
59 ReportCrash: async () => {},
60 RestartApplication: async () => { throw new Error("service gone"); },
61 });
62 paintCrashOverlay(buildCrashPayload("react", new Error("render exploded")));
63 restartButton()?.click();
64 await flush();
65 ok(reloads === 1, "a relaunch the host refuses falls back to reloading the renderer");
66 rejecting.uninstall();
67
68 reloads = 0;
69 delete (globalThis as any).window.reasonixDesktop;
70 paintCrashOverlay(buildCrashPayload("react", new Error("render exploded")));
71 restartButton()?.click();
72 await flush();
73 ok(reloads === 1, "without a desktop host the restart action reloads the renderer");
74
75 console.log(`\n${passed} passed, ${failed} failed, ${passed + failed} total`);
76 if (failed > 0) process.exit(1);
77 }
78
79 void main();
80
80 lines TYPESCRIPT