1import { assert, describe, it } from "@effect/vitest";
2import * as HostProcess from "@t3tools/shared/HostProcess";
3import * as Cause from "effect/Cause";
4import * as Effect from "effect/Effect";
5import * as Fiber from "effect/Fiber";
6import * as Layer from "effect/Layer";
7import type * as Electron from "electron";
8import { beforeEach, vi } from "vite-plus/test";
9
10const {
11 activateWindowsForegroundMock,
12 appFocusMock,
13 browserWindowMock,
14 foregroundWindowMock,
15 getAllWindowsMock,
16 getFocusedWindowMock,
17 loadWindowsForegroundApiMock,
18 shellHostedForegroundMock,
19 startWindowsForegroundFocusThreadMock,
20 windowsForegroundFocusMock,
21 windowsForegroundPrepareMock,
22 windowsForegroundCloseMock,
23} = vi.hoisted(() => ({
24 activateWindowsForegroundMock: vi.fn(),
25 appFocusMock: vi.fn(),
26 browserWindowMock: vi.fn(function BrowserWindowMock() {}),
27 foregroundWindowMock: vi.fn<() => bigint>(),
28 getAllWindowsMock: vi.fn(),
29 getFocusedWindowMock: vi.fn(),
30 loadWindowsForegroundApiMock: vi.fn<() => Promise<{ getForegroundWindow: () => bigint }>>(),
31 shellHostedForegroundMock: vi.fn(),
32 startWindowsForegroundFocusThreadMock: vi.fn(),
33 windowsForegroundFocusMock: vi.fn(),
34 windowsForegroundPrepareMock: vi.fn(),
35 windowsForegroundCloseMock: vi.fn(),
36}));
37
38vi.mock("./WindowsForeground.ts", () => ({
39 activateWindowsForeground: activateWindowsForegroundMock,
40 isWindowsShellHostedForeground: shellHostedForegroundMock,
41 loadWindowsForegroundApi: loadWindowsForegroundApiMock,
42}));
43
44vi.mock("./WindowsForegroundFocusThread.ts", () => ({
45 startWindowsForegroundFocusThread: startWindowsForegroundFocusThreadMock,
46}));
47
48vi.mock("electron", () => ({
49 app: {
50 focus: appFocusMock,
51 },
52 BrowserWindow: Object.assign(browserWindowMock, {
53 getAllWindows: getAllWindowsMock,
54 getFocusedWindow: getFocusedWindowMock,
55 }),
56}));
57
58import * as ElectronWindow from "./ElectronWindow.ts";
59
60const layerTestFor = (platform: NodeJS.Platform) =>
61 ElectronWindow.layer.pipe(Layer.provide(Layer.succeed(HostProcess.Platform, platform)));
62
63const layerTest = layerTestFor("linux");
64
65function makeBrowserWindow(input: { readonly id: number; readonly destroyed: boolean }) {
66 return {
67 id: input.id,
68 isDestroyed: vi.fn(() => input.destroyed),
69 } as unknown as Electron.BrowserWindow;
70}
71
72function makeWindowsRevealWindow() {
73 return {
74 id: 41,
75 isDestroyed: vi.fn(() => false),
76 isFocused: vi.fn(() => false),
77 isMinimized: vi.fn(() => false),
78 isVisible: vi.fn(() => true),
79 show: vi.fn(),
80 moveTop: vi.fn(),
81 focus: vi.fn(),
82 getTitle: vi.fn(() => "T3 Code (Dev)"),
83 getBounds: vi.fn(() => ({ x: 100, y: 50, width: 1_200, height: 800 })),
84 getContentBounds: vi.fn(() => ({ x: 108, y: 50, width: 1_184, height: 792 })),
85 getNativeWindowHandle: vi.fn(() => Buffer.from([41, 0, 0, 0])),
86 restore: vi.fn(),
87 };
88}
89
90describe("ElectronWindow", () => {
91 beforeEach(() => {
92 activateWindowsForegroundMock.mockReset().mockResolvedValue(undefined);
93 appFocusMock.mockReset();
94 browserWindowMock.mockReset();
95 foregroundWindowMock.mockReset().mockReturnValue(0n);
96 getAllWindowsMock.mockReset();
97 getFocusedWindowMock.mockReset();
98 loadWindowsForegroundApiMock
99 .mockReset()
100 .mockImplementation(() => Promise.resolve({ getForegroundWindow: foregroundWindowMock }));
101 shellHostedForegroundMock.mockReset().mockResolvedValue(false);
102 startWindowsForegroundFocusThreadMock.mockReset().mockReturnValue({
103 prepare: windowsForegroundPrepareMock,
104 focus: windowsForegroundFocusMock,
105 close: windowsForegroundCloseMock,
106 });
107 windowsForegroundFocusMock.mockReset().mockResolvedValue(false);
108 windowsForegroundPrepareMock.mockReset().mockResolvedValue(false);
109 windowsForegroundCloseMock.mockReset();
110 });
111
112 it.effect("preserves schema-safe creation context and the Electron cause", () =>
113 Effect.gen(function* () {
114 const cause = new Error("native BrowserWindow construction failed");
115 browserWindowMock.mockImplementationOnce(function BrowserWindowFailure() {
116 throw cause;
117 });
118 const options = {
119 title: "T3 Code",
120 width: 1100,
121 height: 780,
122 minWidth: 840,
123 minHeight: 620,
124 show: false,
125 modal: false,
126 frame: true,
127 transparent: false,
128 backgroundColor: "#101010",
129 icon: {} as Electron.NativeImage,
130 webPreferences: {
131 preload: "/tmp/preload.js",
132 partition: "persist:t3code-preview-test",
133 sandbox: true,
134 contextIsolation: true,
135 nodeIntegration: false,
136 webviewTag: true,
137 spellcheck: true,
138 },
139 } satisfies Electron.BrowserWindowConstructorOptions;
140 const electronWindow = yield* ElectronWindow.ElectronWindow;
141
142 const error = yield* electronWindow.create(options).pipe(Effect.flip);
143
144 assert.instanceOf(error, ElectronWindow.ElectronWindowCreateError);
145 assert.deepEqual(error.options, {
146 title: "T3 Code",
147 width: 1100,
148 height: 780,
149 minWidth: 840,
150 minHeight: 620,
151 show: false,
152 modal: false,
153 frame: true,
154 transparent: false,
155 backgroundColor: "#101010",
156 webPreferences: {
157 preload: "/tmp/preload.js",
158 partition: "persist:t3code-preview-test",
159 backgroundThrottling: null,
160 sandbox: true,
161 contextIsolation: true,
162 nodeIntegration: false,
163 webviewTag: true,
164 },
165 });
166 assert.isFalse("icon" in error.options);
167 assert.isFalse("spellcheck" in error.options.webPreferences);
168 assert.strictEqual(error.cause, cause);
169 assert.equal(error.message, 'Failed to create Electron BrowserWindow "T3 Code" (1100x780).');
170 assert.notInclude(error.message, cause.message);
171 assert.deepEqual(browserWindowMock.mock.calls, [[options]]);
172 }).pipe(Effect.provide(layerTest)),
173 );
174
175 it.effect("skips windows destroyed before appearance sync runs", () =>
176 Effect.gen(function* () {
177 const liveWindow = makeBrowserWindow({ id: 1, destroyed: false });
178 const destroyedWindow = makeBrowserWindow({ id: 2, destroyed: true });
179 getAllWindowsMock.mockReturnValue([destroyedWindow, liveWindow]);
180
181 const syncedWindows: Electron.BrowserWindow[] = [];
182 const electronWindow = yield* ElectronWindow.ElectronWindow;
183 yield* electronWindow.syncAllAppearance((window) =>
184 Effect.sync(() => {
185 syncedWindows.push(window);
186 }),
187 );
188
189 assert.deepEqual(syncedWindows, [liveWindow]);
190 }).pipe(Effect.provide(layerTest)),
191 );
192
193 it.effect("preserves window enumeration failures as structured defects", () =>
194 Effect.gen(function* () {
195 const cause = new Error("window enumeration failed");
196 getAllWindowsMock.mockImplementationOnce(() => {
197 throw cause;
198 });
199
200 const electronWindow = yield* ElectronWindow.ElectronWindow;
201 const exit = yield* Effect.exit(electronWindow.currentMainOrFirst);
202
203 assert.equal(exit._tag, "Failure");
204 if (exit._tag === "Failure") {
205 const error = Cause.squash(exit.cause);
206 assert.instanceOf(error, ElectronWindow.ElectronWindowOperationError);
207 assert.equal(error.operation, "list-windows");
208 assert.equal(error.platform, "linux");
209 assert.isNull(error.windowId);
210 assert.isNull(error.channel);
211 assert.strictEqual(error.cause, cause);
212 assert.notInclude(error.message, cause.message);
213 }
214 }).pipe(Effect.provide(layerTest)),
215 );
216
217 it.effect("preserves reveal failures with the target window", () =>
218 Effect.gen(function* () {
219 const cause = new Error("window restore failed");
220 const window = {
221 id: 41,
222 isDestroyed: vi.fn(() => false),
223 isMinimized: vi.fn(() => true),
224 restore: vi.fn(() => {
225 throw cause;
226 }),
227 } as unknown as Electron.BrowserWindow;
228
229 const electronWindow = yield* ElectronWindow.ElectronWindow;
230 const exit = yield* Effect.exit(electronWindow.reveal(window));
231
232 assert.equal(exit._tag, "Failure");
233 if (exit._tag === "Failure") {
234 const error = Cause.squash(exit.cause);
235 assert.instanceOf(error, ElectronWindow.ElectronWindowOperationError);
236 assert.equal(error.operation, "reveal-window");
237 assert.equal(error.windowId, 41);
238 assert.isNull(error.channel);
239 assert.strictEqual(error.cause, cause);
240 }
241 }).pipe(Effect.provide(layerTest)),
242 );
243
244 it.effect("uses native Windows activation without querying the foreground window", () =>
245 Effect.gen(function* () {
246 const operations: Array<string> = [];
247 appFocusMock.mockImplementation(() => operations.push("app-focus"));
248 activateWindowsForegroundMock.mockImplementation(async () => {
249 operations.push("native-activation");
250 });
251 const window = {
252 ...makeWindowsRevealWindow(),
253 show: vi.fn(() => operations.push("show")),
254 moveTop: vi.fn(() => operations.push("move-top")),
255 focus: vi.fn(() => operations.push("focus")),
256 } as unknown as Electron.BrowserWindow;
257 const electronWindow = yield* ElectronWindow.ElectronWindow;
258 yield* electronWindow.prepareReveal(window);
259
260 yield* electronWindow.reveal(window);
261
262 assert.deepEqual(operations, ["app-focus", "show", "move-top", "focus", "native-activation"]);
263 assert.lengthOf(loadWindowsForegroundApiMock.mock.calls, 0);
264 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 0);
265 }).pipe(Effect.provide(layerTestFor("win32"))),
266 );
267
268 it.effect("focuses the exact T3 window before activating from a shell-hosted app", () =>
269 Effect.gen(function* () {
270 const operations: Array<string> = [];
271 shellHostedForegroundMock.mockResolvedValue(true);
272 windowsForegroundFocusMock.mockImplementation(async () => {
273 operations.push("native-focus");
274 return true;
275 });
276 activateWindowsForegroundMock.mockImplementation(async () => {
277 operations.push("native-activation");
278 });
279 const window = {
280 ...makeWindowsRevealWindow(),
281 show: vi.fn(() => operations.push("show")),
282 moveTop: vi.fn(() => operations.push("move-top")),
283 focus: vi.fn(() => operations.push("focus")),
284 } as unknown as Electron.BrowserWindow;
285 appFocusMock.mockImplementation(() => operations.push("app-focus"));
286 const electronWindow = yield* ElectronWindow.ElectronWindow;
287 yield* electronWindow.prepareReveal(window);
288
289 yield* electronWindow.reveal(window);
290
291 assert.deepEqual(operations, [
292 "app-focus",
293 "show",
294 "move-top",
295 "focus",
296 "native-focus",
297 "native-activation",
298 ]);
299 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 1);
300 assert.deepEqual(windowsForegroundFocusMock.mock.calls, [
301 [
302 {
303 windowId: 41,
304 processId: process.pid,
305 title: "T3 Code (Dev)",
306 bounds: { x: 100, y: 50, width: 1_200, height: 800 },
307 contentBounds: { x: 108, y: 50, width: 1_184, height: 792 },
308 },
309 ],
310 ]);
311 }).pipe(Effect.provide(layerTestFor("win32"))),
312 );
313
314 it.effect("prepares the exact T3 window before a capture overlay", () =>
315 Effect.gen(function* () {
316 windowsForegroundPrepareMock.mockResolvedValue(true);
317 const window = makeWindowsRevealWindow();
318 const electronWindow = yield* ElectronWindow.ElectronWindow;
319
320 const prepared = yield* electronWindow.prepareReveal(
321 window as unknown as Electron.BrowserWindow,
322 );
323
324 assert.isTrue(prepared);
325 assert.deepEqual(windowsForegroundPrepareMock.mock.calls, [
326 [
327 {
328 windowId: 41,
329 processId: process.pid,
330 title: "T3 Code (Dev)",
331 bounds: { x: 100, y: 50, width: 1_200, height: 800 },
332 contentBounds: { x: 108, y: 50, width: 1_184, height: 792 },
333 },
334 ],
335 ]);
336 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 0);
337 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 0);
338 }).pipe(Effect.provide(layerTestFor("win32"))),
339 );
340
341 it.effect.each([4, 8])(
342 "skips the focus worker only when the foreground matches the %i-byte HWND",
343 (handleBytes) =>
344 Effect.gen(function* () {
345 const window = makeWindowsRevealWindow();
346 activateWindowsForegroundMock.mockRejectedValueOnce(
347 new Error("Windows initially refused foreground activation"),
348 );
349 const hwnd = handleBytes === 4 ? 0xf123_4567n : 0x1_f123_4567n;
350 const handle = Buffer.alloc(handleBytes);
351 if (handleBytes === 4) handle.writeUInt32LE(Number(hwnd));
352 else handle.writeBigUInt64LE(hwnd);
353 window.getNativeWindowHandle.mockReturnValue(handle);
354 foregroundWindowMock.mockReturnValue(hwnd);
355 const electronWindow = yield* ElectronWindow.ElectronWindow;
356 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
357 window.getTitle.mockClear();
358
359 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
360
361 assert.lengthOf(foregroundWindowMock.mock.calls, 1);
362 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 0);
363 assert.lengthOf(window.getTitle.mock.calls, 0);
364 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 2);
365 }).pipe(Effect.provide(layerTestFor("win32"))),
366 );
367
368 it.effect.each([42n, 0n])(
369 "focuses through the worker when the foreground HWND is %s instead of the target",
370 (foreground) =>
371 Effect.gen(function* () {
372 const window = makeWindowsRevealWindow();
373 activateWindowsForegroundMock.mockRejectedValueOnce(
374 new Error("Windows initially refused foreground activation"),
375 );
376 foregroundWindowMock.mockReturnValue(foreground);
377 const electronWindow = yield* ElectronWindow.ElectronWindow;
378 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
379
380 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
381
382 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 1);
383 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 2);
384 }).pipe(Effect.provide(layerTestFor("win32"))),
385 );
386
387 it.effect("continues native focus when the foreground query fails", () =>
388 Effect.gen(function* () {
389 const window = makeWindowsRevealWindow();
390 activateWindowsForegroundMock.mockRejectedValueOnce(
391 new Error("Windows initially refused foreground activation"),
392 );
393 loadWindowsForegroundApiMock.mockRejectedValue(new Error("Foreground query unavailable"));
394 const electronWindow = yield* ElectronWindow.ElectronWindow;
395 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
396
397 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
398
399 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 1);
400 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 2);
401 }).pipe(Effect.provide(layerTestFor("win32"))),
402 );
403
404 it.effect("does not fail reveal when native focus rejects", () =>
405 Effect.gen(function* () {
406 const window = makeWindowsRevealWindow();
407 activateWindowsForegroundMock.mockRejectedValueOnce(
408 new Error("Windows initially refused foreground activation"),
409 );
410 windowsForegroundFocusMock.mockRejectedValue(new Error("Focus rejected"));
411 const electronWindow = yield* ElectronWindow.ElectronWindow;
412 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
413
414 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
415
416 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 1);
417 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 2);
418 }).pipe(Effect.provide(layerTestFor("win32"))),
419 );
420
421 it.effect("fails reveal when Windows refuses foreground activation", () =>
422 Effect.gen(function* () {
423 const cause = new Error("Windows refused foreground activation");
424 const window = makeWindowsRevealWindow();
425 activateWindowsForegroundMock.mockRejectedValue(cause);
426 const electronWindow = yield* ElectronWindow.ElectronWindow;
427 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
428
429 const exit = yield* Effect.exit(
430 electronWindow.reveal(window as unknown as Electron.BrowserWindow),
431 );
432
433 assert.equal(exit._tag, "Failure");
434 if (exit._tag === "Failure") {
435 const error = Cause.squash(exit.cause);
436 assert.instanceOf(error, ElectronWindow.ElectronWindowOperationError);
437 assert.equal(error.operation, "reveal-window");
438 assert.strictEqual(error.cause, cause);
439 }
440 assert.deepEqual(activateWindowsForegroundMock.mock.calls, [
441 [window.getNativeWindowHandle.mock.results[0]?.value],
442 [window.getNativeWindowHandle.mock.results[1]?.value],
443 ]);
444 }).pipe(Effect.provide(layerTestFor("win32"))),
445 );
446
447 it.effect("cancels native focus when destroyed during the foreground query", () =>
448 Effect.gen(function* () {
449 const window = makeWindowsRevealWindow();
450 activateWindowsForegroundMock.mockRejectedValueOnce(
451 new Error("Windows initially refused foreground activation"),
452 );
453 const queryStarted = Promise.withResolvers<void>();
454 const foreground = Promise.withResolvers<{ getForegroundWindow: () => bigint }>();
455 loadWindowsForegroundApiMock.mockImplementation(() => {
456 queryStarted.resolve();
457 return foreground.promise;
458 });
459 const electronWindow = yield* ElectronWindow.ElectronWindow;
460 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
461 window.getTitle.mockClear();
462
463 const revealFiber = yield* electronWindow
464 .reveal(window as unknown as Electron.BrowserWindow)
465 .pipe(Effect.forkChild({ startImmediately: true }));
466 yield* Effect.promise(() => queryStarted.promise);
467 window.isDestroyed.mockReturnValue(true);
468 foreground.resolve({ getForegroundWindow: foregroundWindowMock });
469 yield* Fiber.join(revealFiber);
470
471 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 0);
472 assert.lengthOf(window.getNativeWindowHandle.mock.calls, 1);
473 assert.lengthOf(window.getTitle.mock.calls, 0);
474 }).pipe(Effect.provide(layerTestFor("win32"))),
475 );
476
477 it.effect("preserves message delivery failures with window and channel context", () =>
478 Effect.gen(function* () {
479 const cause = new Error("renderer send failed");
480 const window = {
481 id: 42,
482 isDestroyed: vi.fn(() => false),
483 webContents: {
484 send: vi.fn(() => {
485 throw cause;
486 }),
487 },
488 } as unknown as Electron.BrowserWindow;
489 getAllWindowsMock.mockReturnValueOnce([window]);
490
491 const electronWindow = yield* ElectronWindow.ElectronWindow;
492 const exit = yield* Effect.exit(electronWindow.sendAll("desktop:update", { ready: true }));
493
494 assert.equal(exit._tag, "Failure");
495 if (exit._tag === "Failure") {
496 const error = Cause.squash(exit.cause);
497 assert.instanceOf(error, ElectronWindow.ElectronWindowOperationError);
498 assert.equal(error.operation, "send-window-message");
499 assert.equal(error.windowId, 42);
500 assert.equal(error.channel, "desktop:update");
501 assert.strictEqual(error.cause, cause);
502 }
503 }).pipe(Effect.provide(layerTest)),
504 );
505
506 it.effect("preserves destroy failures and continues with later windows", () =>
507 Effect.gen(function* () {
508 const cause = new Error("window destroy failed");
509 const window = {
510 id: 43,
511 destroy: vi.fn(() => {
512 throw cause;
513 }),
514 } as unknown as Electron.BrowserWindow;
515 const laterWindow = {
516 id: 44,
517 destroy: vi.fn(),
518 } as unknown as Electron.BrowserWindow;
519 getAllWindowsMock.mockReturnValueOnce([window, laterWindow]);
520
521 const electronWindow = yield* ElectronWindow.ElectronWindow;
522 const exit = yield* Effect.exit(electronWindow.destroyAll);
523
524 assert.equal(exit._tag, "Failure");
525 if (exit._tag === "Failure") {
526 const error = Cause.squash(exit.cause);
527 assert.instanceOf(error, ElectronWindow.ElectronWindowOperationError);
528 assert.equal(error.operation, "destroy-window");
529 assert.equal(error.windowId, 43);
530 assert.isNull(error.channel);
531 assert.strictEqual(error.cause, cause);
532 }
533 assert.equal(vi.mocked(laterWindow.destroy).mock.calls.length, 1);
534 }).pipe(Effect.provide(layerTest)),
535 );
536 it.effect("an ordinary reveal on Windows does not touch the Win32 foreground helpers", () =>
537 Effect.gen(function* () {
538 const window = makeWindowsRevealWindow();
539 const electronWindow = yield* ElectronWindow.ElectronWindow;
540
541 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
542
543 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 0);
544 assert.lengthOf(windowsForegroundFocusMock.mock.calls, 0);
545 assert.lengthOf(shellHostedForegroundMock.mock.calls, 0);
546 assert.lengthOf(startWindowsForegroundFocusThreadMock.mock.calls, 0);
547 assert.lengthOf(window.focus.mock.calls, 1);
548 }).pipe(Effect.provide(layerTestFor("win32"))),
549 );
550
551 it.effect("a capture reveal on Windows uses the Win32 path only once", () =>
552 Effect.gen(function* () {
553 const window = makeWindowsRevealWindow();
554 const electronWindow = yield* ElectronWindow.ElectronWindow;
555
556 yield* electronWindow.prepareReveal(window as unknown as Electron.BrowserWindow);
557 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
558 yield* electronWindow.reveal(window as unknown as Electron.BrowserWindow);
559
560 assert.lengthOf(activateWindowsForegroundMock.mock.calls, 1);
561 assert.lengthOf(window.focus.mock.calls, 2);
562 }).pipe(Effect.provide(layerTestFor("win32"))),
563 );
564
565 it.effect("starts the Windows focus worker lazily and closes it with the layer", () =>
566 Effect.gen(function* () {
567 yield* ElectronWindow.ElectronWindow.pipe(Effect.provide(layerTestFor("win32")));
568 assert.lengthOf(startWindowsForegroundFocusThreadMock.mock.calls, 0);
569 assert.lengthOf(windowsForegroundCloseMock.mock.calls, 0);
570
571 yield* Effect.gen(function* () {
572 const electronWindow = yield* ElectronWindow.ElectronWindow;
573 const window = makeWindowsRevealWindow() as unknown as Electron.BrowserWindow;
574 yield* electronWindow.prepareReveal(window);
575 yield* electronWindow.prepareReveal(window);
576 assert.lengthOf(startWindowsForegroundFocusThreadMock.mock.calls, 1);
577 assert.lengthOf(windowsForegroundCloseMock.mock.calls, 0);
578 }).pipe(Effect.provide(layerTestFor("win32")));
579 assert.lengthOf(windowsForegroundCloseMock.mock.calls, 1);
580 }),
581 );
582});