1import { afterEach, describe, expect, it } from "vite-plus/test";
2
3import { getTerminalFocusOwner, isTerminalFocused } from "./terminalFocus";
4
5class MockHTMLElement {
6 isConnected = false;
7 className = "";
8 terminalOwner: string | null = null;
9 readonly dataset: { terminalOwner?: string } = {};
10
11 readonly classList = {
12 contains: (value: string) => this.className.split(/\s+/).includes(value),
13 };
14
15 closest(selector: string): MockHTMLElement | null {
16 if (!this.isConnected) {
17 return null;
18 }
19 if (selector === "[data-terminal-owner]" && this.terminalOwner !== null) {
20 return this;
21 }
22 return null;
23 }
24}
25
26const originalDocument = globalThis.document;
27const originalHTMLElement = globalThis.HTMLElement;
28
29afterEach(() => {
30 if (originalDocument === undefined) {
31 delete (globalThis as { document?: Document }).document;
32 } else {
33 globalThis.document = originalDocument;
34 }
35
36 if (originalHTMLElement === undefined) {
37 delete (globalThis as { HTMLElement?: typeof HTMLElement }).HTMLElement;
38 } else {
39 globalThis.HTMLElement = originalHTMLElement;
40 }
41});
42
43describe("isTerminalFocused", () => {
44 it("returns false for detached xterm helper textareas", () => {
45 const detached = new MockHTMLElement();
46 detached.className = "xterm-helper-textarea";
47
48 globalThis.HTMLElement = MockHTMLElement as unknown as typeof HTMLElement;
49 globalThis.document = { activeElement: detached } as unknown as Document;
50
51 expect(isTerminalFocused()).toBe(false);
52 });
53
54 it("returns the drawer owner for connected xterm helper textareas", () => {
55 const attached = new MockHTMLElement();
56 attached.className = "xterm-helper-textarea";
57 attached.isConnected = true;
58 attached.terminalOwner = "drawer";
59 attached.dataset.terminalOwner = "drawer";
60
61 globalThis.HTMLElement = MockHTMLElement as unknown as typeof HTMLElement;
62 globalThis.document = { activeElement: attached } as unknown as Document;
63
64 expect(getTerminalFocusOwner()).toBe("drawer");
65 expect(isTerminalFocused()).toBe(true);
66 });
67
68 it("returns the right panel owner for focus inside its terminal UI", () => {
69 const sidebarButton = new MockHTMLElement();
70 sidebarButton.className = "terminal-sidebar-button";
71 sidebarButton.isConnected = true;
72 sidebarButton.terminalOwner = "right-panel";
73 sidebarButton.dataset.terminalOwner = "right-panel";
74
75 globalThis.HTMLElement = MockHTMLElement as unknown as typeof HTMLElement;
76 globalThis.document = { activeElement: sidebarButton } as unknown as Document;
77
78 expect(getTerminalFocusOwner()).toBe("right-panel");
79 expect(isTerminalFocused()).toBe(true);
80 });
81});