返回 DeepSeek-Reasonix
windows-maximised-sync.test.tsx
根目录 / desktop / frontend / src / __tests__ / windows-maximised-sync.test.tsx
1 import assert from "node:assert/strict";
2 import React, { act } from "react";
3 import { createRoot } from "react-dom/client";
4 import { JSDOM } from "jsdom";
5 import { syncMainWindowMaximised, useWindowsMaximisedSync } from "../app-runtime/useNativeWindowController";
6 import { useWindowChromeStore } from "../store/windowChrome";
7 import { installDesktopHostStub } from "./desktopHostStub";
8
9 const dom = new JSDOM("<div id='root'></div>", { pretendToBeVisual: true });
10 Object.assign(globalThis, { window: dom.window, document: dom.window.document, IS_REACT_ACT_ENVIRONMENT: true });
11 globalThis.Event = dom.window.Event;
12 const root = createRoot(document.getElementById("root")!);
13
14 function deferred<T>() {
15 let resolve!: (value: T) => void;
16 const promise = new Promise<T>((yes) => { resolve = yes; });
17 return { promise, resolve };
18 }
19
20 const bridgeCalls: string[] = [];
21 let maximisedValue = false;
22 let maximisedGate: ReturnType<typeof deferred<boolean>> | null = null;
23 installDesktopHostStub({}, {
24 window: {
25 isMaximised: async () => {
26 bridgeCalls.push("query");
27 if (maximisedGate) return maximisedGate.promise;
28 return maximisedValue;
29 },
30 },
31 });
32
33 function Probe({ enabled }: { enabled: boolean }) {
34 useWindowsMaximisedSync(enabled);
35 return null;
36 }
37
38 const maximised = () => useWindowChromeStore.getState().mainWindowMaximised;
39
40 try {
41 syncMainWindowMaximised();
42 assert.equal(bridgeCalls.length, 0, "sync before any lifecycle is a no-op");
43
44 maximisedValue = true;
45 await act(async () => root.render(<Probe enabled={true} />));
46 assert.equal(maximised(), true, "the enabling lifecycle syncs the native flag into the store");
47 assert.deepEqual(bridgeCalls, ["query"], "the initial sync queries the native host once");
48
49 maximisedValue = false;
50 await act(async () => { window.dispatchEvent(new window.Event("resize")); });
51 assert.equal(maximised(), false, "a resize event re-syncs the flag");
52 assert.equal(bridgeCalls.length, 2, "listener sync queries the bridge again");
53
54 maximisedValue = true;
55 await act(async () => { window.dispatchEvent(new window.Event("focus")); });
56 assert.equal(maximised(), true, "a focus event re-syncs the flag");
57
58 const supersededGate = deferred<boolean>();
59 maximisedGate = supersededGate;
60 await act(async () => { syncMainWindowMaximised(); });
61 maximisedGate = null;
62 maximisedValue = false;
63 await act(async () => { syncMainWindowMaximised(); });
64 assert.equal(maximised(), false, "the newer sync lands first");
65 await act(async () => { supersededGate.resolve(true); await supersededGate.promise; });
66 assert.equal(maximised(), false, "an out-of-order resolution from a superseded sync is discarded");
67
68 await act(async () => root.render(<Probe enabled={false} />));
69 assert.equal(maximised(), false, "disabling the lifecycle resets the flag");
70 bridgeCalls.length = 0;
71 syncMainWindowMaximised();
72 assert.equal(bridgeCalls.length, 0, "event-handler sync stays gated while disabled");
73
74 await act(async () => root.unmount());
75 bridgeCalls.length = 0;
76 syncMainWindowMaximised();
77 assert.equal(bridgeCalls.length, 0, "unmounting the host disables the sync gate");
78
79 console.log("windows maximised sync: lifecycle gating, listener sync, generation fence and store ownership passed");
80 } finally { dom.window.close(); }
81
81 lines Plain Text