import assert from "node:assert/strict"; import test from "node:test"; import { parseRemotePathProbe, probeRemotePath } from "../src/remote-probe.ts"; import type { RemoteExecOptions, RemoteTransport } from "../src/ssh2-transport.ts"; class ProbeTransport implements RemoteTransport { command = ""; cwd = ""; connect(): Promise { return Promise.resolve(); } dispose(): Promise { return Promise.resolve(); } exec(command: string, cwd: string, options: RemoteExecOptions): Promise<{ exitCode: number | null }> { this.command = command; this.cwd = cwd; const start = command.match(/'(__PI_SSH_PROBE_[a-f0-9]+_START__)'/)?.[1]; const end = command.match(/'(__PI_SSH_PROBE_[a-f0-9]+_END__)'/)?.[1]; if (!start || !end) throw new Error("probe markers missing"); options.onData(Buffer.from(`login banner\n${start}/srv/project${end}\nlogout banner\n`)); return Promise.resolve({ exitCode: 0 }); } capture(): Promise<{ exitCode: number | null; output: Buffer }> { throw new Error("not used"); } readFile(): Promise { throw new Error("not used"); } ensureReadable(): Promise { throw new Error("not used"); } ensureReadableWritable(): Promise { throw new Error("not used"); } detectImageMimeType(): Promise { throw new Error("not used"); } mkdir(): Promise { throw new Error("not used"); } writeFile(): Promise { throw new Error("not used"); } } test("extracts one framed absolute path while ignoring shell startup output", async () => { const transport = new ProbeTransport(); assert.equal(await probeRemotePath(transport, "cwd", "/srv"), "/srv/project"); assert.equal(transport.cwd, "/srv"); assert.match(transport.command, /pwd -P/); }); test("rejects unframed, relative, multiline, and oversized path probes", () => { assert.throws(() => parseRemotePathProbe(Buffer.from("/srv"), "START", "END", "cwd"), /invalid framed/); assert.throws(() => parseRemotePathProbe(Buffer.from("STARTrelativeEND"), "START", "END", "cwd"), /absolute POSIX path/); assert.throws(() => parseRemotePathProbe(Buffer.from("START/srv\notherEND"), "START", "END", "cwd"), /absolute POSIX path/); assert.throws( () => parseRemotePathProbe(Buffer.alloc(64 * 1024 + 1), "START", "END", "cwd"), /exceeded 65536 bytes/, ); }); test("forwards cancellation to the probe exec call", async () => { const controller = new AbortController(); controller.abort(); const transport = new ProbeTransport(); const original = transport.exec.bind(transport); transport.exec = (command, cwd, options) => { assert.equal(options.signal, controller.signal); if (options.signal?.aborted) return Promise.reject(new Error("SSH command aborted")); return original(command, cwd, options); }; await assert.rejects(probeRemotePath(transport, "home", ".", controller.signal), /SSH command aborted/); });