1import { describe, expect, it } from "vite-plus/test";
2
3import { TERMINAL_WRITE_MAX_LENGTH } from "./terminalInput";
4import { createTerminalPasteSession } from "./terminalPaste";
5
6function deferred<T>() {
7 let resolve!: (value: T) => void;
8 const promise = new Promise<T>((resolvePromise) => {
9 resolve = resolvePromise;
10 });
11 return { promise, resolve };
12}
13
14describe("terminal paste session", () => {
15 it("drops a clipboard read when the pty restarts in place", async () => {
16 const session = createTerminalPasteSession();
17 session.reset(true);
18 const clipboardRead = deferred<string>();
19 const writes: string[] = [];
20
21 const paste = session.paste({
22 readText: () => clipboardRead.promise,
23 write: async (data) => {
24 writes.push(data);
25 return true;
26 },
27 onReadError: () => undefined,
28 });
29
30 session.reset(true);
31 clipboardRead.resolve("stale");
32 await paste;
33
34 expect(writes).toEqual([]);
35 });
36
37 it("never overlaps writes from rapid paste requests", async () => {
38 const session = createTerminalPasteSession();
39 session.reset(true);
40
41 const firstWrite = deferred<boolean>();
42 const firstWriteStarted = deferred<void>();
43 const writes: string[] = [];
44 let activeWrites = 0;
45 let maximumActiveWrites = 0;
46 const write = async (data: string) => {
47 writes.push(data);
48 activeWrites += 1;
49 maximumActiveWrites = Math.max(maximumActiveWrites, activeWrites);
50 if (writes.length === 1) {
51 firstWriteStarted.resolve();
52 await firstWrite.promise;
53 }
54 activeWrites -= 1;
55 return true;
56 };
57
58 const olderPaste = session.paste({
59 readText: async () => "a".repeat(TERMINAL_WRITE_MAX_LENGTH + 1),
60 write,
61 onReadError: () => undefined,
62 });
63 await firstWriteStarted.promise;
64
65 const newerPaste = session.paste({
66 readText: async () => "newer",
67 write,
68 onReadError: () => undefined,
69 });
70 await Promise.resolve();
71
72 expect(writes.map((chunk) => chunk.length)).toEqual([TERMINAL_WRITE_MAX_LENGTH]);
73 expect(maximumActiveWrites).toBe(1);
74
75 firstWrite.resolve(true);
76 await Promise.all([olderPaste, newerPaste]);
77
78 expect(writes.map((chunk) => chunk.length)).toEqual([TERMINAL_WRITE_MAX_LENGTH, 5]);
79 expect(writes[1]).toBe("newer");
80 expect(maximumActiveWrites).toBe(1);
81 });
82});