178 lines · 6.1 KB · TypeScript
RawDownload
import { assert, describe, it } from "@effect/vitest";import * as Effect from "effect/Effect";import { beforeEach, vi } from "vite-plus/test"; const { openExternalMock, writeTextMock } = vi.hoisted(() => ({  openExternalMock: vi.fn(),  writeTextMock: vi.fn(),})); vi.mock("electron", () => ({  shell: {    openExternal: openExternalMock,  },  clipboard: {    writeText: writeTextMock,  },})); import * as ElectronShell from "./ElectronShell.ts"; describe("ElectronShell", () => {  beforeEach(() => {    openExternalMock.mockReset();    writeTextMock.mockReset();  });   it.effect("opens safe external URLs", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const result = yield* electronShell.openExternal("https://example.com/path");       assert.equal(result, true);      assert.deepEqual(openExternalMock.mock.calls, [["https://example.com/path"]]);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("copies text to the system clipboard", () =>    Effect.gen(function* () {      writeTextMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      yield* electronShell.copyText("https://example.com/path");       assert.deepEqual(writeTextMock.mock.calls, [["https://example.com/path"]]);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("does not fail when the clipboard write rejects", () =>    Effect.gen(function* () {      writeTextMock.mockRejectedValue(new Error("write failed"));       const electronShell = yield* ElectronShell.ElectronShell;      yield* electronShell.copyText("https://example.com/path");       assert.deepEqual(writeTextMock.mock.calls, [["https://example.com/path"]]);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("opens the Full Disk Access settings anchor", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const result = yield* electronShell.openSystemSettings("full-disk-access");       assert.equal(result, true);      assert.deepEqual(openExternalMock.mock.calls, [        ["x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?Privacy_AllFiles"],      ]);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("opens remote SSH editor URLs", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const result = yield* electronShell.openExternal(        "vscode://vscode-remote/ssh-remote+example.com/home/user/project",      );       assert.equal(result, true);      assert.deepEqual(openExternalMock.mock.calls, [        ["vscode://vscode-remote/ssh-remote+example.com/home/user/project"],      ]);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("opens Zed's ssh deep link", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const results = yield* Effect.all([        electronShell.openExternal("zed://ssh/example.com/home/user/project"),        electronShell.openExternal("zed://ssh/example.com/"),      ]);       assert.deepEqual(results, [true, true]);      assert.deepEqual(openExternalMock.mock.calls, [        ["zed://ssh/example.com/home/user/project"],        ["zed://ssh/example.com/"],      ]);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("does not open editor URLs that mix up link shapes", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const results = yield* Effect.all([        electronShell.openExternal("zed://extension/attacker"),        electronShell.openExternal("vscode://ssh/example.com/home/user/project"),      ]);       assert.deepEqual(results, [false, false]);      assert.equal(openExternalMock.mock.calls.length, 0);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("does not open remote editor URLs with userinfo", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const results = yield* Effect.all([        electronShell.openExternal(          "vscode://user@vscode-remote/ssh-remote+example.com/home/user/project",        ),        electronShell.openExternal(          "vscode://:secret@vscode-remote/ssh-remote+example.com/home/user/project",        ),        electronShell.openExternal("zed://ssh/user@example.com/home/user/project"),      ]);       assert.deepEqual(results, [false, false, false]);      assert.equal(openExternalMock.mock.calls.length, 0);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("does not open unsafe external URLs", () =>    Effect.gen(function* () {      const electronShell = yield* ElectronShell.ElectronShell;      const result = yield* electronShell.openExternal("file:///etc/passwd");       assert.equal(result, false);      assert.equal(openExternalMock.mock.calls.length, 0);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("does not open non-remote editor URLs", () =>    Effect.gen(function* () {      openExternalMock.mockResolvedValue(undefined);       const electronShell = yield* ElectronShell.ElectronShell;      const result = yield* electronShell.openExternal(        "vscode://ms-python.python/some-command?argument=attacker",      );       assert.equal(result, false);      assert.equal(openExternalMock.mock.calls.length, 0);    }).pipe(Effect.provide(ElectronShell.layer)),  );   it.effect("returns false when Electron rejects openExternal", () =>    Effect.gen(function* () {      openExternalMock.mockRejectedValue(new Error("open failed"));       const electronShell = yield* ElectronShell.ElectronShell;      const result = yield* electronShell.openExternal("https://example.com/path");       assert.equal(result, false);    }).pipe(Effect.provide(ElectronShell.layer)),  );});