import assert from "node:assert/strict"; import { test } from "vitest"; const { runSubprocess, resolveModulePaths } = await import( "../web/subprocess-runner.ts" ); // --------------------------------------------------------------------------- // resolveModulePaths — centralised TS loader + module path resolution // --------------------------------------------------------------------------- test("resolveModulePaths returns tsLoaderPath and validates it exists", () => { const packageRoot = "/fake/package"; const result = resolveModulePaths(packageRoot, { modules: [{ envKey: "MOD", relativePath: "src/mod.ts" }], existsSync: () => true, }); assert.equal( result.tsLoaderPath, "/fake/package/src/resources/extensions/sf/tests/resolve-ts.mjs", ); }); test("resolveModulePaths throws when TS loader is missing", () => { const packageRoot = "/fake/package"; assert.throws( () => resolveModulePaths(packageRoot, { modules: [{ envKey: "MOD", relativePath: "src/mod.ts" }], existsSync: () => false, label: "test-service", }), (error: Error) => { assert.match(error.message, /test-service/); assert.match(error.message, /not found/); return true; }, ); }); test("resolveModulePaths throws when any module path is missing", () => { const packageRoot = "/fake/package"; const existingSets = new Set([ "/fake/package/src/resources/extensions/sf/tests/resolve-ts.mjs", ]); assert.throws( () => resolveModulePaths(packageRoot, { modules: [ { envKey: "MOD_A", relativePath: "src/a.ts" }, { envKey: "MOD_B", relativePath: "src/b.ts" }, ], existsSync: (p: string) => existingSets.has(p), label: "multi-mod", }), (error: Error) => { assert.match(error.message, /multi-mod/); return true; }, ); }); test("resolveModulePaths returns env entries for each module", () => { const packageRoot = "/fake/package"; const result = resolveModulePaths(packageRoot, { modules: [ { envKey: "SF_MOD_A", relativePath: "src/a.ts" }, { envKey: "SF_MOD_B", relativePath: "src/b.ts" }, ], existsSync: () => true, }); assert.deepEqual(result.env, { SF_MOD_A: "/fake/package/src/a.ts", SF_MOD_B: "/fake/package/src/b.ts", }); }); // --------------------------------------------------------------------------- // runSubprocess — shared execFile + JSON.parse wrapper // --------------------------------------------------------------------------- test("runSubprocess returns parsed JSON from a child process", async () => { const result = await runSubprocess<{ hello: string }>({ packageRoot: process.cwd(), script: 'process.stdout.write(JSON.stringify({ hello: "world" }));', env: {}, label: "test", }); assert.deepEqual(result, { hello: "world" }); }); test("runSubprocess rejects when child process exits with error", async () => { await assert.rejects( () => runSubprocess({ packageRoot: process.cwd(), script: "process.exit(1);", env: {}, label: "exit-test", }), (error: Error) => { assert.match(error.message, /exit-test/); assert.match(error.message, /subprocess failed/); return true; }, ); }); test("runSubprocess rejects on invalid JSON output", async () => { await assert.rejects( () => runSubprocess({ packageRoot: process.cwd(), script: 'process.stdout.write("not json");', env: {}, label: "json-test", }), (error: Error) => { assert.match(error.message, /json-test/); assert.match(error.message, /invalid JSON/); return true; }, ); }); test("runSubprocess applies timeout option", async () => { await assert.rejects( () => runSubprocess({ packageRoot: process.cwd(), script: "setTimeout(() => {}, 60000);", env: {}, label: "timeout-test", timeoutMs: 500, }), (error: Error) => { assert.match(error.message, /timeout-test/); return true; }, ); }); test("runSubprocess accepts custom maxBuffer", async () => { // Verify it does not throw with a reasonable buffer const result = await runSubprocess<{ ok: boolean }>({ packageRoot: process.cwd(), script: "process.stdout.write(JSON.stringify({ ok: true }));", env: {}, label: "buffer-test", maxBuffer: 512, }); assert.equal(result.ok, true); }); test("runSubprocess passes env vars to child process", async () => { const result = await runSubprocess<{ val: string }>({ packageRoot: process.cwd(), script: "process.stdout.write(JSON.stringify({ val: process.env.TEST_VAR }));", env: { TEST_VAR: "hello_from_parent" }, label: "env-test", }); assert.equal(result.val, "hello_from_parent"); }); test("runSubprocess includes stderr in error message on failure", async () => { await assert.rejects( () => runSubprocess({ packageRoot: process.cwd(), script: 'process.stderr.write("detailed error info"); process.exit(1);', env: {}, label: "stderr-test", }), (error: Error) => { assert.match(error.message, /detailed error info/); return true; }, ); });