/** * E2E test fixture generator for the Electrobun prototype. * * Creates isolated temp directories with demo groups.json, settings.db, * and a scratch git repo. Cleanup happens automatically on test end. */ import { mkdirSync, writeFileSync, rmSync } from "node:fs"; import { execSync } from "node:child_process"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { randomUUID } from "node:crypto"; export interface TestFixture { /** Root temp directory for this test run. */ rootDir: string; /** ~/.config/agor equivalent for test isolation. */ configDir: string; /** ~/.local/share/agor equivalent for test isolation. */ dataDir: string; /** A scratch git repo with an initial commit. */ repoDir: string; /** Environment variables to pass to the app process. */ env: Record; /** Remove all fixture files (best-effort). */ cleanup: () => void; } /** Default groups matching the app's seed data. */ const DEMO_GROUPS = [ { id: "dev", name: "Development", icon: "\uD83D\uDD27", position: 0 }, { id: "test", name: "Testing", icon: "\uD83E\uddEA", position: 1 }, { id: "ops", name: "DevOps", icon: "\uD83D\uDE80", position: 2 }, { id: "research", name: "Research", icon: "\uD83D\uDD2C", position: 3 }, ]; /** Demo project config for test assertions. */ const DEMO_PROJECTS = [ { id: "test-project-1", name: "test-project", cwd: "", // filled in with repoDir accent: "var(--ctp-mauve)", provider: "claude", groupId: "dev", }, ]; /** * Create an isolated test fixture with config/data dirs, groups.json, * and a git repo with one commit. */ export function createTestFixture(prefix = "agor-ebun-e2e"): TestFixture { const rootDir = join(tmpdir(), `${prefix}-${randomUUID().slice(0, 8)}`); const configDir = join(rootDir, "config", "agor"); const dataDir = join(rootDir, "data", "agor"); const repoDir = join(rootDir, "repo"); // Create directory tree mkdirSync(configDir, { recursive: true }); mkdirSync(dataDir, { recursive: true }); mkdirSync(repoDir, { recursive: true }); // Write demo groups.json writeFileSync( join(configDir, "groups.json"), JSON.stringify({ groups: DEMO_GROUPS }, null, 2), ); // Update demo project CWD to point at the scratch repo const projects = DEMO_PROJECTS.map((p) => ({ ...p, cwd: repoDir })); writeFileSync( join(configDir, "projects.json"), JSON.stringify(projects, null, 2), ); // Initialise a scratch git repo with one commit execSync("git init && git commit --allow-empty -m 'init'", { cwd: repoDir, stdio: "ignore", env: { ...process.env, GIT_AUTHOR_NAME: "test", GIT_AUTHOR_EMAIL: "test@test", GIT_COMMITTER_NAME: "test", GIT_COMMITTER_EMAIL: "test@test", }, }); const env: Record = { AGOR_TEST: "1", AGOR_TEST_CONFIG_DIR: configDir, AGOR_TEST_DATA_DIR: dataDir, }; function cleanup() { try { rmSync(rootDir, { recursive: true, force: true }); } catch { /* best-effort */ } } return { rootDir, configDir, dataDir, repoDir, env, cleanup }; }