diff --git a/packages/cli/package.json b/packages/cli/package.json index 08092fc6..873c064e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.15.31", + "version": "0.15.32", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/__tests__/orchestrate.test.ts b/packages/cli/src/__tests__/orchestrate.test.ts index c9b03311..adc973d6 100644 --- a/packages/cli/src/__tests__/orchestrate.test.ts +++ b/packages/cli/src/__tests__/orchestrate.test.ts @@ -10,7 +10,10 @@ * bleed into with-retry-result.test.ts which tests the real wrapSshCall. */ -import { beforeEach, describe, expect, it, mock, spyOn } from "bun:test"; +import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test"; +import { mkdirSync, rmSync } from "node:fs"; +import { homedir } from "node:os"; +import { join } from "node:path"; import { isNumber } from "../shared/type-guards.js"; // ── Mock oauth + tarball (needed to avoid interactive prompts / network) ── @@ -101,9 +104,18 @@ describe("runOrchestration", () => { let exitSpy: ReturnType; let capturedExitCode: number | undefined; let stderrSpy: ReturnType; + let testDir: string; + let savedSpawnHome: string | undefined; beforeEach(() => { capturedExitCode = undefined; + // Isolate history writes to a temp directory so tests never pollute ~/.spawn + testDir = join(homedir(), `.spawn-test-orch-${Date.now()}-${Math.random()}`); + mkdirSync(testDir, { + recursive: true, + }); + savedSpawnHome = process.env.SPAWN_HOME; + process.env.SPAWN_HOME = testDir; // Skip GitHub auth prompts during tests process.env.SPAWN_SKIP_GITHUB_AUTH = "1"; stderrSpy = spyOn(process.stderr, "write").mockImplementation(() => true); @@ -117,6 +129,22 @@ describe("runOrchestration", () => { mockTryTarballInstall.mockImplementation(() => Promise.resolve(false)); }); + afterEach(() => { + if (savedSpawnHome !== undefined) { + process.env.SPAWN_HOME = savedSpawnHome; + } else { + delete process.env.SPAWN_HOME; + } + try { + rmSync(testDir, { + recursive: true, + force: true, + }); + } catch { + // best-effort cleanup + } + }); + it("calls all cloud lifecycle methods in correct order", async () => { const callOrder: string[] = []; const cloud = createMockCloud({