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)), ); });