1// @effect-diagnostics nodeBuiltinImport:off -- Exercise the bundled KWin script in an isolated JS context.
2import * as NodeFSP from "node:fs/promises";
3import * as NodeVM from "node:vm";
4import { expect, it } from "vite-plus/test";
5
6const source = await NodeFSP.readFile(new URL("./activate.js", import.meta.url), "utf8");
7function signal() {
8 const callbacks: Array<(...args: unknown[]) => void> = [];
9 return {
10 connect: (callback: (...args: unknown[]) => void) => callbacks.push(callback),
11 emit: (...args: unknown[]) => callbacks.forEach((callback) => callback(...args)),
12 };
13}
14function fixture() {
15 const windows: Array<{
16 pid: number;
17 caption: string;
18 minimized: boolean;
19 captionChanged: ReturnType<typeof signal>;
20 }> = [];
21 const replies: unknown[] = [];
22 const workspace = {
23 windowList: () => windows,
24 activeWindow: undefined as (typeof windows)[number] | undefined,
25 windowAdded: signal(),
26 windowActivated: signal(),
27 };
28 const timeout = signal();
29 let stopped = false;
30 class Timer {
31 timeout = timeout;
32 start() {}
33 stop() {
34 stopped = true;
35 }
36 }
37 return {
38 windows,
39 workspace,
40 replies,
41 timeout,
42 stopped: () => stopped,
43 run: () =>
44 NodeVM.runInNewContext(source, {
45 workspace,
46 QTimer: Timer,
47 targetPid: 123,
48 targetTitle: "Draft",
49 reply: (value: unknown) => replies.push(value),
50 }),
51 };
52}
53
54it("waits for a remapped T3 window and its title before activating", () => {
55 const f = fixture();
56 f.run();
57 const other = { pid: 999, caption: "Draft", minimized: false, captionChanged: signal() };
58 f.windows.push(other);
59 f.workspace.windowAdded.emit(other);
60 expect(f.replies).toEqual([]);
61 const target = { pid: 123, caption: "", minimized: true, captionChanged: signal() };
62 f.windows.push(target);
63 f.workspace.windowAdded.emit(target);
64 expect(f.replies).toEqual([]);
65 target.caption = "Draft";
66 target.captionChanged.emit();
67 expect(f.workspace.activeWindow).toBe(target);
68 expect(target.minimized).toBe(false);
69 expect(f.replies).toEqual([{ activated: true }]);
70 expect(f.stopped()).toBe(true);
71});
72
73it("rejects ambiguous destinations and ends a wait without activating a lookalike", () => {
74 const f = fixture();
75 f.windows.push(
76 ...[1, 2].map(() => ({
77 pid: 123,
78 caption: "Draft",
79 minimized: false,
80 captionChanged: signal(),
81 })),
82 );
83 f.run();
84 expect(f.replies).toEqual([{ activated: false }]);
85 expect(f.workspace.activeWindow).toBeUndefined();
86 const waiting = fixture();
87 waiting.run();
88 waiting.timeout.emit();
89 expect(waiting.replies).toEqual([{ activated: false }]);
90 expect(waiting.stopped()).toBe(true);
91});