diff --git a/packages/auth/package.json b/packages/auth/package.json index 54aa63e..4dd5815 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -25,6 +25,7 @@ }, "devDependencies": { "@repo/core-eslint": "workspace:*", + "@repo/core-testing": "workspace:*", "@repo/core-typescript": "workspace:*", "@types/node": "^22.0.0", "vitest": "^3.1.0" diff --git a/packages/auth/vitest.config.ts b/packages/auth/vitest.config.ts index 1125f01..2ee07c1 100644 --- a/packages/auth/vitest.config.ts +++ b/packages/auth/vitest.config.ts @@ -1,11 +1,9 @@ import path from "node:path"; -import { baseVitestConfig } from "@repo/core-typescript/vitest.base"; +import { mergeConfig } from "vitest/config"; +import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node"; -export default { - ...baseVitestConfig, +export default mergeConfig(nodeVitestConfig, { resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, + alias: { "@": path.resolve(__dirname, "./src") }, }, -}; +}); diff --git a/packages/blog/package.json b/packages/blog/package.json index 1354987..d9d00c6 100644 --- a/packages/blog/package.json +++ b/packages/blog/package.json @@ -25,6 +25,7 @@ }, "devDependencies": { "@repo/core-eslint": "workspace:*", + "@repo/core-testing": "workspace:*", "@repo/core-typescript": "workspace:*", "@types/node": "^22.0.0", "vitest": "^3.1.0" diff --git a/packages/blog/vitest.config.ts b/packages/blog/vitest.config.ts index 1eb6d87..2ee07c1 100644 --- a/packages/blog/vitest.config.ts +++ b/packages/blog/vitest.config.ts @@ -1,11 +1,9 @@ -import path from "path"; -import { baseVitestConfig } from "@repo/core-typescript/vitest.base"; +import path from "node:path"; +import { mergeConfig } from "vitest/config"; +import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node"; -export default { - ...baseVitestConfig, +export default mergeConfig(nodeVitestConfig, { resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, + alias: { "@": path.resolve(__dirname, "./src") }, }, -}; +}); diff --git a/packages/core-shared/package.json b/packages/core-shared/package.json index 7bf3fd9..bb63b07 100644 --- a/packages/core-shared/package.json +++ b/packages/core-shared/package.json @@ -23,6 +23,7 @@ }, "devDependencies": { "@repo/core-eslint": "workspace:*", + "@repo/core-testing": "workspace:*", "@repo/core-typescript": "workspace:*", "@types/node": "^22.0.0", "vitest": "^3.1.0" diff --git a/packages/core-shared/vitest.config.ts b/packages/core-shared/vitest.config.ts index c681164..2ee07c1 100644 --- a/packages/core-shared/vitest.config.ts +++ b/packages/core-shared/vitest.config.ts @@ -1,3 +1,9 @@ -import { baseVitestConfig } from "@repo/core-typescript/vitest.base"; +import path from "node:path"; +import { mergeConfig } from "vitest/config"; +import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node"; -export default baseVitestConfig; +export default mergeConfig(nodeVitestConfig, { + resolve: { + alias: { "@": path.resolve(__dirname, "./src") }, + }, +}); diff --git a/packages/core-typescript/package.json b/packages/core-typescript/package.json index 5d9eeff..41c80a2 100644 --- a/packages/core-typescript/package.json +++ b/packages/core-typescript/package.json @@ -7,7 +7,12 @@ "./base.json": "./base.json", "./nextjs.json": "./nextjs.json", "./react-library.json": "./react-library.json", - "./vitest.base": "./vitest.base.ts" + "./vitest.base": "./vitest.base.ts", + "./vitest.base.node": "./vitest.base.node.ts", + "./vitest.base.jsdom": "./vitest.base.jsdom.ts" + }, + "scripts": { + "test": "vitest run" }, "devDependencies": { "vitest": "^3.1.0" diff --git a/packages/core-typescript/vitest.base.jsdom.test.ts b/packages/core-typescript/vitest.base.jsdom.test.ts new file mode 100644 index 0000000..539f5a0 --- /dev/null +++ b/packages/core-typescript/vitest.base.jsdom.test.ts @@ -0,0 +1,21 @@ +import { describe, it, expect } from "vitest"; +import { jsdomVitestConfig } from "./vitest.base.jsdom"; + +describe("jsdomVitestConfig", () => { + it("uses jsdom environment", () => { + expect(jsdomVitestConfig.test?.environment).toBe("jsdom"); + }); + it("loads the jsdom setup file", () => { + expect(jsdomVitestConfig.test?.setupFiles).toEqual( + expect.arrayContaining(["@repo/core-testing/setup/jsdom"]), + ); + }); + it("includes tsx files", () => { + expect(jsdomVitestConfig.test?.include).toEqual( + expect.arrayContaining(["src/**/*.test.{ts,tsx}", "tests/**/*.test.{ts,tsx}"]), + ); + }); + it("inherits clearMocks from node base", () => { + expect(jsdomVitestConfig.test?.clearMocks).toBe(true); + }); +}); diff --git a/packages/core-typescript/vitest.base.jsdom.ts b/packages/core-typescript/vitest.base.jsdom.ts new file mode 100644 index 0000000..44f5162 --- /dev/null +++ b/packages/core-typescript/vitest.base.jsdom.ts @@ -0,0 +1,13 @@ +import { defineConfig, mergeConfig } from "vitest/config"; +import { nodeVitestConfig } from "./vitest.base.node.js"; + +export const jsdomVitestConfig = mergeConfig( + nodeVitestConfig, + defineConfig({ + test: { + environment: "jsdom", + setupFiles: ["@repo/core-testing/setup/jsdom"], + include: ["src/**/*.test.{ts,tsx}", "tests/**/*.test.{ts,tsx}"], + }, + }), +); diff --git a/packages/core-typescript/vitest.base.node.test.ts b/packages/core-typescript/vitest.base.node.test.ts new file mode 100644 index 0000000..c3b8e4e --- /dev/null +++ b/packages/core-typescript/vitest.base.node.test.ts @@ -0,0 +1,28 @@ +import { describe, it, expect } from "vitest"; +import { nodeVitestConfig } from "./vitest.base.node"; + +describe("nodeVitestConfig", () => { + it("uses node environment", () => { + expect(nodeVitestConfig.test?.environment).toBe("node"); + }); + it("enables clearMocks, restoreMocks, mockReset", () => { + expect(nodeVitestConfig.test?.clearMocks).toBe(true); + expect(nodeVitestConfig.test?.restoreMocks).toBe(true); + expect(nodeVitestConfig.test?.mockReset).toBe(true); + }); + it("declares coverage thresholds", () => { + expect(nodeVitestConfig.test?.coverage?.thresholds).toMatchObject({ + statements: 80, branches: 75, functions: 80, lines: 80, + }); + }); + it("includes src and tests glob", () => { + expect(nodeVitestConfig.test?.include).toEqual( + expect.arrayContaining(["src/**/*.test.ts", "tests/**/*.test.ts"]), + ); + }); + it("excludes factories and contracts from coverage", () => { + expect(nodeVitestConfig.test?.coverage?.exclude).toEqual( + expect.arrayContaining(["src/__factories__/**", "src/__contracts__/**"]), + ); + }); +}); diff --git a/packages/core-typescript/vitest.base.node.ts b/packages/core-typescript/vitest.base.node.ts new file mode 100644 index 0000000..45d427d --- /dev/null +++ b/packages/core-typescript/vitest.base.node.ts @@ -0,0 +1,29 @@ +import { defineConfig } from "vitest/config"; + +export const nodeVitestConfig = defineConfig({ + test: { + globals: true, + environment: "node", + include: ["src/**/*.test.ts", "tests/**/*.test.ts"], + setupFiles: ["@repo/core-testing/setup/node"], + clearMocks: true, + restoreMocks: true, + mockReset: true, + unstubGlobals: true, + sequence: { shuffle: true }, + coverage: { + provider: "v8", + reporter: ["text", "html", "lcov"], + include: ["src/**"], + exclude: [ + "src/**/*.test.{ts,tsx}", + "src/**/index.ts", + "src/__factories__/**", + "src/__contracts__/**", + ], + thresholds: { + statements: 80, branches: 75, functions: 80, lines: 80, + }, + }, + }, +}); diff --git a/packages/core-typescript/vitest.base.ts b/packages/core-typescript/vitest.base.ts index 4f69a34..e1f760d 100644 --- a/packages/core-typescript/vitest.base.ts +++ b/packages/core-typescript/vitest.base.ts @@ -1,15 +1,3 @@ -import { defineConfig } from "vitest/config"; - -export const baseVitestConfig = defineConfig({ - test: { - globals: true, - environment: "node", - include: ["src/**/*.test.ts", "src/**/*.test.tsx", "tests/**/*.test.ts"], - coverage: { - provider: "v8", - reporter: ["text", "html"], - include: ["src/**"], - exclude: ["src/**/*.test.{ts,tsx}", "src/**/index.ts"], - }, - }, -}); +// Backwards-compat re-export. New code should import from +// vitest.base.node or vitest.base.jsdom directly. +export { nodeVitestConfig as baseVitestConfig } from "./vitest.base.node.js"; diff --git a/packages/core-typescript/vitest.config.ts b/packages/core-typescript/vitest.config.ts new file mode 100644 index 0000000..abbbbdc --- /dev/null +++ b/packages/core-typescript/vitest.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "vitest/config"; + +// Core-typescript tests the vitest base configs themselves. +// They live at package root (not under src/), so we use a standalone config. +export default defineConfig({ + test: { + globals: true, + environment: "node", + include: ["*.test.ts"], + clearMocks: true, + restoreMocks: true, + }, +}); diff --git a/packages/marketing-pages/package.json b/packages/marketing-pages/package.json index 8928d0e..b4f9c4b 100644 --- a/packages/marketing-pages/package.json +++ b/packages/marketing-pages/package.json @@ -25,6 +25,7 @@ }, "devDependencies": { "@repo/core-eslint": "workspace:*", + "@repo/core-testing": "workspace:*", "@repo/core-typescript": "workspace:*", "@types/node": "^22.0.0", "vitest": "^3.1.0" diff --git a/packages/marketing-pages/vitest.config.ts b/packages/marketing-pages/vitest.config.ts index 1125f01..2ee07c1 100644 --- a/packages/marketing-pages/vitest.config.ts +++ b/packages/marketing-pages/vitest.config.ts @@ -1,11 +1,9 @@ import path from "node:path"; -import { baseVitestConfig } from "@repo/core-typescript/vitest.base"; +import { mergeConfig } from "vitest/config"; +import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node"; -export default { - ...baseVitestConfig, +export default mergeConfig(nodeVitestConfig, { resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, + alias: { "@": path.resolve(__dirname, "./src") }, }, -}; +}); diff --git a/packages/navigation/package.json b/packages/navigation/package.json index eaacab8..3de1d73 100644 --- a/packages/navigation/package.json +++ b/packages/navigation/package.json @@ -25,6 +25,7 @@ }, "devDependencies": { "@repo/core-eslint": "workspace:*", + "@repo/core-testing": "workspace:*", "@repo/core-typescript": "workspace:*", "@types/node": "^22.0.0", "vitest": "^3.1.0" diff --git a/packages/navigation/vitest.config.ts b/packages/navigation/vitest.config.ts index 1125f01..2ee07c1 100644 --- a/packages/navigation/vitest.config.ts +++ b/packages/navigation/vitest.config.ts @@ -1,11 +1,9 @@ import path from "node:path"; -import { baseVitestConfig } from "@repo/core-typescript/vitest.base"; +import { mergeConfig } from "vitest/config"; +import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node"; -export default { - ...baseVitestConfig, +export default mergeConfig(nodeVitestConfig, { resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, + alias: { "@": path.resolve(__dirname, "./src") }, }, -}; +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c43904f..24f3e5d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -256,6 +256,9 @@ importers: '@repo/core-eslint': specifier: workspace:* version: link:../core-eslint + '@repo/core-testing': + specifier: workspace:* + version: link:../core-testing '@repo/core-typescript': specifier: workspace:* version: link:../core-typescript @@ -290,6 +293,9 @@ importers: '@repo/core-eslint': specifier: workspace:* version: link:../core-eslint + '@repo/core-testing': + specifier: workspace:* + version: link:../core-testing '@repo/core-typescript': specifier: workspace:* version: link:../core-typescript @@ -413,6 +419,9 @@ importers: '@repo/core-eslint': specifier: workspace:* version: link:../core-eslint + '@repo/core-testing': + specifier: workspace:* + version: link:../core-testing '@repo/core-typescript': specifier: workspace:* version: link:../core-typescript @@ -570,6 +579,9 @@ importers: '@repo/core-eslint': specifier: workspace:* version: link:../core-eslint + '@repo/core-testing': + specifier: workspace:* + version: link:../core-testing '@repo/core-typescript': specifier: workspace:* version: link:../core-typescript @@ -620,6 +632,9 @@ importers: '@repo/core-eslint': specifier: workspace:* version: link:../core-eslint + '@repo/core-testing': + specifier: workspace:* + version: link:../core-testing '@repo/core-typescript': specifier: workspace:* version: link:../core-typescript