Skip to content
Source
Sign inSign up
Open History to see the last commit

SnapShotAccessibilityProcess.test.ts

86 lines2.5 KB

1import { assert, beforeEach, it } from "@effect/vitest";
2import * as NodeEvents from "node:events";
3import { vi } from "vite-plus/test";
4​
5const forkMock = vi.hoisted(() =>
6 vi.fn<
7 (
8 _path: string,
9 _args: ReadonlyArray<string>,
10 _options: { env?: NodeJS.ProcessEnv; execPath?: string },
11 ) => unknown
12 >(),
13);
14​
15vi.mock("node:child_process", () => ({ fork: forkMock }));
16​
17import {
18 makeSnapShotAccessibilityProcessPool,
19 startSnapShotAccessibilityProcess,
20} from "./SnapShotAccessibilityProcess.ts";
21​
22const makeWorker = () =>
23 Object.assign(new NodeEvents.EventEmitter(), {
24 kill: vi.fn(() => true),
25 send: vi.fn(),
26 });
27let worker = makeWorker();
28const request = {
29 active: {
30 title: "Zoom Meeting",
31 bounds: { x: 10, y: 20, width: 800, height: 600 },
32 owner: { processId: 42 },
33 },
34 platform: "darwin" as const,
35 sourceTitle: "Zoom Meeting",
36 imageSize: { width: 1_600, height: 1_200 },
37};
38​
39beforeEach(() => {
40 worker = makeWorker();
41 forkMock.mockReset().mockReturnValue(worker);
42});
43​
44it("keeps T3 alive when Zoom crashes accessibility extraction", async () => {
45 const process = startSnapShotAccessibilityProcess("accessibility.cjs");
46 const read = process.read(request);
47 worker.emit("message", "ready");
48 worker.emit("message", "started");
49 await read.started;
50 worker.emit("exit", null, "SIGABRT");
51​
52 assert.isUndefined(await read.result);
53});
54​
55it("returns immediately when accessibility crashes before the screenshot is ready", async () => {
56 const process = startSnapShotAccessibilityProcess("accessibility.cjs");
57 worker.emit("exit", null, "SIGABRT");
58​
59 const read = process.read(request);
60 await read.started;
61 assert.isUndefined(await read.result);
62});
63​
64it("replaces a warm helper that exits before capture", async () => {
65 const exitedWorker = makeWorker();
66 const captureWorker = makeWorker();
67 const replacementWorker = makeWorker();
68 forkMock
69 .mockReset()
70 .mockReturnValueOnce(exitedWorker)
71 .mockReturnValueOnce(captureWorker)
72 .mockReturnValueOnce(replacementWorker);
73 const pool = makeSnapShotAccessibilityProcessPool("accessibility.cjs");
74​
75 pool.warm();
76 exitedWorker.emit("exit", 1);
77 const read = pool.read(request);
78 captureWorker.emit("message", "ready");
79 captureWorker.emit("message", "started");
80 captureWorker.emit("message", { type: "result", context: { accessibleText: "Recovered" } });
81​
82 assert.deepEqual(await read.result, { accessibleText: "Recovered" });
83 assert.lengthOf(forkMock.mock.calls, 3);
84 assert.deepEqual(captureWorker.send.mock.calls[0]?.[0], request);
85 pool.close();
86});