import { join } from "path"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; const CLI_PATH = join(import.meta.dir, "../src/cli.ts"); export interface CLIResult { stdout: string; stderr: string; exitCode: number; } export async function runCLI(args: string[], preload?: string): Promise { const proc = Bun.spawn(["bun", "run", ...(preload ? ["--preload", preload] : []), CLI_PATH, ...args], { stdout: "pipe", stderr: "pipe", }); const [stdout, stderr, exitCode] = await Promise.all([ new Response(proc.stdout).text(), new Response(proc.stderr).text(), proc.exited, ]); return { stdout: stdout.trim(), stderr: stderr.trim(), exitCode }; } /** Run valid search controls through the real CLI with a saved, offline response. */ export async function runSearchFixture(args: string[]): Promise<{ result: CLIResult; requests: URL[] }> { const requests: URL[] = []; const server = Bun.serve({ hostname: "127.0.0.1", port: 0, async fetch(request) { requests.push(new URL(request.url)); return new Response(await Bun.file(join(import.meta.dir, "fixtures/search-cards.json")).json()); }, }); const dir = mkdtempSync(join(tmpdir(), "linkedin-valid-flags-")); const preload = join(dir, "fetch.ts"); writeFileSync(preload, ` const originalFetch = globalThis.fetch; globalThis.fetch = (input, init) => { const url = new URL(input instanceof Request ? input.url : String(input)); if (url.origin !== "https://www.linkedin.com" || url.pathname !== "/jobs-guest/jobs/api/seeMoreJobPostings/search") { throw new Error("Unexpected search fixture request"); } return originalFetch(${JSON.stringify(server.url.origin)} + url.pathname + url.search, init); }; `); try { return { result: await runCLI(args, preload), requests }; } finally { server.stop(true); rmSync(dir, { recursive: true, force: true }); } } export function parseJSON(result: CLIResult): T { if (result.exitCode !== 0) { throw new Error( `CLI exited with code ${result.exitCode}. stderr: ${result.stderr}` ); } try { return JSON.parse(result.stdout) as T; } catch { throw new Error( `Failed to parse JSON. stdout: ${result.stdout}\nstderr: ${result.stderr}` ); } }