|
1 | 1 | import { beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 2 |
|
3 | 3 | const runCommandWithTimeoutMock = vi.hoisted(() => vi.fn()); |
| 4 | +const isWSL2SyncMock = vi.hoisted(() => vi.fn(() => false)); |
4 | 5 |
|
5 | 6 | vi.mock("../process/exec.js", () => ({ |
6 | 7 | runCommandWithTimeout: (...args: unknown[]) => runCommandWithTimeoutMock(...args), |
7 | 8 | })); |
8 | 9 |
|
| 10 | +vi.mock("./wsl.js", () => ({ |
| 11 | + isWSL2Sync: isWSL2SyncMock, |
| 12 | +})); |
| 13 | + |
9 | 14 | const { copyToClipboard } = await import("./clipboard.js"); |
10 | 15 |
|
11 | 16 | describe("copyToClipboard", () => { |
12 | 17 | beforeEach(() => { |
13 | 18 | runCommandWithTimeoutMock.mockReset(); |
| 19 | + isWSL2SyncMock.mockReturnValue(false); |
14 | 20 | }); |
15 | 21 |
|
16 | 22 | it("returns true on the first successful clipboard command", async () => { |
@@ -38,6 +44,41 @@ describe("copyToClipboard", () => { |
38 | 44 | ]); |
39 | 45 | }); |
40 | 46 |
|
| 47 | + it("uses a startup-free WSL2 shell bridge for clip.exe without putting the value in argv", async () => { |
| 48 | + isWSL2SyncMock.mockReturnValue(true); |
| 49 | + runCommandWithTimeoutMock.mockResolvedValueOnce({ code: 0, killed: false }); |
| 50 | + |
| 51 | + const tokenUrl = "http://127.0.0.1:18789/#token=secret-token"; |
| 52 | + await expect(copyToClipboard(tokenUrl)).resolves.toBe(true); |
| 53 | + |
| 54 | + expect(runCommandWithTimeoutMock).toHaveBeenCalledWith( |
| 55 | + ["/bin/sh", "-c", "exec /mnt/c/Windows/System32/clip.exe"], |
| 56 | + { |
| 57 | + timeoutMs: 3000, |
| 58 | + input: tokenUrl, |
| 59 | + }, |
| 60 | + ); |
| 61 | + const invokedArgv = runCommandWithTimeoutMock.mock.calls[0]?.[0] as string[]; |
| 62 | + expect(invokedArgv.join("\0")).not.toContain("secret-token"); |
| 63 | + expect(runCommandWithTimeoutMock).toHaveBeenCalledTimes(1); |
| 64 | + }); |
| 65 | + |
| 66 | + it("does not prepend the WSL2 bridge outside WSL2", async () => { |
| 67 | + runCommandWithTimeoutMock |
| 68 | + .mockRejectedValueOnce(new Error("missing pbcopy")) |
| 69 | + .mockResolvedValueOnce({ code: 0, killed: true }) |
| 70 | + .mockRejectedValueOnce(new Error("missing wl-copy")) |
| 71 | + .mockResolvedValueOnce({ code: 0, killed: false }); |
| 72 | + |
| 73 | + await expect(copyToClipboard("hello")).resolves.toBe(true); |
| 74 | + expect(runCommandWithTimeoutMock.mock.calls.map((call) => call[0])).toEqual([ |
| 75 | + ["pbcopy"], |
| 76 | + ["xclip", "-selection", "clipboard"], |
| 77 | + ["wl-copy"], |
| 78 | + ["clip.exe"], |
| 79 | + ]); |
| 80 | + }); |
| 81 | + |
41 | 82 | it("returns false when every clipboard backend fails or is killed", async () => { |
42 | 83 | runCommandWithTimeoutMock |
43 | 84 | .mockResolvedValueOnce({ code: 0, killed: true }) |
|
0 commit comments