/** * Vitest configuration for singularity-forge. * * Runs tests directly from TypeScript source — no esbuild pre-compilation needed. * Vitest handles TypeScript transformation via esbuild (bundled, not separate process). * * Coverage uses @vitest/coverage-v8 (same engine as c8, but integrated). * * Usage: * npx vitest run # run all tests once * npx vitest # watch mode * npx vitest run --changed # only tests affected by recent changes */ import { defineConfig } from "vitest/config"; import { resolve } from "node:path"; const __dirname = import.meta.dirname; export default defineConfig({ test: { // ── File patterns ───────────────────────────────────────────────────────── // Files without vitest imports (standalone test scripts that run assertions // directly at module load time — these are skipped by the old node --test // runner and must be excluded here too to avoid "No test suite found" errors. exclude: [ // Standalone script-style tests (no describe/test, custom assertEq) // (converted to vitest describe/it style) "packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts", // SF integration tests without vitest test/it calls (WIP or script-style) "src/resources/extensions/sf/tests/integration/git-self-heal.test.ts", "src/resources/extensions/sf/tests/integration/queue-completed-milestone-perf.test.ts", "src/resources/extensions/sf/tests/integration/token-savings.test.ts", "src/resources/extensions/sf/tests/integration/worktree-e2e.test.ts", "src/resources/extensions/sf/tests/auto-start-worktree-db-path.test.ts", "src/resources/extensions/sf/tests/complete-task.test.ts", "src/resources/extensions/sf/tests/derive-state-db-disk-reconcile.test.ts", "src/resources/extensions/sf/tests/doctor-fix-flag.test.ts", "src/resources/extensions/sf/tests/draft-promotion.test.ts", "src/resources/extensions/sf/tests/merge-conflict-stops-loop.test.ts", "src/resources/extensions/sf/tests/planning-crossval.test.ts", "src/resources/extensions/sf/tests/recovery-attempts-reset.test.ts", "src/resources/extensions/sf/tests/slice-disk-reconcile.test.ts", "src/resources/extensions/sf/tests/survivor-branch-complete.test.ts", "src/resources/extensions/sf/tests/tool-naming.test.ts", "src/resources/extensions/sf/tests/unit-runtime.test.ts", "src/resources/extensions/sf/tests/worker-registry.test.ts", "src/resources/extensions/sf/tests/worktree-health-monorepo.test.ts", "src/resources/extensions/sf/tests/worktree-submodule-safety.test.ts", "src/resources/extensions/sf/tests/worktree-sync-overwrite-loop.test.ts", "src/resources/extensions/sf/tests/zombie-sf-state.test.ts", ], include: [ "src/tests/**/*.test.ts", "src/tests/**/*.test.mjs", "src/resources/extensions/sf/tests/**/*.test.ts", "src/resources/extensions/sf/tests/**/*.test.mjs", "src/resources/extensions/shared/tests/**/*.test.ts", "src/resources/extensions/claude-code-cli/tests/**/*.test.ts", "src/resources/extensions/github-sync/tests/**/*.test.ts", "src/resources/extensions/universal-config/tests/**/*.test.ts", "src/resources/extensions/voice/tests/**/*.test.ts", "src/resources/extensions/vectordrive/tests/**/*.test.ts", "src/resources/extensions/mcp-client/tests/**/*.test.ts", "src/resources/extensions/async-jobs/*.test.ts", "src/resources/extensions/browser-tools/tests/*.test.mjs", "packages/pi-coding-agent/src/**/*.test.ts", "packages/pi-ai/src/**/*.test.ts", "packages/pi-agent-core/src/**/*.test.ts", "packages/pi-tui/src/**/*.test.ts", "packages/daemon/src/**/*.test.ts", "packages/mcp-server/src/**/*.test.ts", "packages/rpc-client/src/**/*.test.ts", "packages/native/src/**/*.test.mjs", "web/lib/**/*.test.ts", "studio/test/**/*.test.mjs", "scripts/*.test.mjs", ], // ── Timeouts ────────────────────────────────────────────────────────────── testTimeout: 30_000, hookTimeout: 30_000, // ── Pool: forks = one Node process per test file (best for Node.js tests) ─ pool: "forks", // Single worker in CI; parallel in dev for speed singleFork: process.env.CI === "true", // ── Coverage ────────────────────────────────────────────────────────────── coverage: { provider: "v8", reporter: ["text", "lcov"], exclude: [ "src/resources/extensions/sf/tests/**", "src/tests/**", "scripts/**", "rust-engine/**", "node_modules/**", "dist/**", "dist-test/**", "web/**", ], thresholds: { statements: 40, lines: 40, branches: 20, functions: 20, }, }, // ── TypeScript / module resolution ───────────────────────────────────────── // Vitest uses esbuild for TS transform (fast, bundled). We still set up // NodeNext module resolution and path aliases to match the project's tsconfig. resolve: { alias: { "@singularity-forge/pi-coding-agent": resolve( __dirname, "packages/pi-coding-agent/src/index.ts", ), "@singularity-forge/pi-ai": resolve( __dirname, "packages/pi-ai/src/index.ts", ), "@singularity-forge/pi-ai/oauth": resolve( __dirname, "packages/pi-ai/src/utils/oauth/index.ts", ), "@singularity-forge/pi-agent-core": resolve( __dirname, "packages/pi-agent-core/src/index.ts", ), "@singularity-forge/pi-tui": resolve( __dirname, "packages/pi-tui/src/index.ts", ), "@singularity-forge/native": resolve( __dirname, "packages/native/src/index.ts", ), "@singularity-forge/mcp-server": resolve( __dirname, "packages/mcp-server/src/index.ts", ), "@singularity-forge/rpc-client": resolve( __dirname, "packages/rpc-client/src/index.ts", ), }, }, }, });