// @effect-diagnostics nodeBuiltinImport:off - the Windows reveal smoke test drives a real PowerShell through Node process and filesystem APIs.import * as NodeChildProcess from "node:child_process";import * as NodeFS from "node:fs";import * as NodeOS from "node:os";import * as NodePath from "node:path";import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, it } from "@effect/vitest";import * as ConfigProvider from "effect/ConfigProvider";import * as Effect from "effect/Effect";import * as Fiber from "effect/Fiber";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Path from "effect/Path";import * as Sink from "effect/Sink";import * as Stream from "effect/Stream";import * as TestClock from "effect/testing/TestClock";import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; import { HostProcessPlatform } from "@t3tools/shared/hostProcess";import { SpawnExecutableResolution } from "@t3tools/shared/shell";import * as ExternalLauncher from "./externalLauncher.ts"; interface MockSpawnResult { readonly exitCode?: number; readonly stdout?: string; /** Never deliver an exit code, like a child wedged on a broken desktop session. */ readonly stall?: boolean;} function makeMockDetachedHandle(input: MockSpawnResult & { readonly onUnref?: () => void } = {}) { return ChildProcessSpawner.makeHandle({ pid: ChildProcessSpawner.ProcessId(1), exitCode: input.stall ? Effect.never : Effect.succeed(ChildProcessSpawner.ExitCode(input.exitCode ?? 0)), isRunning: Effect.succeed(true), kill: () => Effect.void, unref: Effect.sync(() => { input.onUnref?.(); return Effect.void; }), stdin: Sink.drain, stdout: input.stdout === undefined ? Stream.empty : Stream.make(new TextEncoder().encode(input.stdout)), stderr: Stream.empty, all: Stream.empty, getInputFd: () => Sink.drain, getOutputFd: () => Stream.empty, });} const testLayer = (input: { readonly platform: NodeJS.Platform; readonly env?: Record<string, string>; readonly resolveExecutable?: (command: string) => string | undefined; readonly onSpawn?: (command: ChildProcess.StandardCommand) => void; readonly onUnref?: () => void; readonly spawnResult?: (command: ChildProcess.StandardCommand) => MockSpawnResult | undefined;}) => { const spawnerLayer = Layer.succeed( ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make((command) => Effect.sync(() => { assert.equal(ChildProcess.isStandardCommand(command), true); if (!ChildProcess.isStandardCommand(command)) { throw new Error("Expected a standard command"); } input.onSpawn?.(command); return makeMockDetachedHandle({ ...(input.onUnref === undefined ? {} : { onUnref: input.onUnref }), ...input.spawnResult?.(command), }); }), ), ); return Layer.mergeAll( ExternalLauncher.layer.pipe(Layer.provide(Layer.merge(NodeServices.layer, spawnerLayer))), Layer.succeed(HostProcessPlatform, input.platform), Layer.succeed( SpawnExecutableResolution, (command) => input.resolveExecutable?.(command) ?? command, ), ConfigProvider.layer(ConfigProvider.fromEnv({ env: input.env ?? {} })), );}; it.effect("launches the default browser through the platform command", () => { let spawned: ChildProcess.StandardCommand | undefined; let didUnref = false; return Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchBrowser("https://example.com/some path"); assert.ok(spawned); assert.equal(spawned.command, "xdg-open"); assert.deepEqual(spawned.args, ["https://example.com/some path"]); assert.equal(spawned.options.detached, true); assert.equal(didUnref, true); }).pipe( Effect.provide( testLayer({ platform: "linux", onSpawn: (command) => { spawned = command; }, onUnref: () => { didUnref = true; }, }), ), );}); it.effect("launches an installed editor with platform-safe arguments", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); yield* fileSystem.writeFileString(path.join(binDir, "code.CMD"), "@echo off\r\n"); let spawned: ChildProcess.StandardCommand | undefined; yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchEditor({ editor: "vscode", cwd: "C:\\workspace with spaces\\src\\index.ts:12:4", }); }).pipe( Effect.provide( testLayer({ platform: "win32", env: { PATH: binDir, PATHEXT: ".COM;.EXE;.BAT;.CMD" }, resolveExecutable: (command) => command === "code" ? "C:\\Program Files\\Microsoft VS Code\\bin\\code.CMD" : command, onSpawn: (command) => { spawned = command; }, }), ), ); assert.ok(spawned); assert.equal(spawned.command, '^"C:\\Program^ Files\\Microsoft^ VS^ Code\\bin\\code.CMD^"'); assert.deepEqual(spawned.args, [ '^"--goto^"', '^"C:\\workspace^ with^ spaces\\src\\index.ts:12:4^"', ]); assert.equal(spawned.options.shell, true); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); it.effect("reveals a file in Finder with open -R on macOS", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); const openPath = path.join(binDir, "open"); yield* fileSystem.writeFileString(openPath, "#!/bin/sh\n"); yield* fileSystem.chmod(openPath, 0o755); let spawned: ChildProcess.StandardCommand | undefined; yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchEditor({ editor: "file-manager", cwd: "/workspace/media/linux-mini-v2.mp4", reveal: true, }); }).pipe( Effect.provide( testLayer({ platform: "darwin", env: { PATH: binDir }, onSpawn: (command) => { spawned = command; }, }), ), ); assert.ok(spawned); assert.equal(spawned.command, "open"); assert.deepEqual(spawned.args, ["-R", "/workspace/media/linux-mini-v2.mp4"]); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); it.effect("reveals a file in File Explorer through PowerShell on Windows", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); yield* fileSystem.writeFileString(path.join(binDir, "explorer.CMD"), "@echo off\r\n"); // resolvePowerShellPath builds `${SYSTEMROOT}\System32\...` with Windows // separators, which on the posix test filesystem is one file name. const systemRoot = path.join(binDir, "system-root"); const powerShellPath = `${systemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`; yield* fileSystem.makeDirectory(path.dirname(powerShellPath), { recursive: true }); yield* fileSystem.writeFileString(powerShellPath, ""); let spawned: ChildProcess.StandardCommand | undefined; const kind = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchEditor({ editor: "file-manager", cwd: "C:\\workspace with spaces\\media\\author's clip.mp4", reveal: true, }); return yield* launcher.resolveFileManagerRevealKind(); }).pipe( Effect.provide( testLayer({ platform: "win32", env: { PATH: binDir, PATHEXT: ".COM;.EXE;.BAT;.CMD", SYSTEMROOT: systemRoot }, onSpawn: (command) => { spawned = command; }, }), ), ); assert.equal(kind, "file-explorer"); assert.ok(spawned); assert.equal(spawned.command, powerShellPath); assert.deepEqual(spawned.args.slice(0, -1), [ "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand", ]); const encodedCommand = spawned.args[spawned.args.length - 1] ?? ""; const decodedCommand = Buffer.from(encodedCommand, "base64").toString("utf16le"); // explorer.exe expects `/select,"<path>"` with only the path quoted; // PowerShell 5.1's Start-Process passes the argument string verbatim. assert.equal( decodedCommand, "$ProgressPreference = 'SilentlyContinue'; Start-Process 'explorer.exe' -ArgumentList ('/select,\"' + 'C:\\workspace with spaces\\media\\author''s clip.mp4' + '\"')", ); assert.equal(spawned.options.shell, false); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); // Real-chain smoke check for the Explorer selection contract: runs the exact// PowerShell source the reveal launch encodes, against a stub that records// the raw argument tail it receives, and asserts a spaced path arrives as the// single `/select,"<path>"` switch. Mock argv assertions cannot prove this —// only Windows' own PowerShell -> CreateProcess quoting chain can, so the// test runs only where that chain exists.// oxlint-disable-next-line t3code/no-global-process-runtime -- the skip decision needs the real host platform, outside any Effect runtime.it.skipIf(process.platform !== "win32")( "delivers the raw /select switch for spaced paths through real PowerShell", { timeout: 60_000 }, async () => { const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-reveal-smoke-")); try { const recorderPath = NodePath.join(tempDir, "recorder.cmd"); const outputPath = NodePath.join(tempDir, "argv.txt"); NodeFS.writeFileSync(recorderPath, `@echo off\r\n>"${outputPath}" echo(%*\r\n`); const target = "C:\\workspace with spaces\\media\\author's clip.mp4"; const source = ExternalLauncher.buildFileExplorerRevealPowerShellSource(recorderPath, target); const powerShellPath = `${process.env.SYSTEMROOT ?? "C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`; NodeChildProcess.execFileSync( powerShellPath, [ "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand", Buffer.from(source, "utf16le").toString("base64"), ], { timeout: 30_000 }, ); // Start-Process returns before the recorder runs; wait for its output. // The waits run outside the Effect runtime on purpose: the test // exercises the real Windows process chain in real time. // @effect-diagnostics-next-line globalTimers:off const sleep = (millis: number) => new Promise((resolve) => setTimeout(resolve, millis)); // @effect-diagnostics-next-line globalDate:off const deadline = Date.now() + 20_000; // @effect-diagnostics-next-line globalDate:off while (!NodeFS.existsSync(outputPath) && Date.now() < deadline) { await sleep(100); } await sleep(200); const recorded = NodeFS.readFileSync(outputPath, "utf8").trim(); assert.equal(recorded, `/select,"${target}"`); } finally { NodeFS.rmSync(tempDir, { recursive: true, force: true }); } },); it.effect("does not advertise reveal on Windows when PowerShell is missing", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); yield* fileSystem.writeFileString(path.join(binDir, "explorer.CMD"), "@echo off\r\n"); const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; return { kind: yield* launcher.resolveFileManagerRevealKind(), editors: yield* launcher.resolveAvailableEditors(), }; }).pipe( Effect.provide( testLayer({ platform: "win32", env: { PATH: binDir, PATHEXT: ".COM;.EXE;.BAT;.CMD", SYSTEMROOT: path.join(binDir, "missing-system-root"), }, }), ), ); // Plain "open in file manager" still works through explorer; only the // reveal capability, which launches PowerShell, must stay hidden. assert.equal(result.editors.includes("file-manager"), true); assert.isUndefined(result.kind); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); it.effect("reveals a WSL file in Windows File Explorer through its UNC path", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); for (const name of ["explorer.exe", "powershell.exe", "xdg-open"]) { const filePath = path.join(binDir, name); yield* fileSystem.writeFileString(filePath, "#!/bin/sh\n"); yield* fileSystem.chmod(filePath, 0o755); } let spawned: ChildProcess.StandardCommand | undefined; const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; const kind = yield* launcher.resolveFileManagerRevealKind(); const editors = yield* launcher.resolveAvailableEditors(); yield* launcher.launchEditor({ editor: "file-manager", cwd: "/home/t3/workspace/media/clip.mp4", reveal: true, }); return { kind, editors }; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir, WSL_DISTRO_NAME: "Ubuntu-24.04", WSL_INTEROP: "/run/WSL/1_interop", }, onSpawn: (command) => { spawned = command; }, }), ), ); assert.equal(result.kind, "file-explorer"); assert.equal(result.editors.includes("file-manager"), true); assert.ok(spawned); // The reveal routes through interop PowerShell so Explorer receives its // raw `/select,"<path>"` switch even for spaced paths. assert.equal(spawned.command, "powershell.exe"); const encodedCommand = spawned.args[spawned.args.length - 1] ?? ""; const decodedCommand = Buffer.from(encodedCommand, "base64").toString("utf16le"); assert.equal( decodedCommand, "$ProgressPreference = 'SilentlyContinue'; Start-Process 'explorer.exe' -ArgumentList ('/select,\"' + '\\\\wsl.localhost\\Ubuntu-24.04\\home\\t3\\workspace\\media\\clip.mp4' + '\"')", ); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); it.effect("does not advertise reveal from WSL when interop PowerShell is missing", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); const explorerPath = path.join(binDir, "explorer.exe"); yield* fileSystem.writeFileString(explorerPath, ""); yield* fileSystem.chmod(explorerPath, 0o755); const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; return { kind: yield* launcher.resolveFileManagerRevealKind(), editors: yield* launcher.resolveAvailableEditors(), }; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir, WSL_DISTRO_NAME: "Ubuntu-24.04", WSL_INTEROP: "/run/WSL/1_interop", }, }), ), ); assert.equal(result.editors.includes("file-manager"), true); assert.isUndefined(result.kind); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); // When interop PowerShell is missing the capability advertises the Linux// "files" kind (or nothing), so the reveal must open the Linux file manager// the label promised even though plain open still prefers File Explorer.it.effect("reveals through the Linux file manager when WSL lacks interop PowerShell", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); for (const name of ["explorer.exe", "xdg-open", "xdg-mime"]) { const filePath = path.join(binDir, name); yield* fileSystem.writeFileString(filePath, "#!/bin/sh\n"); yield* fileSystem.chmod(filePath, 0o755); } const spawnedCommands: ChildProcess.StandardCommand[] = []; const kind = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; const revealKind = yield* launcher.resolveFileManagerRevealKind(); yield* launcher.launchEditor({ editor: "file-manager", cwd: "/home/t3/workspace/media/clip.mp4", reveal: true, }); return revealKind; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir, WSL_DISTRO_NAME: "Ubuntu-24.04", WSL_INTEROP: "/run/WSL/1_interop", DISPLAY: ":0", }, onSpawn: (command) => { spawnedCommands.push(command); }, spawnResult: (command) => command.command === "xdg-mime" ? { stdout: "org.gnome.Nautilus.desktop\n" } : undefined, }), ), ); assert.equal(kind, "files"); const launch = spawnedCommands.find((command) => command.command === "xdg-open"); assert.ok(launch); assert.deepEqual(launch.args, ["/home/t3/workspace/media"]); assert.isUndefined(spawnedCommands.find((command) => command.command === "explorer.exe")); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),); // Interop can exist without `explorer.exe` on PATH (appendWindowsPath=false)// while WSLg still provides a working Linux file manager; the host must keep// the Linux open/reveal path instead of losing the editor entirely.it.effect("falls back to the Linux file manager when WSL lacks the Explorer bridge", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); for (const name of ["xdg-open", "xdg-mime"]) { const filePath = path.join(binDir, name); yield* fileSystem.writeFileString(filePath, "#!/bin/sh\n"); yield* fileSystem.chmod(filePath, 0o755); } const spawnedCommands: ChildProcess.StandardCommand[] = []; const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; const editors = yield* launcher.resolveAvailableEditors(); const kind = yield* launcher.resolveFileManagerRevealKind(); yield* launcher.launchEditor({ editor: "file-manager", cwd: "/home/t3/workspace/media/clip.mp4", reveal: true, }); return { editors, kind }; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir,Lines 1–500 of 932. Load more
// @effect-diagnostics nodeBuiltinImport:off - the Windows reveal smoke test drives a real PowerShell through Node process and filesystem APIs. import * as NodeChildProcess from "node:child_process"; import * as NodeFS from "node:fs"; import * as NodeOS from "node:os"; import * as NodePath from "node:path"; import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; import * as ConfigProvider from "effect/ConfigProvider"; import * as Effect from "effect/Effect"; import * as Fiber from "effect/Fiber"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Path from "effect/Path"; import * as Sink from "effect/Sink"; import * as Stream from "effect/Stream"; import * as TestClock from "effect/testing/TestClock"; import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; import { SpawnExecutableResolution } from "@t3tools/shared/shell"; import * as ExternalLauncher from "./externalLauncher.ts"; interface MockSpawnResult { readonly exitCode?: number; readonly stdout?: string; /** Never deliver an exit code, like a child wedged on a broken desktop session. */ readonly stall?: boolean; } function makeMockDetachedHandle(input: MockSpawnResult & { readonly onUnref?: () => void } = {}) { return ChildProcessSpawner.makeHandle({ pid: ChildProcessSpawner.ProcessId(1), exitCode: input.stall ? Effect.never : Effect.succeed(ChildProcessSpawner.ExitCode(input.exitCode ?? 0)), isRunning: Effect.succeed(true), kill: () => Effect.void, unref: Effect.sync(() => { input.onUnref?.(); return Effect.void; }), stdin: Sink.drain, stdout: input.stdout === undefined ? Stream.empty : Stream.make(new TextEncoder().encode(input.stdout)), stderr: Stream.empty, all: Stream.empty, getInputFd: () => Sink.drain, getOutputFd: () => Stream.empty, }); } const testLayer = (input: { readonly platform: NodeJS.Platform; readonly env?: Record<string, string>; readonly resolveExecutable?: (command: string) => string | undefined; readonly onSpawn?: (command: ChildProcess.StandardCommand) => void; readonly onUnref?: () => void; readonly spawnResult?: (command: ChildProcess.StandardCommand) => MockSpawnResult | undefined; }) => { const spawnerLayer = Layer.succeed( ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make((command) => Effect.sync(() => { assert.equal(ChildProcess.isStandardCommand(command), true); if (!ChildProcess.isStandardCommand(command)) { throw new Error("Expected a standard command"); } input.onSpawn?.(command); return makeMockDetachedHandle({ ...(input.onUnref === undefined ? {} : { onUnref: input.onUnref }), ...input.spawnResult?.(command), }); }), ), ); return Layer.mergeAll( ExternalLauncher.layer.pipe(Layer.provide(Layer.merge(NodeServices.layer, spawnerLayer))), Layer.succeed(HostProcessPlatform, input.platform), Layer.succeed( SpawnExecutableResolution, (command) => input.resolveExecutable?.(command) ?? command, ), ConfigProvider.layer(ConfigProvider.fromEnv({ env: input.env ?? {} })), ); }; it.effect("launches the default browser through the platform command", () => { let spawned: ChildProcess.StandardCommand | undefined; let didUnref = false; return Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchBrowser("https://example.com/some path"); assert.ok(spawned); assert.equal(spawned.command, "xdg-open"); assert.deepEqual(spawned.args, ["https://example.com/some path"]); assert.equal(spawned.options.detached, true); assert.equal(didUnref, true); }).pipe( Effect.provide( testLayer({ platform: "linux", onSpawn: (command) => { spawned = command; }, onUnref: () => { didUnref = true; }, }), ), ); }); it.effect("launches an installed editor with platform-safe arguments", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); yield* fileSystem.writeFileString(path.join(binDir, "code.CMD"), "@echo off\r\n"); let spawned: ChildProcess.StandardCommand | undefined; yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchEditor({ editor: "vscode", cwd: "C:\\workspace with spaces\\src\\index.ts:12:4", }); }).pipe( Effect.provide( testLayer({ platform: "win32", env: { PATH: binDir, PATHEXT: ".COM;.EXE;.BAT;.CMD" }, resolveExecutable: (command) => command === "code" ? "C:\\Program Files\\Microsoft VS Code\\bin\\code.CMD" : command, onSpawn: (command) => { spawned = command; }, }), ), ); assert.ok(spawned); assert.equal(spawned.command, '^"C:\\Program^ Files\\Microsoft^ VS^ Code\\bin\\code.CMD^"'); assert.deepEqual(spawned.args, [ '^"--goto^"', '^"C:\\workspace^ with^ spaces\\src\\index.ts:12:4^"', ]); assert.equal(spawned.options.shell, true); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("reveals a file in Finder with open -R on macOS", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); const openPath = path.join(binDir, "open"); yield* fileSystem.writeFileString(openPath, "#!/bin/sh\n"); yield* fileSystem.chmod(openPath, 0o755); let spawned: ChildProcess.StandardCommand | undefined; yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchEditor({ editor: "file-manager", cwd: "/workspace/media/linux-mini-v2.mp4", reveal: true, }); }).pipe( Effect.provide( testLayer({ platform: "darwin", env: { PATH: binDir }, onSpawn: (command) => { spawned = command; }, }), ), ); assert.ok(spawned); assert.equal(spawned.command, "open"); assert.deepEqual(spawned.args, ["-R", "/workspace/media/linux-mini-v2.mp4"]); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("reveals a file in File Explorer through PowerShell on Windows", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); yield* fileSystem.writeFileString(path.join(binDir, "explorer.CMD"), "@echo off\r\n"); // resolvePowerShellPath builds `${SYSTEMROOT}\System32\...` with Windows // separators, which on the posix test filesystem is one file name. const systemRoot = path.join(binDir, "system-root"); const powerShellPath = `${systemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`; yield* fileSystem.makeDirectory(path.dirname(powerShellPath), { recursive: true }); yield* fileSystem.writeFileString(powerShellPath, ""); let spawned: ChildProcess.StandardCommand | undefined; const kind = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; yield* launcher.launchEditor({ editor: "file-manager", cwd: "C:\\workspace with spaces\\media\\author's clip.mp4", reveal: true, }); return yield* launcher.resolveFileManagerRevealKind(); }).pipe( Effect.provide( testLayer({ platform: "win32", env: { PATH: binDir, PATHEXT: ".COM;.EXE;.BAT;.CMD", SYSTEMROOT: systemRoot }, onSpawn: (command) => { spawned = command; }, }), ), ); assert.equal(kind, "file-explorer"); assert.ok(spawned); assert.equal(spawned.command, powerShellPath); assert.deepEqual(spawned.args.slice(0, -1), [ "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand", ]); const encodedCommand = spawned.args[spawned.args.length - 1] ?? ""; const decodedCommand = Buffer.from(encodedCommand, "base64").toString("utf16le"); // explorer.exe expects `/select,"<path>"` with only the path quoted; // PowerShell 5.1's Start-Process passes the argument string verbatim. assert.equal( decodedCommand, "$ProgressPreference = 'SilentlyContinue'; Start-Process 'explorer.exe' -ArgumentList ('/select,\"' + 'C:\\workspace with spaces\\media\\author''s clip.mp4' + '\"')", ); assert.equal(spawned.options.shell, false); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); // Real-chain smoke check for the Explorer selection contract: runs the exact // PowerShell source the reveal launch encodes, against a stub that records // the raw argument tail it receives, and asserts a spaced path arrives as the // single `/select,"<path>"` switch. Mock argv assertions cannot prove this — // only Windows' own PowerShell -> CreateProcess quoting chain can, so the // test runs only where that chain exists. // oxlint-disable-next-line t3code/no-global-process-runtime -- the skip decision needs the real host platform, outside any Effect runtime. it.skipIf(process.platform !== "win32")( "delivers the raw /select switch for spaced paths through real PowerShell", { timeout: 60_000 }, async () => { const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-reveal-smoke-")); try { const recorderPath = NodePath.join(tempDir, "recorder.cmd"); const outputPath = NodePath.join(tempDir, "argv.txt"); NodeFS.writeFileSync(recorderPath, `@echo off\r\n>"${outputPath}" echo(%*\r\n`); const target = "C:\\workspace with spaces\\media\\author's clip.mp4"; const source = ExternalLauncher.buildFileExplorerRevealPowerShellSource(recorderPath, target); const powerShellPath = `${process.env.SYSTEMROOT ?? "C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`; NodeChildProcess.execFileSync( powerShellPath, [ "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand", Buffer.from(source, "utf16le").toString("base64"), ], { timeout: 30_000 }, ); // Start-Process returns before the recorder runs; wait for its output. // The waits run outside the Effect runtime on purpose: the test // exercises the real Windows process chain in real time. // @effect-diagnostics-next-line globalTimers:off const sleep = (millis: number) => new Promise((resolve) => setTimeout(resolve, millis)); // @effect-diagnostics-next-line globalDate:off const deadline = Date.now() + 20_000; // @effect-diagnostics-next-line globalDate:off while (!NodeFS.existsSync(outputPath) && Date.now() < deadline) { await sleep(100); } await sleep(200); const recorded = NodeFS.readFileSync(outputPath, "utf8").trim(); assert.equal(recorded, `/select,"${target}"`); } finally { NodeFS.rmSync(tempDir, { recursive: true, force: true }); } }, ); it.effect("does not advertise reveal on Windows when PowerShell is missing", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); yield* fileSystem.writeFileString(path.join(binDir, "explorer.CMD"), "@echo off\r\n"); const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; return { kind: yield* launcher.resolveFileManagerRevealKind(), editors: yield* launcher.resolveAvailableEditors(), }; }).pipe( Effect.provide( testLayer({ platform: "win32", env: { PATH: binDir, PATHEXT: ".COM;.EXE;.BAT;.CMD", SYSTEMROOT: path.join(binDir, "missing-system-root"), }, }), ), ); // Plain "open in file manager" still works through explorer; only the // reveal capability, which launches PowerShell, must stay hidden. assert.equal(result.editors.includes("file-manager"), true); assert.isUndefined(result.kind); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("reveals a WSL file in Windows File Explorer through its UNC path", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); for (const name of ["explorer.exe", "powershell.exe", "xdg-open"]) { const filePath = path.join(binDir, name); yield* fileSystem.writeFileString(filePath, "#!/bin/sh\n"); yield* fileSystem.chmod(filePath, 0o755); } let spawned: ChildProcess.StandardCommand | undefined; const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; const kind = yield* launcher.resolveFileManagerRevealKind(); const editors = yield* launcher.resolveAvailableEditors(); yield* launcher.launchEditor({ editor: "file-manager", cwd: "/home/t3/workspace/media/clip.mp4", reveal: true, }); return { kind, editors }; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir, WSL_DISTRO_NAME: "Ubuntu-24.04", WSL_INTEROP: "/run/WSL/1_interop", }, onSpawn: (command) => { spawned = command; }, }), ), ); assert.equal(result.kind, "file-explorer"); assert.equal(result.editors.includes("file-manager"), true); assert.ok(spawned); // The reveal routes through interop PowerShell so Explorer receives its // raw `/select,"<path>"` switch even for spaced paths. assert.equal(spawned.command, "powershell.exe"); const encodedCommand = spawned.args[spawned.args.length - 1] ?? ""; const decodedCommand = Buffer.from(encodedCommand, "base64").toString("utf16le"); assert.equal( decodedCommand, "$ProgressPreference = 'SilentlyContinue'; Start-Process 'explorer.exe' -ArgumentList ('/select,\"' + '\\\\wsl.localhost\\Ubuntu-24.04\\home\\t3\\workspace\\media\\clip.mp4' + '\"')", ); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("does not advertise reveal from WSL when interop PowerShell is missing", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); const explorerPath = path.join(binDir, "explorer.exe"); yield* fileSystem.writeFileString(explorerPath, ""); yield* fileSystem.chmod(explorerPath, 0o755); const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; return { kind: yield* launcher.resolveFileManagerRevealKind(), editors: yield* launcher.resolveAvailableEditors(), }; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir, WSL_DISTRO_NAME: "Ubuntu-24.04", WSL_INTEROP: "/run/WSL/1_interop", }, }), ), ); assert.equal(result.editors.includes("file-manager"), true); assert.isUndefined(result.kind); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); // When interop PowerShell is missing the capability advertises the Linux // "files" kind (or nothing), so the reveal must open the Linux file manager // the label promised even though plain open still prefers File Explorer. it.effect("reveals through the Linux file manager when WSL lacks interop PowerShell", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); for (const name of ["explorer.exe", "xdg-open", "xdg-mime"]) { const filePath = path.join(binDir, name); yield* fileSystem.writeFileString(filePath, "#!/bin/sh\n"); yield* fileSystem.chmod(filePath, 0o755); } const spawnedCommands: ChildProcess.StandardCommand[] = []; const kind = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; const revealKind = yield* launcher.resolveFileManagerRevealKind(); yield* launcher.launchEditor({ editor: "file-manager", cwd: "/home/t3/workspace/media/clip.mp4", reveal: true, }); return revealKind; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir, WSL_DISTRO_NAME: "Ubuntu-24.04", WSL_INTEROP: "/run/WSL/1_interop", DISPLAY: ":0", }, onSpawn: (command) => { spawnedCommands.push(command); }, spawnResult: (command) => command.command === "xdg-mime" ? { stdout: "org.gnome.Nautilus.desktop\n" } : undefined, }), ), ); assert.equal(kind, "files"); const launch = spawnedCommands.find((command) => command.command === "xdg-open"); assert.ok(launch); assert.deepEqual(launch.args, ["/home/t3/workspace/media"]); assert.isUndefined(spawnedCommands.find((command) => command.command === "explorer.exe")); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); // Interop can exist without `explorer.exe` on PATH (appendWindowsPath=false) // while WSLg still provides a working Linux file manager; the host must keep // the Linux open/reveal path instead of losing the editor entirely. it.effect("falls back to the Linux file manager when WSL lacks the Explorer bridge", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const binDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-editors-" }); for (const name of ["xdg-open", "xdg-mime"]) { const filePath = path.join(binDir, name); yield* fileSystem.writeFileString(filePath, "#!/bin/sh\n"); yield* fileSystem.chmod(filePath, 0o755); } const spawnedCommands: ChildProcess.StandardCommand[] = []; const result = yield* Effect.gen(function* () { const launcher = yield* ExternalLauncher.ExternalLauncher; const editors = yield* launcher.resolveAvailableEditors(); const kind = yield* launcher.resolveFileManagerRevealKind(); yield* launcher.launchEditor({ editor: "file-manager", cwd: "/home/t3/workspace/media/clip.mp4", reveal: true, }); return { editors, kind }; }).pipe( Effect.provide( testLayer({ platform: "linux", env: { PATH: binDir,