import { coverageConfigDefaults, defineConfig } from "vitest/config"; import path from "path"; const coreOnlyExclude = [ "apps/web/app/routes/__forms/**", "apps/web/app/routes/admin/__workflows/**", "apps/web/app/routes/app.$tenant/__portals/**", "apps/web/app/routes/app.$tenant/__workflows/**", "apps/web/app/routes/internal/api/__workflows/**", "apps/web/app/modules/formBuilder/**", "apps/web/app/modules/portals/**", "apps/web/app/modules/sites/**", "apps/web/app/modules/surveys/**", "apps/web/app/modules/workflowEngine/**", ]; const coreTestExcludes = process.env.TOOLCTRL_CORE_TESTS_ONLY === "1" ? coreOnlyExclude : []; const coverageGateEnabled = process.env.TOOLCTRL_COVERAGE_GATE === "1"; const coverageArtifactExcludes = [ "**/node_modules/**", "**/dist/**", "**/build/**", "**/.react-router/**", "**/storybook-static/**", "**/coverage/**", "**/coverage-gate/**", "**/generated/**", "**/*.generated.*", ]; export default defineConfig({ test: { globals: true, environment: "jsdom", exclude: ["**/node_modules/**", "**/dist/**", "**/.react-router/**", "**/.claude/**", "tests/e2e/**", ...coreTestExcludes], setupFiles: [path.resolve(__dirname, "vitest.setup.ts")], coverage: { // Vitest 3 uses `@vitest/coverage-v8` (V8 native coverage). The legacy // c8 provider was retired in vitest 1.0 and the `coverage-c8` package // is unmaintained. // // Reporter list per docs/architecture/test-coverage.md: // - text-summary: human-readable terminal output // - json-summary: feeds scripts/verify-test-coverage.mjs + readme badge // - html: drillable artifact, uploaded by .github/workflows/coverage.yml // - lcov: consumed by external tools (Codecov, IDE plugins) // The CI threshold gate sets TOOLCTRL_COVERAGE_GATE=1 to avoid writing // heavyweight HTML/LCOV artifacts during the quick threshold check. provider: "v8", reporter: coverageGateEnabled ? ["text-summary", "json-summary"] : ["text-summary", "json-summary", "html", "lcov"], reportsDirectory: coverageGateEnabled ? "coverage-gate" : "coverage", exclude: [...coverageConfigDefaults.exclude, ...coverageArtifactExcludes], }, }, resolve: { alias: { "~": path.resolve(__dirname, "./apps/web/app"), "vite-env-only/macros": path.resolve(__dirname, "./tests/vite-env-only-macros.ts"), "@toolctrl/error-reporter": path.resolve(__dirname, "./packages/error-reporter/src/index.ts"), "@toolctrl/exports/audit-pdf": path.resolve(__dirname, "./packages/exports/src/audit-pdf.ts"), "@toolctrl/exports/csv": path.resolve(__dirname, "./packages/exports/src/csv/index.ts"), "@toolctrl/exports/json": path.resolve(__dirname, "./packages/exports/src/json/index.ts"), "@toolctrl/exports/limits": path.resolve(__dirname, "./packages/exports/src/limits.ts"), "@toolctrl/exports/pdf": path.resolve(__dirname, "./packages/exports/src/pdf/index.ts"), "@toolctrl/exports/s3-multipart": path.resolve(__dirname, "./packages/exports/src/sinks/s3-multipart.ts"), "@toolctrl/exports/types": path.resolve(__dirname, "./packages/exports/src/types.ts"), "@toolctrl/exports/xlsx": path.resolve(__dirname, "./packages/exports/src/xlsx/index.ts"), "@toolctrl/exports": path.resolve(__dirname, "./packages/exports/src/index.ts"), "@toolctrl/plugins": path.resolve(__dirname, "./packages/plugins/src/index.ts"), "@toolctrl/realtime": path.resolve(__dirname, "./packages/realtime/src/index.ts"), "@toolctrl/storage": path.resolve(__dirname, "./packages/storage/src/index.ts"), "@toolctrl/url": path.resolve(__dirname, "./packages/url/src/index.ts"), // Subpath exports for `@toolctrl/ui-app` — the workspace package ships // unbuilt TS, so we explicitly map the test-helper subpaths used by // *.axe.test.tsx suites (see docs/contributing/wcag-audit.md). "@toolctrl/ui-app/test-setup/axe": path.resolve(__dirname, "./packages/ui-app/test-setup/axe.ts"), "@toolctrl/ui-app/test-utils/a11y-template": path.resolve(__dirname, "./packages/ui-app/src/test-utils/a11y-template.ts"), }, }, });