import { mkdir, mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; import { getScanStatus, startOnboardingScan } from "./onboarding-scan.js"; const owner = { userId: "user-owner", isDeploymentOwner: true }; const member = { userId: "user-member", isDeploymentOwner: false }; async function scanHomeWithOneFile(): Promise { const home = await mkdtemp(join(tmpdir(), "evoo-scan-")); await mkdir(join(home, "Projects")); await writeFile(join(home, "Projects", "notes.ts"), "export const x = 1;\n"); return home; } async function completed(scanId: string, userId: string) { return await vi.waitFor( async () => { const status = await getScanStatus(scanId, userId); if (status.status !== "complete" && status.status !== "failed") throw new Error("pending"); return status; }, { timeout: 10_000, interval: 50 }, ); } describe("onboarding scan", () => { afterEach(() => { vi.unstubAllEnvs(); }); it("hides a scan from every account except the one that started it", async () => { const { scanId } = await startOnboardingScan({ actor: member }, {}); await expect(getScanStatus(scanId, owner.userId)).rejects.toThrow(/Scan not found/); await expect(getScanStatus(scanId, member.userId)).resolves.toMatchObject({ status: expect.any(String), }); await expect(getScanStatus("scan_missing", member.userId)).rejects.toThrow(/Scan not found/); }); it("never reads the host without a configured scan home", async () => { const { scanId } = await startOnboardingScan({ actor: owner }, {}); const status = await completed(scanId, owner.userId); expect(status.status).toBe("complete"); expect(status.result).toMatchObject({ localRepos: [], fileSummary: { totalFiles: 0 } }); }); it("lets only the deployment owner discover the configured scan home", async () => { // The shared test setup pins the emulated runtime, which also keeps the scan simulated. vi.stubEnv("AGENT_RUNTIME", ""); vi.stubEnv("SANDBOX_PROVIDER", ""); const scanHome = await scanHomeWithOneFile(); const asMember = await startOnboardingScan({ actor: member, scanHome }, {}); const memberStatus = await completed(asMember.scanId, member.userId); expect(memberStatus.result).toMatchObject({ fileSummary: { totalFiles: 0 } }); const asOwner = await startOnboardingScan({ actor: owner, scanHome }, {}); const ownerStatus = await completed(asOwner.scanId, owner.userId); expect(ownerStatus.status).toBe("complete"); expect(ownerStatus.result).toMatchObject({ fileSummary: { totalFiles: 1 } }); }); });