From 72b6379b9147d5de3e72e2541f05da57149fdb33 Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 15 Aug 2025 18:35:23 +0300 Subject: [PATCH 1/8] test: introduce test-vitest-setup --- e2e/ci-e2e/vitest.e2e.config.ts | 32 ++- e2e/cli-e2e/vitest.e2e.config.ts | 28 +-- e2e/create-cli-e2e/vitest.e2e.config.ts | 30 +-- e2e/nx-plugin-e2e/vitest.e2e.config.ts | 29 +-- e2e/plugin-coverage-e2e/vitest.e2e.config.ts | 29 +-- e2e/plugin-eslint-e2e/vitest.e2e.config.ts | 29 +-- .../vitest.e2e.config.ts | 29 +-- e2e/plugin-jsdocs-e2e/vitest.e2e.config.ts | 29 +-- .../vitest.e2e.config.ts | 29 +-- .../vitest.e2e.config.ts | 34 +-- eslint.config.js | 3 + examples/plugins/vitest.int.config.ts | 39 +--- examples/plugins/vitest.unit.config.ts | 39 +--- packages/ci/vitest.int.config.ts | 37 +--- packages/ci/vitest.unit.config.ts | 40 +--- packages/cli/vitest.int.config.ts | 44 ++-- packages/cli/vitest.unit.config.ts | 60 +++-- packages/core/vitest.int.config.ts | 52 +++-- packages/core/vitest.unit.config.ts | 53 ++--- packages/create-cli/vitest.unit.config.ts | 38 +--- packages/models/eslint.config.js | 2 +- .../models/transformers/eslint.config.cjs | 10 + .../transformers/src/lib/transformers.ts | 5 +- packages/models/vitest.unit.config.ts | 49 ++--- packages/nx-plugin/vitest.int.config.ts | 36 +-- packages/nx-plugin/vitest.unit.config.ts | 37 +--- packages/plugin-coverage/vitest.int.config.ts | 47 ++-- .../plugin-coverage/vitest.unit.config.ts | 46 ++-- packages/plugin-eslint/vitest.int.config.ts | 43 ++-- packages/plugin-eslint/vitest.unit.config.ts | 49 ++--- .../plugin-js-packages/vitest.int.config.ts | 43 ++-- .../plugin-js-packages/vitest.unit.config.ts | 45 ++-- packages/plugin-jsdocs/vitest.int.config.ts | 44 ++-- packages/plugin-jsdocs/vitest.unit.config.ts | 49 ++--- .../plugin-lighthouse/vitest.unit.config.ts | 51 ++--- .../plugin-typescript/vitest.int.config.ts | 45 ++-- .../plugin-typescript/vitest.unit.config.ts | 49 ++--- packages/utils/vitest.int.config.ts | 38 +--- packages/utils/vitest.unit.config.ts | 66 +++--- testing/test-nx-utils/vitest.unit.config.ts | 33 ++- .../test-setup/src/lib/fs-memfs.setup-file.ts | 12 + testing/test-setup/src/lib/fs-only.mock.ts | 12 + .../src/lib/fs-with-cwd.setup-file.ts | 24 ++ testing/test-setup/vitest.unit.config.ts | 42 ++-- testing/test-utils/vitest.unit.config.ts | 33 ++- testing/test-vitest-setup/README.md | 205 ++++++++++++++++++ testing/test-vitest-setup/eslint.config.js | 8 + testing/test-vitest-setup/package.json | 4 + testing/test-vitest-setup/project.json | 11 + testing/test-vitest-setup/src/configs/base.ts | 19 ++ testing/test-vitest-setup/src/configs/e2e.ts | 20 ++ testing/test-vitest-setup/src/configs/int.ts | 23 ++ .../src/configs/unit-no-fs-cwd.ts | 32 +++ testing/test-vitest-setup/src/configs/unit.ts | 28 +++ testing/test-vitest-setup/src/index.ts | 7 + .../src/utils/project-config.ts | 169 +++++++++++++++ .../src/utils/tsconfig-path-aliases.ts | 3 +- testing/test-vitest-setup/tsconfig.json | 23 ++ testing/test-vitest-setup/tsconfig.lib.json | 8 + tsconfig.base.json | 3 + 60 files changed, 1224 insertions(+), 952 deletions(-) create mode 100644 testing/test-setup/src/lib/fs-memfs.setup-file.ts create mode 100644 testing/test-setup/src/lib/fs-only.mock.ts create mode 100644 testing/test-setup/src/lib/fs-with-cwd.setup-file.ts create mode 100644 testing/test-vitest-setup/README.md create mode 100644 testing/test-vitest-setup/eslint.config.js create mode 100644 testing/test-vitest-setup/package.json create mode 100644 testing/test-vitest-setup/project.json create mode 100644 testing/test-vitest-setup/src/configs/base.ts create mode 100644 testing/test-vitest-setup/src/configs/e2e.ts create mode 100644 testing/test-vitest-setup/src/configs/int.ts create mode 100644 testing/test-vitest-setup/src/configs/unit-no-fs-cwd.ts create mode 100644 testing/test-vitest-setup/src/configs/unit.ts create mode 100644 testing/test-vitest-setup/src/index.ts create mode 100644 testing/test-vitest-setup/src/utils/project-config.ts rename tools/vitest-tsconfig-path-aliases.ts => testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts (88%) create mode 100644 testing/test-vitest-setup/tsconfig.json create mode 100644 testing/test-vitest-setup/tsconfig.lib.json diff --git a/e2e/ci-e2e/vitest.e2e.config.ts b/e2e/ci-e2e/vitest.e2e.config.ts index 188911141..5b900dc4f 100644 --- a/e2e/ci-e2e/vitest.e2e.config.ts +++ b/e2e/ci-e2e/vitest.e2e.config.ts @@ -1,22 +1,18 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/ci-e2e', - test: { - reporters: ['basic'], - testTimeout: 60_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + globalSetup: './global-setup.ts', }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: './global-setup.ts', - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, + }; }); diff --git a/e2e/cli-e2e/vitest.e2e.config.ts b/e2e/cli-e2e/vitest.e2e.config.ts index c2f8187bd..326e8f2be 100644 --- a/e2e/cli-e2e/vitest.e2e.config.ts +++ b/e2e/cli-e2e/vitest.e2e.config.ts @@ -1,21 +1,15 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/cli-e2e', - test: { - reporters: ['basic'], +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', testTimeout: 20_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/create-cli-e2e/vitest.e2e.config.ts b/e2e/create-cli-e2e/vitest.e2e.config.ts index 08534a740..c0aab4060 100644 --- a/e2e/create-cli-e2e/vitest.e2e.config.ts +++ b/e2e/create-cli-e2e/vitest.e2e.config.ts @@ -1,22 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/create-cli-e2e', - test: { - reporters: ['basic'], - testTimeout: 20_000, - hookTimeout: 20_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/nx-plugin-e2e/vitest.e2e.config.ts b/e2e/nx-plugin-e2e/vitest.e2e.config.ts index c0f955673..c0aab4060 100644 --- a/e2e/nx-plugin-e2e/vitest.e2e.config.ts +++ b/e2e/nx-plugin-e2e/vitest.e2e.config.ts @@ -1,21 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/nx-plugin-e2e', - test: { - reporters: ['basic'], - testTimeout: 80_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/plugin-coverage-e2e/vitest.e2e.config.ts b/e2e/plugin-coverage-e2e/vitest.e2e.config.ts index 15ef3ba1a..c0aab4060 100644 --- a/e2e/plugin-coverage-e2e/vitest.e2e.config.ts +++ b/e2e/plugin-coverage-e2e/vitest.e2e.config.ts @@ -1,21 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-coverage-e2e', - test: { - reporters: ['basic'], - testTimeout: 40_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/plugin-eslint-e2e/vitest.e2e.config.ts b/e2e/plugin-eslint-e2e/vitest.e2e.config.ts index 500fe0cd5..c0aab4060 100644 --- a/e2e/plugin-eslint-e2e/vitest.e2e.config.ts +++ b/e2e/plugin-eslint-e2e/vitest.e2e.config.ts @@ -1,21 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-lighthouse-e2e', - test: { - reporters: ['basic'], - testTimeout: 20_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/plugin-js-packages-e2e/vitest.e2e.config.ts b/e2e/plugin-js-packages-e2e/vitest.e2e.config.ts index 8b8475ed1..c0aab4060 100644 --- a/e2e/plugin-js-packages-e2e/vitest.e2e.config.ts +++ b/e2e/plugin-js-packages-e2e/vitest.e2e.config.ts @@ -1,21 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-js-packages-e2e', - test: { - reporters: ['basic'], - testTimeout: 120_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/plugin-jsdocs-e2e/vitest.e2e.config.ts b/e2e/plugin-jsdocs-e2e/vitest.e2e.config.ts index ecbc894ae..c0aab4060 100644 --- a/e2e/plugin-jsdocs-e2e/vitest.e2e.config.ts +++ b/e2e/plugin-jsdocs-e2e/vitest.e2e.config.ts @@ -1,21 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-jsdocs-e2e', - test: { - reporters: ['basic'], - testTimeout: 20_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/plugin-lighthouse-e2e/vitest.e2e.config.ts b/e2e/plugin-lighthouse-e2e/vitest.e2e.config.ts index 1040920ff..c0aab4060 100644 --- a/e2e/plugin-lighthouse-e2e/vitest.e2e.config.ts +++ b/e2e/plugin-lighthouse-e2e/vitest.e2e.config.ts @@ -1,21 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-lighthouse-e2e', - test: { - reporters: ['basic'], - testTimeout: 80_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/e2e/plugin-typescript-e2e/vitest.e2e.config.ts b/e2e/plugin-typescript-e2e/vitest.e2e.config.ts index 8f30d049b..c0aab4060 100644 --- a/e2e/plugin-typescript-e2e/vitest.e2e.config.ts +++ b/e2e/plugin-typescript-e2e/vitest.e2e.config.ts @@ -1,26 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-typescript-e2e', - test: { - reporters: ['basic'], - testTimeout: 20_000, - globals: true, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-typescript-e2e/e2e-tests', - exclude: ['mocks/**', '**/types.ts'], - }, - cache: { - dir: '../../node_modules/.vitest', - }, - environment: 'node', - include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], - }, +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/eslint.config.js b/eslint.config.js index 5830ca0f7..d62152d3f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -27,6 +27,8 @@ export default tseslint.config( String.raw`^.*/eslint(\.base)?\.config\.[cm]?js$`, String.raw`^.*/code-pushup\.(config|preset)(\.m?[jt]s)?$`, '^[./]+/tools/.*$', + '^[./]+/testing/test-vitest-setup/.*$', + '^[./]+/test-vitest-setup/.*$', ], depConstraints: [ { @@ -131,6 +133,7 @@ export default tseslint.config( '**/__snapshots__/**', '**/dist', '**/*.md', + '**/coverage/**', ], }, ); diff --git a/examples/plugins/vitest.int.config.ts b/examples/plugins/vitest.int.config.ts index 116936d7b..b9f8b6946 100644 --- a/examples/plugins/vitest.int.config.ts +++ b/examples/plugins/vitest.int.config.ts @@ -1,31 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/examples-plugins', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/examples-plugins/int-tests', - exclude: ['**/mocks/**', '**/mock/**', 'code-pushup.config.ts'], - }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/git.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/examples/plugins/vitest.unit.config.ts b/examples/plugins/vitest.unit.config.ts index a39e779dc..2457541c5 100644 --- a/examples/plugins/vitest.unit.config.ts +++ b/examples/plugins/vitest.unit.config.ts @@ -1,31 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/examples-plugins', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/examples-plugins/unit-tests', - exclude: ['**/mocks/**', '**/mock/**', 'code-pushup.config.ts'], - }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/git.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/ci/vitest.int.config.ts b/packages/ci/vitest.int.config.ts index dd5ebd0f9..b9f8b6946 100644 --- a/packages/ci/vitest.int.config.ts +++ b/packages/ci/vitest.int.config.ts @@ -1,29 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/ci', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/ci/int-tests', - exclude: ['mocks/**', '**/types.ts'], - }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/ci/vitest.unit.config.ts b/packages/ci/vitest.unit.config.ts index a7b37b3fd..2457541c5 100644 --- a/packages/ci/vitest.unit.config.ts +++ b/packages/ci/vitest.unit.config.ts @@ -1,32 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/ci', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/ci/unit-tests', - exclude: ['mocks/**', '**/types.ts'], - }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/git.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/cli/vitest.int.config.ts b/packages/cli/vitest.int.config.ts index 822df760a..28ff3e565 100644 --- a/packages/cli/vitest.int.config.ts +++ b/packages/cli/vitest.int.config.ts @@ -1,29 +1,27 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/cli', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/cli/int-tests', - exclude: ['mocks/**', '**/types.ts'], - }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', setupFiles: [ '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], - }, + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + coverage: { + ...baseConfig.test.coverage, + exclude: [ + ...baseConfig.test.coverage.exclude, + // CLI-specific excludes (already has mocks/** and **/types.ts) + ], + }, + }, + }; }); diff --git a/packages/cli/vitest.unit.config.ts b/packages/cli/vitest.unit.config.ts index cb4a01fb0..ecfb07c6f 100644 --- a/packages/cli/vitest.unit.config.ts +++ b/packages/cli/vitest.unit.config.ts @@ -1,34 +1,32 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/cli', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/cli/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/git.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/portal-client.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + ], + coverage: { + ...baseConfig.test.coverage, + exclude: [ + ...baseConfig.test.coverage.exclude, + // All defaults already included + ], + }, }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/git.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/portal-client.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - ], - }, + }; }); diff --git a/packages/core/vitest.int.config.ts b/packages/core/vitest.int.config.ts index 819c3a5bb..d68b24986 100644 --- a/packages/core/vitest.int.config.ts +++ b/packages/core/vitest.int.config.ts @@ -1,30 +1,28 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/core', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/core/int-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/portal-client.mock.ts', + ], + coverage: { + ...baseConfig.test.coverage, + exclude: [ + ...baseConfig.test.coverage.exclude, + // All defaults already included + ], + }, }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/portal-client.mock.ts', - ], - }, + }; }); diff --git a/packages/core/vitest.unit.config.ts b/packages/core/vitest.unit.config.ts index 820eb538c..1e76e8ecc 100644 --- a/packages/core/vitest.unit.config.ts +++ b/packages/core/vitest.unit.config.ts @@ -1,36 +1,23 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/core', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/core/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + coverage: { + ...baseConfig.test.coverage, + exclude: [ + ...baseConfig.test.coverage.exclude, + // Core-specific excludes (already has mocks/** and **/types.ts) + ], + }, }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/git.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/portal-client.mock.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', - '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', - ], - }, + }; }); diff --git a/packages/create-cli/vitest.unit.config.ts b/packages/create-cli/vitest.unit.config.ts index b990c0c6f..2457541c5 100644 --- a/packages/create-cli/vitest.unit.config.ts +++ b/packages/create-cli/vitest.unit.config.ts @@ -1,30 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/create-cli', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/create-cli/unit-tests', - exclude: ['mocks/**', '**/types.ts'], - }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/models/eslint.config.js b/packages/models/eslint.config.js index 26af011ea..39b69793d 100644 --- a/packages/models/eslint.config.js +++ b/packages/models/eslint.config.js @@ -19,6 +19,6 @@ export default tseslint.config( }, }, { - ignores: ['packages/models/transformers/**/*.ts'], + ignores: ['packages/models/transformers/**/*'], }, ); diff --git a/packages/models/transformers/eslint.config.cjs b/packages/models/transformers/eslint.config.cjs index 4eaecdb17..d0c35d2dd 100644 --- a/packages/models/transformers/eslint.config.cjs +++ b/packages/models/transformers/eslint.config.cjs @@ -8,4 +8,14 @@ module.exports = [ '@nx/dependency-checks': 'error', }, }, + { + files: ['**/*.ts', '**/*.js'], + rules: { + // Allow CommonJS in this transformer package + 'import/no-commonjs': 'off', + '@typescript-eslint/no-require-imports': 'off', + 'unicorn/prefer-module': 'off', + 'functional/immutable-data': 'off', + }, + }, ]; diff --git a/packages/models/transformers/src/lib/transformers.ts b/packages/models/transformers/src/lib/transformers.ts index b61f19455..8b0b4634a 100644 --- a/packages/models/transformers/src/lib/transformers.ts +++ b/packages/models/transformers/src/lib/transformers.ts @@ -41,9 +41,8 @@ function annotateTypeDefinitions( } return tsLib.visitEachChild(node, visitor, context); }; - return (sourceFile: ts.SourceFile) => { - return tsLib.visitNode(sourceFile, visitor, tsLib.isSourceFile); - }; + return (sourceFile: ts.SourceFile) => + tsLib.visitNode(sourceFile, visitor, tsLib.isSourceFile); }; } diff --git a/packages/models/vitest.unit.config.ts b/packages/models/vitest.unit.config.ts index 386a073db..52a7af70c 100644 --- a/packages/models/vitest.unit.config.ts +++ b/packages/models/vitest.unit.config.ts @@ -1,30 +1,25 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/models', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/models/unit-tests', - exclude: ['mocks/**', '**/types.ts', 'zod2md.config.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], + coverage: { + ...baseConfig.test.coverage, + exclude: [...baseConfig.test.coverage.exclude, 'zod2md.config.ts'], + }, }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, + }; }); diff --git a/packages/nx-plugin/vitest.int.config.ts b/packages/nx-plugin/vitest.int.config.ts index 25d5530d1..b9f8b6946 100644 --- a/packages/nx-plugin/vitest.int.config.ts +++ b/packages/nx-plugin/vitest.int.config.ts @@ -1,28 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/nx-plugin', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/nx-plugin/int-tests', - exclude: ['mocks/**', '**/types.ts', '**/__snapshots__/**'], - }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/nx-plugin/vitest.unit.config.ts b/packages/nx-plugin/vitest.unit.config.ts index db557f696..2457541c5 100644 --- a/packages/nx-plugin/vitest.unit.config.ts +++ b/packages/nx-plugin/vitest.unit.config.ts @@ -1,29 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/nx-plugin', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/nx-plugin/unit-tests', - exclude: ['mocks/**', '**/types.ts', '**/__snapshots__/**'], - }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/plugin-coverage/vitest.int.config.ts b/packages/plugin-coverage/vitest.int.config.ts index a105197ee..b36b3cf62 100644 --- a/packages/plugin-coverage/vitest.int.config.ts +++ b/packages/plugin-coverage/vitest.int.config.ts @@ -1,29 +1,24 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-coverage', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-coverage/int-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], + coverage: { + ...baseConfig.test.coverage, + exclude: [...baseConfig.test.coverage.exclude, '**/vitest.*.config.ts'], + }, }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, + }; }); diff --git a/packages/plugin-coverage/vitest.unit.config.ts b/packages/plugin-coverage/vitest.unit.config.ts index e86d3f2e5..3beb7dc75 100644 --- a/packages/plugin-coverage/vitest.unit.config.ts +++ b/packages/plugin-coverage/vitest.unit.config.ts @@ -1,32 +1,20 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-coverage', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-coverage/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + coverage: { + ...baseConfig.test.coverage, + exclude: [...baseConfig.test.coverage.exclude, '**/vitest.*.config.ts'], + }, }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - ], - }, + }; }); diff --git a/packages/plugin-eslint/vitest.int.config.ts b/packages/plugin-eslint/vitest.int.config.ts index 4019fef85..a89e8ae92 100644 --- a/packages/plugin-eslint/vitest.int.config.ts +++ b/packages/plugin-eslint/vitest.int.config.ts @@ -1,29 +1,20 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-eslint', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-eslint/int-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, + }; }); diff --git a/packages/plugin-eslint/vitest.unit.config.ts b/packages/plugin-eslint/vitest.unit.config.ts index 65695242a..499243556 100644 --- a/packages/plugin-eslint/vitest.unit.config.ts +++ b/packages/plugin-eslint/vitest.unit.config.ts @@ -1,32 +1,23 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-eslint', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-eslint/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + ], }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - ], - }, + }; }); diff --git a/packages/plugin-js-packages/vitest.int.config.ts b/packages/plugin-js-packages/vitest.int.config.ts index aee4b57a1..a89e8ae92 100644 --- a/packages/plugin-js-packages/vitest.int.config.ts +++ b/packages/plugin-js-packages/vitest.int.config.ts @@ -1,29 +1,20 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-js-packages', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-js-packages/int-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, + }; }); diff --git a/packages/plugin-js-packages/vitest.unit.config.ts b/packages/plugin-js-packages/vitest.unit.config.ts index 68f80bdce..a121926a9 100644 --- a/packages/plugin-js-packages/vitest.unit.config.ts +++ b/packages/plugin-js-packages/vitest.unit.config.ts @@ -1,30 +1,21 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-js-packages', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-js-packages/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, + }; }); diff --git a/packages/plugin-jsdocs/vitest.int.config.ts b/packages/plugin-jsdocs/vitest.int.config.ts index 52301cf7d..a89e8ae92 100644 --- a/packages/plugin-jsdocs/vitest.int.config.ts +++ b/packages/plugin-jsdocs/vitest.int.config.ts @@ -1,30 +1,20 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-coverage', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-jsdocs/int-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/path.matcher.ts', - ], - }, + }; }); diff --git a/packages/plugin-jsdocs/vitest.unit.config.ts b/packages/plugin-jsdocs/vitest.unit.config.ts index 048851c63..47fdfe030 100644 --- a/packages/plugin-jsdocs/vitest.unit.config.ts +++ b/packages/plugin-jsdocs/vitest.unit.config.ts @@ -1,32 +1,23 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-coverage', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-jsdocs/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/extend/path.matcher.ts', + ], }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/path.matcher.ts', - ], - }, + }; }); diff --git a/packages/plugin-lighthouse/vitest.unit.config.ts b/packages/plugin-lighthouse/vitest.unit.config.ts index 6739ccd4c..fcc7d1bb9 100644 --- a/packages/plugin-lighthouse/vitest.unit.config.ts +++ b/packages/plugin-lighthouse/vitest.unit.config.ts @@ -1,33 +1,24 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-lighthouse', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-lighthouse/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/extend/path.matcher.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + ], }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/path.matcher.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - ], - }, + }; }); diff --git a/packages/plugin-typescript/vitest.int.config.ts b/packages/plugin-typescript/vitest.int.config.ts index 42d047592..9f4842a74 100644 --- a/packages/plugin-typescript/vitest.int.config.ts +++ b/packages/plugin-typescript/vitest.int.config.ts @@ -1,30 +1,21 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-typescript', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest/plugin-typescript', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-typescript/int-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/chrome-path.mock.ts', + ], }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/chrome-path.mock.ts', - ], - }, + }; }); diff --git a/packages/plugin-typescript/vitest.unit.config.ts b/packages/plugin-typescript/vitest.unit.config.ts index f4b1337f9..50b7924ec 100644 --- a/packages/plugin-typescript/vitest.unit.config.ts +++ b/packages/plugin-typescript/vitest.unit.config.ts @@ -1,32 +1,23 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/plugin-typescript', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest/plugin-typescript', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/plugin-typescript/unit-tests', - exclude: ['mocks/**', '**/types.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + ], }, - environment: 'node', - include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, + }; }); diff --git a/packages/utils/vitest.int.config.ts b/packages/utils/vitest.int.config.ts index 61c01ddad..b9f8b6946 100644 --- a/packages/utils/vitest.int.config.ts +++ b/packages/utils/vitest.int.config.ts @@ -1,30 +1,14 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/utils', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/utils/int-tests', - exclude: ['mocks/**', 'perf/**', '**/types.ts'], - }, - environment: 'node', - include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - ], - }, +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; }); diff --git a/packages/utils/vitest.unit.config.ts b/packages/utils/vitest.unit.config.ts index ac74f7af6..d077f7197 100644 --- a/packages/utils/vitest.unit.config.ts +++ b/packages/utils/vitest.unit.config.ts @@ -1,38 +1,34 @@ -/// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../../node_modules/.vite/utils', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/utils/unit-tests', - exclude: ['mocks/**', 'perf/**', '**/types.ts'], - }, - environment: 'node', - include: ['src/**/*.{unit,type}.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - typecheck: { - include: ['**/*.type.test.ts'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + include: ['src/**/*.{unit,type}.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: [ + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/fs.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', + '../../testing/test-setup/src/lib/extend/path.matcher.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', + ], + coverage: { + ...baseConfig.test.coverage, + exclude: [...baseConfig.test.coverage.exclude, 'perf/**'], + }, + typecheck: { + include: ['**/*.type.test.ts'], + }, }, - globalSetup: ['../../global-setup.ts'], - setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', - '../../testing/test-setup/src/lib/extend/path.matcher.ts', - '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', - ], - }, + }; }); diff --git a/testing/test-nx-utils/vitest.unit.config.ts b/testing/test-nx-utils/vitest.unit.config.ts index b5a305cc1..c18cd237a 100644 --- a/testing/test-nx-utils/vitest.unit.config.ts +++ b/testing/test-nx-utils/vitest.unit.config.ts @@ -1,24 +1,17 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../node_modules/.vite/test-nx-utils', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../node_modules/.vitest', +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig( + { + projectRoot: __dirname, + workspaceRoot: '../..', }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/test-nx-utils/unit-tests', - exclude: ['**/*.mock.{mjs,ts}', '**/*.config.{js,mjs,ts}'], - }, - environment: 'node', - include: ['src/**/*.unit.test.ts'], - }, + true, + ); // noFsCwd = true for test-nx-utils + + return { + ...baseConfig, + }; }); diff --git a/testing/test-setup/src/lib/fs-memfs.setup-file.ts b/testing/test-setup/src/lib/fs-memfs.setup-file.ts new file mode 100644 index 000000000..21e4530e6 --- /dev/null +++ b/testing/test-setup/src/lib/fs-memfs.setup-file.ts @@ -0,0 +1,12 @@ +import { vi } from 'vitest'; + +// Mock fs and fs/promises to use memfs +vi.mock('fs', async () => { + const memfs: typeof import('memfs') = await vi.importActual('memfs'); + return memfs.fs; +}); + +vi.mock('fs/promises', async () => { + const memfs: typeof import('memfs') = await vi.importActual('memfs'); + return memfs.fs.promises; +}); diff --git a/testing/test-setup/src/lib/fs-only.mock.ts b/testing/test-setup/src/lib/fs-only.mock.ts new file mode 100644 index 000000000..bd93ffc74 --- /dev/null +++ b/testing/test-setup/src/lib/fs-only.mock.ts @@ -0,0 +1,12 @@ +import { vi } from 'vitest'; + +// Mock only fs modules, not process.cwd() +// This allows tests to mock process.cwd() themselves +vi.mock('fs', async () => { + const memfs: typeof import('memfs') = await vi.importActual('memfs'); + return memfs.fs; +}); +vi.mock('fs/promises', async () => { + const memfs: typeof import('memfs') = await vi.importActual('memfs'); + return memfs.fs.promises; +}); diff --git a/testing/test-setup/src/lib/fs-with-cwd.setup-file.ts b/testing/test-setup/src/lib/fs-with-cwd.setup-file.ts new file mode 100644 index 000000000..3282e9dd5 --- /dev/null +++ b/testing/test-setup/src/lib/fs-with-cwd.setup-file.ts @@ -0,0 +1,24 @@ +import { type MockInstance, afterEach, beforeEach, vi } from 'vitest'; +import { MEMFS_VOLUME } from '@code-pushup/test-utils'; + +// Mock fs, fs/promises AND process.cwd() for full memfs environment +vi.mock('fs', async () => { + const memfs: typeof import('memfs') = await vi.importActual('memfs'); + return memfs.fs; +}); + +vi.mock('fs/promises', async () => { + const memfs: typeof import('memfs') = await vi.importActual('memfs'); + return memfs.fs.promises; +}); + +// eslint-disable-next-line functional/no-let -- Mock spy needs to be reassignable +let cwdSpy: MockInstance<[], string> | undefined; + +beforeEach(() => { + cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(MEMFS_VOLUME); +}); + +afterEach(() => { + cwdSpy?.mockRestore(); +}); diff --git a/testing/test-setup/vitest.unit.config.ts b/testing/test-setup/vitest.unit.config.ts index 9a8966612..02af5aefc 100644 --- a/testing/test-setup/vitest.unit.config.ts +++ b/testing/test-setup/vitest.unit.config.ts @@ -1,29 +1,21 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../node_modules/.vite/test-setup', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../node_modules/.vitest', - }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/test-setup/unit-tests', - exclude: ['**/*.mock.{mjs,ts}', '**/*.config.{js,mjs,ts}'], +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [ + ...baseConfig.test.setupFiles, + 'src/lib/extend/path.matcher.ts', + ], }, - environment: 'node', - include: ['src/**/*.unit.test.ts'], - setupFiles: [ - '../test-setup/src/lib/reset.mocks.ts', - '../test-setup/src/lib/extend/path.matcher.ts', - '../test-setup/src/lib/extend/markdown-table.matcher.ts', - ], - }, + }; }); diff --git a/testing/test-utils/vitest.unit.config.ts b/testing/test-utils/vitest.unit.config.ts index 8d5f0328f..0d3bcea5e 100644 --- a/testing/test-utils/vitest.unit.config.ts +++ b/testing/test-utils/vitest.unit.config.ts @@ -1,24 +1,17 @@ /// -import { defineConfig } from 'vite'; -import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../test-vitest-setup/src/utils/project-config.js'; -export default defineConfig({ - cacheDir: '../node_modules/.vite/test-utils', - test: { - reporters: ['basic'], - globals: true, - cache: { - dir: '../node_modules/.vitest', +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig( + { + projectRoot: __dirname, + workspaceRoot: '../..', }, - alias: tsconfigPathAliases(), - pool: 'threads', - poolOptions: { threads: { singleThread: true } }, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: '../../coverage/test-utils/unit-tests', - exclude: ['**/*.mock.{mjs,ts}', '**/*.config.{js,mjs,ts}'], - }, - environment: 'node', - include: ['src/**/*.unit.test.ts'], - }, + true, + ); // noFsCwd = true for test-utils + + return { + ...baseConfig, + }; }); diff --git a/testing/test-vitest-setup/README.md b/testing/test-vitest-setup/README.md new file mode 100644 index 000000000..4c209f4dd --- /dev/null +++ b/testing/test-vitest-setup/README.md @@ -0,0 +1,205 @@ +# test-vitest-setup + +This library provides shared Vitest configurations for different test types in the Code PushUp monorepo, similar to the [cpu-prof vitest-setup](https://github.com/push-based/cpu-prof/tree/main/testing/vitest-setup). + +## Features + +✅ **Centralized Configuration**: Common Vitest settings shared across all projects +✅ **Coverage at Project Root**: Coverage reports are generated at the project root level +✅ **Type-specific Configs**: Separate configurations for unit, integration, and e2e tests +✅ **Type-safe Interface**: Strongly typed configuration options with TypeScript interfaces +✅ **Clean API**: Simple, consistent interface for all test types + +## Configurations + +The library provides three main configuration functions: + +- `createSharedUnitVitestConfig()` - Configuration for unit tests +- `createSharedIntegrationVitestConfig()` - Configuration for integration tests +- `createSharedE2eVitestConfig()` - Configuration for end-to-end tests + +## Setup Files + +### File System Mocking + +- `fs-with-cwd.setup-file.ts` - Mocks fs AND process.cwd() (default for most tests) +- `fs-memfs.setup-file.ts` - Only mocks fs, preserves real process.cwd() (for utility tests) + +## Usage + +### Basic Usage + +```typescript +// vitest.unit.config.ts +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; + +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + }; +}); +``` + +### Custom Configuration + +```typescript +// vitest.unit.config.ts +import { defineConfig } from 'vitest/config'; +import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; + +export default defineConfig(() => { + const baseConfig = createSharedUnitVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + coverage: { + ...baseConfig.test.coverage, + exclude: [...baseConfig.test.coverage.exclude, 'mocks/**', '**/types.ts', '**/*.config.ts'], + }, + setupFiles: [...baseConfig.test.setupFiles, '../../testing/test-setup/src/lib/console.mock.ts'], + }, + }; +}); +``` + +### Integration Tests + +```typescript +// vitest.int.config.ts +import { defineConfig } from 'vitest/config'; +import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; + +export default defineConfig(() => { + const baseConfig = createSharedIntegrationVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + setupFiles: [...baseConfig.test.setupFiles, '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts'], + }, + }; +}); +``` + +### E2E Tests + +```typescript +// vitest.e2e.config.ts +import { defineConfig } from 'vitest/config'; +import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; + +export default defineConfig(() => { + const baseConfig = createSharedE2eVitestConfig({ + projectRoot: __dirname, + workspaceRoot: '../..', + }); + + return { + ...baseConfig, + test: { + ...baseConfig.test, + globalSetup: './global-setup.ts', + }, + }; +}); +``` + +## Coverage Configuration + +Coverage reports are automatically configured to be saved at the project root: + +- Unit tests: `./coverage/{project-name}/unit` +- Integration tests: `./coverage/{project-name}/integration` +- E2E tests: `./coverage/{project-name}/e2e` + +This ensures each project has its own organized coverage directory structure at the project root level. + +## Configuration Options + +### SharedVitestConfigOptions + +```typescript +type SharedVitestConfigOptions = { + projectRoot: string; // Path to the project root + workspaceRoot: string; // Path to the workspace root + enabled?: boolean; // Enable/disable coverage (default: true) + environment?: 'node' | 'jsdom' | 'happy-dom'; // Test environment (default: 'node') + include?: string[]; // Custom include patterns + exclude?: string[]; // Custom exclude patterns + testTimeout?: number; // Custom test timeout +}; +``` + +## Migration Guide + +To migrate from the legacy `mergeConfig` approach: + +1. **Replace imports**: + +```diff +- import { mergeConfig } from 'vite'; +- import { unitTestConfig, createUnitTestConfig } from '../../testing/test-vitest-setup/src/index.js'; ++ import { defineConfig } from 'vitest/config'; ++ import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; +``` + +2. **Update configuration structure**: + +```diff +- export default mergeConfig(unitTestConfig, createUnitTestConfig('my-project', { +- test: { +- coverage: { exclude: ['mocks/**'] }, +- }, +- })); + ++ export default defineConfig(() => { ++ const baseConfig = createSharedUnitVitestConfig({ ++ projectRoot: __dirname, ++ workspaceRoot: '../..', ++ }); + ++ return { ++ ...baseConfig, ++ test: { ++ ...baseConfig.test, ++ coverage: { ++ ...baseConfig.test.coverage, ++ exclude: [...baseConfig.test.coverage.exclude, 'mocks/**'], ++ }, ++ }, ++ }; ++ }); +``` + +3. **Benefits of the new approach**: + - **Type Safety**: Full TypeScript support with proper interfaces + - **Consistency**: All projects use the same configuration structure + - **Maintainability**: Centralized configuration logic + - **Flexibility**: Easy to extend and customize per project + - **Performance**: Better caching and optimization + +## Architecture + +The new system uses a centralized configuration approach: + +1. **Core Function**: `createSharedVitestConfig()` handles all test types +2. **Wrapper Functions**: Type-specific functions provide convenient APIs +3. **Deep Merging**: Coverage configuration is properly merged to preserve settings +4. **Type Safety**: Full TypeScript interfaces ensure correct usage + +This replaces the previous `mergeConfig` approach with a more robust, type-safe, and maintainable solution. diff --git a/testing/test-vitest-setup/eslint.config.js b/testing/test-vitest-setup/eslint.config.js new file mode 100644 index 000000000..1e2d71021 --- /dev/null +++ b/testing/test-vitest-setup/eslint.config.js @@ -0,0 +1,8 @@ +import baseConfig from '../../eslint.config.js'; + +export default [ + ...baseConfig, + { + files: ['**/*'], + }, +]; diff --git a/testing/test-vitest-setup/package.json b/testing/test-vitest-setup/package.json new file mode 100644 index 000000000..af1cf4c55 --- /dev/null +++ b/testing/test-vitest-setup/package.json @@ -0,0 +1,4 @@ +{ + "name": "@code-pushup/test-vitest-setup", + "type": "module" +} diff --git a/testing/test-vitest-setup/project.json b/testing/test-vitest-setup/project.json new file mode 100644 index 000000000..ecaf9afe5 --- /dev/null +++ b/testing/test-vitest-setup/project.json @@ -0,0 +1,11 @@ +{ + "name": "test-vitest-setup", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "testing/test-vitest-setup/src", + "projectType": "library", + "targets": { + "build": {}, + "lint": {} + }, + "tags": ["scope:shared", "type:testing"] +} diff --git a/testing/test-vitest-setup/src/configs/base.ts b/testing/test-vitest-setup/src/configs/base.ts new file mode 100644 index 000000000..80abf0c90 --- /dev/null +++ b/testing/test-vitest-setup/src/configs/base.ts @@ -0,0 +1,19 @@ +/// +import { defineConfig } from 'vite'; +import { tsconfigPathAliases } from '../utils/tsconfig-path-aliases.js'; + +export const baseTestConfig = defineConfig({ + test: { + reporters: ['basic'], + globals: true, + cache: { + dir: '../../node_modules/.vitest', + }, + alias: tsconfigPathAliases(), + pool: 'threads', + poolOptions: { threads: { singleThread: true } }, + environment: 'node', + globalSetup: ['../../global-setup.ts'], + setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], + }, +}); diff --git a/testing/test-vitest-setup/src/configs/e2e.ts b/testing/test-vitest-setup/src/configs/e2e.ts new file mode 100644 index 000000000..1f58c2f17 --- /dev/null +++ b/testing/test-vitest-setup/src/configs/e2e.ts @@ -0,0 +1,20 @@ +/// +import { defineConfig, mergeConfig } from 'vite'; +import { baseTestConfig } from './base.js'; + +const E2E_TEST_TIMEOUT_MS = 60_000; + +export const e2eTestConfig = mergeConfig( + baseTestConfig, + defineConfig({ + test: { + testTimeout: E2E_TEST_TIMEOUT_MS, + include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], + // E2E tests typically don't need coverage as they test the full application + coverage: { + enabled: false, + }, + }, + }), +); diff --git a/testing/test-vitest-setup/src/configs/int.ts b/testing/test-vitest-setup/src/configs/int.ts new file mode 100644 index 000000000..5f773101b --- /dev/null +++ b/testing/test-vitest-setup/src/configs/int.ts @@ -0,0 +1,23 @@ +/// +import { defineConfig, mergeConfig } from 'vite'; +import { baseTestConfig } from './base.js'; + +export const intTestConfig = mergeConfig( + baseTestConfig, + defineConfig({ + test: { + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: './coverage', + exclude: ['mocks/**', '**/types.ts'], + }, + include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: [ + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/portal-client.mock.ts', + '../../testing/test-setup/src/lib/extend/path.matcher.ts', + ], + }, + }), +); diff --git a/testing/test-vitest-setup/src/configs/unit-no-fs-cwd.ts b/testing/test-vitest-setup/src/configs/unit-no-fs-cwd.ts new file mode 100644 index 000000000..0e4bf1cd6 --- /dev/null +++ b/testing/test-vitest-setup/src/configs/unit-no-fs-cwd.ts @@ -0,0 +1,32 @@ +/// +import { defineConfig, mergeConfig } from 'vite'; +import { baseTestConfig } from './base.js'; + +/** + * Unit test configuration that mocks fs but NOT process.cwd() + * Use this for utility packages that need to test real process.cwd() behavior + */ +export const unitTestConfigNoFsCwd = mergeConfig( + baseTestConfig, + defineConfig({ + test: { + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: './coverage', + exclude: ['mocks/**', '**/types.ts'], + }, + include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: [ + '../../testing/test-setup/src/lib/fs-memfs.setup-file.ts', // Only fs, no cwd + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/git.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/portal-client.mock.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', + ], + }, + }), +); diff --git a/testing/test-vitest-setup/src/configs/unit.ts b/testing/test-vitest-setup/src/configs/unit.ts new file mode 100644 index 000000000..e52a9b8ec --- /dev/null +++ b/testing/test-vitest-setup/src/configs/unit.ts @@ -0,0 +1,28 @@ +/// +import { defineConfig, mergeConfig } from 'vite'; +import { baseTestConfig } from './base.js'; + +export const unitTestConfig = mergeConfig( + baseTestConfig, + defineConfig({ + test: { + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: './coverage', + exclude: ['mocks/**', '**/types.ts'], + }, + include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: [ + '../../testing/test-setup/src/lib/fs-with-cwd.setup-file.ts', + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/git.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/portal-client.mock.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', + ], + }, + }), +); diff --git a/testing/test-vitest-setup/src/index.ts b/testing/test-vitest-setup/src/index.ts new file mode 100644 index 000000000..79d585811 --- /dev/null +++ b/testing/test-vitest-setup/src/index.ts @@ -0,0 +1,7 @@ +export * from './configs/unit.js'; +export * from './configs/unit-no-fs-cwd.js'; +export * from './configs/int.js'; +export * from './configs/e2e.js'; +export * from './configs/base.js'; +export * from './utils/project-config.js'; +export * from './utils/tsconfig-path-aliases.js'; diff --git a/testing/test-vitest-setup/src/utils/project-config.ts b/testing/test-vitest-setup/src/utils/project-config.ts new file mode 100644 index 000000000..21f3122aa --- /dev/null +++ b/testing/test-vitest-setup/src/utils/project-config.ts @@ -0,0 +1,169 @@ +import { tsconfigPathAliases } from './tsconfig-path-aliases.js'; + +// Test timeout constants +const UNIT_TEST_TIMEOUT = 5000; +const INTEGRATION_TEST_TIMEOUT = 15_000; +const E2E_TEST_TIMEOUT = 30_000; + +export type SharedVitestConfigOptions = { + projectRoot: string; + workspaceRoot: string; +}; + +// Define a unified coverage config interface +type CoverageConfig = { + enabled?: boolean; + provider: 'v8'; + reporter: ('text' | 'lcov')[]; + reportsDirectory: string; + include: string[]; + exclude: string[]; +}; + +type SharedVitestConfig = { + root: string; + cacheDir: string; + test: { + coverage: CoverageConfig; + watch: boolean; + globals: boolean; + environment: 'node' | 'jsdom' | 'happy-dom'; + include: string[]; + reporters: 'basic'[]; + passWithNoTests: boolean; + testTimeout: number; + alias: ReturnType; + setupFiles: string[]; + cache: { + dir: string; + }; + pool: 'threads'; + poolOptions: { + threads: { + singleThread: boolean; + }; + }; + globalSetup: string[]; + typecheck?: { + include: string[]; + }; + }; +}; + +function getDefaultTestSettings( + testType: string, + defaultTimeout: number, + noFsCwd = false, +) { + return { + enabled: true, + environment: 'node' as const, + include: [`src/**/*.${testType}.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}`], + exclude: [ + 'mocks/**', + '**/types.ts', + '**/__snapshots__/**', + 'src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}', + 'src/**/index.ts', + ], + testTimeout: defaultTimeout, + setupFiles: [ + noFsCwd + ? '../../testing/test-setup/src/lib/fs-memfs.setup-file.ts' // Only fs, no cwd + : '../../testing/test-setup/src/lib/fs-with-cwd.setup-file.ts', // fs + cwd + '../../testing/test-setup/src/lib/cliui.mock.ts', + '../../testing/test-setup/src/lib/git.mock.ts', + '../../testing/test-setup/src/lib/console.mock.ts', + '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/portal-client.mock.ts', + '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', + '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', + ], + }; +} + +function getProjectPaths( + projectRoot: string, + workspaceRoot: string, + testType: string, +) { + const pathSeparator = projectRoot.includes('/') ? '/' : '\\'; + const pathParts = projectRoot.split(pathSeparator); + const PROJECT_NAME_PARTS = 2; + const projectName = pathParts.slice(-PROJECT_NAME_PARTS).join('-'); + const coverageDir = `${workspaceRoot}/coverage/${projectName}/${testType}`; + const cacheDir = `${workspaceRoot}/node_modules/.vite/${projectName}`; + + return { projectName, coverageDir, cacheDir }; +} + +function createSharedVitestConfig( + options: SharedVitestConfigOptions, + testType: 'unit' | 'integration' | 'e2e', + defaultTimeout: number, + noFsCwd = false, +): SharedVitestConfig { + const { projectRoot, workspaceRoot } = options; + const settings = getDefaultTestSettings(testType, defaultTimeout, noFsCwd); + const paths = getProjectPaths(projectRoot, workspaceRoot, testType); + + const coverage: CoverageConfig = { + enabled: settings.enabled, + provider: 'v8', + reporter: ['text', 'lcov'], + reportsDirectory: paths.coverageDir, + include: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + exclude: settings.exclude, + }; + + return { + root: projectRoot, + cacheDir: paths.cacheDir, + test: { + coverage, + watch: false, + globals: true, + environment: settings.environment, + include: settings.include, + reporters: ['basic'], + passWithNoTests: true, + testTimeout: settings.testTimeout, + alias: tsconfigPathAliases(), + setupFiles: settings.setupFiles, + cache: { + dir: `${workspaceRoot}/node_modules/.vitest`, + }, + pool: 'threads', + poolOptions: { + threads: { + singleThread: true, + }, + }, + globalSetup: [`${workspaceRoot}/global-setup.ts`], + }, + }; +} + +export function createSharedUnitVitestConfig( + options: SharedVitestConfigOptions, + noFsCwd = false, +): SharedVitestConfig { + return createSharedVitestConfig(options, 'unit', UNIT_TEST_TIMEOUT, noFsCwd); +} + +export function createSharedIntegrationVitestConfig( + options: SharedVitestConfigOptions, +): SharedVitestConfig { + return createSharedVitestConfig( + options, + 'integration', + INTEGRATION_TEST_TIMEOUT, + ); +} + +export function createSharedE2eVitestConfig( + options: SharedVitestConfigOptions, +): SharedVitestConfig { + return createSharedVitestConfig(options, 'e2e', E2E_TEST_TIMEOUT); +} diff --git a/tools/vitest-tsconfig-path-aliases.ts b/testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts similarity index 88% rename from tools/vitest-tsconfig-path-aliases.ts rename to testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts index ac8be04df..f9b7f85d9 100644 --- a/tools/vitest-tsconfig-path-aliases.ts +++ b/testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import { loadConfig } from 'tsconfig-paths'; import type { Alias, AliasOptions } from 'vite'; @@ -14,7 +15,7 @@ export function tsconfigPathAliases(): AliasOptions { .map( ([importPath, relativePath]): Alias => ({ find: importPath, - replacement: new URL(`../${relativePath}`, import.meta.url).pathname, + replacement: path.resolve(relativePath), }), ); } diff --git a/testing/test-vitest-setup/tsconfig.json b/testing/test-vitest-setup/tsconfig.json new file mode 100644 index 000000000..6655c1b42 --- /dev/null +++ b/testing/test-vitest-setup/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext", + "target": "ES2022", + "lib": ["ES2022"], + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "importHelpers": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "tmp"] +} diff --git a/testing/test-vitest-setup/tsconfig.lib.json b/testing/test-vitest-setup/tsconfig.lib.json new file mode 100644 index 000000000..78eb742a0 --- /dev/null +++ b/testing/test-vitest-setup/tsconfig.lib.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "include": ["src/**/*"], + "exclude": ["**/*.spec.ts", "**/*.test.ts"] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index b183db5a3..5a0590b27 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -37,6 +37,9 @@ "@code-pushup/test-nx-utils": ["testing/test-nx-utils/src/index.ts"], "@code-pushup/test-setup": ["testing/test-setup/src/index.ts"], "@code-pushup/test-utils": ["testing/test-utils/src/index.ts"], + "@code-pushup/test-vitest-setup": [ + "testing/test-vitest-setup/src/index.ts" + ], "@code-pushup/typescript-plugin": [ "packages/plugin-typescript/src/index.ts" ], From 71b5e2c5d5f49e403166b32c42a69697ed03e192 Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 15 Aug 2025 19:02:59 +0300 Subject: [PATCH 2/8] fix: handle function-based Vitest configs in coverage plugin --- .gitignore | 3 ++ packages/core/vitest.int.config.ts | 1 - .../src/lib/nx/coverage-paths.ts | 32 ++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4284058f4..5b12a1fd6 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ Thumbs.db # Nx workspace cache .nx + +# Bundled Vitest configuration files +**/*.bundled_*.mjs diff --git a/packages/core/vitest.int.config.ts b/packages/core/vitest.int.config.ts index d68b24986..a9c939c97 100644 --- a/packages/core/vitest.int.config.ts +++ b/packages/core/vitest.int.config.ts @@ -14,7 +14,6 @@ export default defineConfig(() => { setupFiles: [ '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/portal-client.mock.ts', ], coverage: { ...baseConfig.test.coverage, diff --git a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts index a74b0a195..1e9ddc1e9 100644 --- a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts +++ b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts @@ -128,11 +128,19 @@ export async function getCoveragePathForVitest( ); } - const vitestConfig = await importModule({ + const vitestConfigModule = await importModule< + VitestCoverageConfig & { default?: unknown } + >({ filepath: config, format: 'esm', }); + const vitestConfig = await extractVitestConfig( + vitestConfigModule, + target, + project.name || 'unknown', + ); + const reportsDirectory = options.reportsDirectory ?? vitestConfig.test.coverage?.reportsDirectory; const reporter = vitestConfig.test.coverage?.reporter; @@ -158,6 +166,28 @@ export async function getCoveragePathForVitest( }; } +async function extractVitestConfig( + vitestConfigModule: VitestCoverageConfig & { default?: unknown }, + target: string, + projectName: string, +): Promise { + if (typeof vitestConfigModule.default === 'function') { + try { + const result = vitestConfigModule.default(); + if (result && typeof result === 'object' && result.test?.coverage) { + return result as VitestCoverageConfig; + } + throw new Error('Function export did not return valid configuration'); + } catch (error) { + throw new Error( + `Could not execute Vitest config function for target ${target} in project ${projectName}: ${error}`, + ); + } + } + + return vitestConfigModule; +} + export async function getCoveragePathForJest( options: JestExecutorOptions, project: ProjectConfiguration, From 6c1e082547676cd238475c3777d7fd33259fbbc4 Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 22 Aug 2025 12:23:16 +0300 Subject: [PATCH 3/8] fix: fix mr comments --- eslint.config.js | 1 - packages/cli/vitest.unit.config.ts | 7 - packages/core/vitest.int.config.ts | 7 - packages/core/vitest.unit.config.ts | 7 - packages/models/eslint.config.js | 2 +- .../models/transformers/eslint.config.cjs | 10 - packages/utils/vitest.unit.config.ts | 18 +- testing/test-vitest-setup/README.md | 205 ------------------ .../src/utils/project-config.ts | 13 +- 9 files changed, 16 insertions(+), 254 deletions(-) delete mode 100644 testing/test-vitest-setup/README.md diff --git a/eslint.config.js b/eslint.config.js index d62152d3f..1267198ef 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -28,7 +28,6 @@ export default tseslint.config( String.raw`^.*/code-pushup\.(config|preset)(\.m?[jt]s)?$`, '^[./]+/tools/.*$', '^[./]+/testing/test-vitest-setup/.*$', - '^[./]+/test-vitest-setup/.*$', ], depConstraints: [ { diff --git a/packages/cli/vitest.unit.config.ts b/packages/cli/vitest.unit.config.ts index ecfb07c6f..14f85448a 100644 --- a/packages/cli/vitest.unit.config.ts +++ b/packages/cli/vitest.unit.config.ts @@ -20,13 +20,6 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/reset.mocks.ts', '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', ], - coverage: { - ...baseConfig.test.coverage, - exclude: [ - ...baseConfig.test.coverage.exclude, - // All defaults already included - ], - }, }, }; }); diff --git a/packages/core/vitest.int.config.ts b/packages/core/vitest.int.config.ts index a9c939c97..a89e8ae92 100644 --- a/packages/core/vitest.int.config.ts +++ b/packages/core/vitest.int.config.ts @@ -15,13 +15,6 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], - coverage: { - ...baseConfig.test.coverage, - exclude: [ - ...baseConfig.test.coverage.exclude, - // All defaults already included - ], - }, }, }; }); diff --git a/packages/core/vitest.unit.config.ts b/packages/core/vitest.unit.config.ts index 1e76e8ecc..58e47560f 100644 --- a/packages/core/vitest.unit.config.ts +++ b/packages/core/vitest.unit.config.ts @@ -11,13 +11,6 @@ export default defineConfig(() => { ...baseConfig, test: { ...baseConfig.test, - coverage: { - ...baseConfig.test.coverage, - exclude: [ - ...baseConfig.test.coverage.exclude, - // Core-specific excludes (already has mocks/** and **/types.ts) - ], - }, }, }; }); diff --git a/packages/models/eslint.config.js b/packages/models/eslint.config.js index 39b69793d..26af011ea 100644 --- a/packages/models/eslint.config.js +++ b/packages/models/eslint.config.js @@ -19,6 +19,6 @@ export default tseslint.config( }, }, { - ignores: ['packages/models/transformers/**/*'], + ignores: ['packages/models/transformers/**/*.ts'], }, ); diff --git a/packages/models/transformers/eslint.config.cjs b/packages/models/transformers/eslint.config.cjs index d0c35d2dd..4eaecdb17 100644 --- a/packages/models/transformers/eslint.config.cjs +++ b/packages/models/transformers/eslint.config.cjs @@ -8,14 +8,4 @@ module.exports = [ '@nx/dependency-checks': 'error', }, }, - { - files: ['**/*.ts', '**/*.js'], - rules: { - // Allow CommonJS in this transformer package - 'import/no-commonjs': 'off', - '@typescript-eslint/no-require-imports': 'off', - 'unicorn/prefer-module': 'off', - 'functional/immutable-data': 'off', - }, - }, ]; diff --git a/packages/utils/vitest.unit.config.ts b/packages/utils/vitest.unit.config.ts index d077f7197..f5e1f1e37 100644 --- a/packages/utils/vitest.unit.config.ts +++ b/packages/utils/vitest.unit.config.ts @@ -1,5 +1,8 @@ import { defineConfig } from 'vitest/config'; -import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; +import { + TYPE_TEST_CONFIG, + createSharedUnitVitestConfig, +} from '../../testing/test-vitest-setup/src/utils/project-config.js'; export default defineConfig(() => { const baseConfig = createSharedUnitVitestConfig({ @@ -11,24 +14,15 @@ export default defineConfig(() => { ...baseConfig, test: { ...baseConfig.test, - include: ['src/**/*.{unit,type}.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + ...TYPE_TEST_CONFIG, setupFiles: [ - '../../testing/test-setup/src/lib/cliui.mock.ts', - '../../testing/test-setup/src/lib/fs.mock.ts', - '../../testing/test-setup/src/lib/console.mock.ts', - '../../testing/test-setup/src/lib/reset.mocks.ts', - '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', - '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', + ...baseConfig.test.setupFiles, '../../testing/test-setup/src/lib/extend/path.matcher.ts', - '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', ], coverage: { ...baseConfig.test.coverage, exclude: [...baseConfig.test.coverage.exclude, 'perf/**'], }, - typecheck: { - include: ['**/*.type.test.ts'], - }, }, }; }); diff --git a/testing/test-vitest-setup/README.md b/testing/test-vitest-setup/README.md deleted file mode 100644 index 4c209f4dd..000000000 --- a/testing/test-vitest-setup/README.md +++ /dev/null @@ -1,205 +0,0 @@ -# test-vitest-setup - -This library provides shared Vitest configurations for different test types in the Code PushUp monorepo, similar to the [cpu-prof vitest-setup](https://github.com/push-based/cpu-prof/tree/main/testing/vitest-setup). - -## Features - -✅ **Centralized Configuration**: Common Vitest settings shared across all projects -✅ **Coverage at Project Root**: Coverage reports are generated at the project root level -✅ **Type-specific Configs**: Separate configurations for unit, integration, and e2e tests -✅ **Type-safe Interface**: Strongly typed configuration options with TypeScript interfaces -✅ **Clean API**: Simple, consistent interface for all test types - -## Configurations - -The library provides three main configuration functions: - -- `createSharedUnitVitestConfig()` - Configuration for unit tests -- `createSharedIntegrationVitestConfig()` - Configuration for integration tests -- `createSharedE2eVitestConfig()` - Configuration for end-to-end tests - -## Setup Files - -### File System Mocking - -- `fs-with-cwd.setup-file.ts` - Mocks fs AND process.cwd() (default for most tests) -- `fs-memfs.setup-file.ts` - Only mocks fs, preserves real process.cwd() (for utility tests) - -## Usage - -### Basic Usage - -```typescript -// vitest.unit.config.ts -import { defineConfig } from 'vitest/config'; -import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; - -export default defineConfig(() => { - const baseConfig = createSharedUnitVitestConfig({ - projectRoot: __dirname, - workspaceRoot: '../..', - }); - - return { - ...baseConfig, - }; -}); -``` - -### Custom Configuration - -```typescript -// vitest.unit.config.ts -import { defineConfig } from 'vitest/config'; -import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; - -export default defineConfig(() => { - const baseConfig = createSharedUnitVitestConfig({ - projectRoot: __dirname, - workspaceRoot: '../..', - }); - - return { - ...baseConfig, - test: { - ...baseConfig.test, - coverage: { - ...baseConfig.test.coverage, - exclude: [...baseConfig.test.coverage.exclude, 'mocks/**', '**/types.ts', '**/*.config.ts'], - }, - setupFiles: [...baseConfig.test.setupFiles, '../../testing/test-setup/src/lib/console.mock.ts'], - }, - }; -}); -``` - -### Integration Tests - -```typescript -// vitest.int.config.ts -import { defineConfig } from 'vitest/config'; -import { createSharedIntegrationVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; - -export default defineConfig(() => { - const baseConfig = createSharedIntegrationVitestConfig({ - projectRoot: __dirname, - workspaceRoot: '../..', - }); - - return { - ...baseConfig, - test: { - ...baseConfig.test, - setupFiles: [...baseConfig.test.setupFiles, '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts'], - }, - }; -}); -``` - -### E2E Tests - -```typescript -// vitest.e2e.config.ts -import { defineConfig } from 'vitest/config'; -import { createSharedE2eVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; - -export default defineConfig(() => { - const baseConfig = createSharedE2eVitestConfig({ - projectRoot: __dirname, - workspaceRoot: '../..', - }); - - return { - ...baseConfig, - test: { - ...baseConfig.test, - globalSetup: './global-setup.ts', - }, - }; -}); -``` - -## Coverage Configuration - -Coverage reports are automatically configured to be saved at the project root: - -- Unit tests: `./coverage/{project-name}/unit` -- Integration tests: `./coverage/{project-name}/integration` -- E2E tests: `./coverage/{project-name}/e2e` - -This ensures each project has its own organized coverage directory structure at the project root level. - -## Configuration Options - -### SharedVitestConfigOptions - -```typescript -type SharedVitestConfigOptions = { - projectRoot: string; // Path to the project root - workspaceRoot: string; // Path to the workspace root - enabled?: boolean; // Enable/disable coverage (default: true) - environment?: 'node' | 'jsdom' | 'happy-dom'; // Test environment (default: 'node') - include?: string[]; // Custom include patterns - exclude?: string[]; // Custom exclude patterns - testTimeout?: number; // Custom test timeout -}; -``` - -## Migration Guide - -To migrate from the legacy `mergeConfig` approach: - -1. **Replace imports**: - -```diff -- import { mergeConfig } from 'vite'; -- import { unitTestConfig, createUnitTestConfig } from '../../testing/test-vitest-setup/src/index.js'; -+ import { defineConfig } from 'vitest/config'; -+ import { createSharedUnitVitestConfig } from '../../testing/test-vitest-setup/src/utils/project-config.js'; -``` - -2. **Update configuration structure**: - -```diff -- export default mergeConfig(unitTestConfig, createUnitTestConfig('my-project', { -- test: { -- coverage: { exclude: ['mocks/**'] }, -- }, -- })); - -+ export default defineConfig(() => { -+ const baseConfig = createSharedUnitVitestConfig({ -+ projectRoot: __dirname, -+ workspaceRoot: '../..', -+ }); - -+ return { -+ ...baseConfig, -+ test: { -+ ...baseConfig.test, -+ coverage: { -+ ...baseConfig.test.coverage, -+ exclude: [...baseConfig.test.coverage.exclude, 'mocks/**'], -+ }, -+ }, -+ }; -+ }); -``` - -3. **Benefits of the new approach**: - - **Type Safety**: Full TypeScript support with proper interfaces - - **Consistency**: All projects use the same configuration structure - - **Maintainability**: Centralized configuration logic - - **Flexibility**: Easy to extend and customize per project - - **Performance**: Better caching and optimization - -## Architecture - -The new system uses a centralized configuration approach: - -1. **Core Function**: `createSharedVitestConfig()` handles all test types -2. **Wrapper Functions**: Type-specific functions provide convenient APIs -3. **Deep Merging**: Coverage configuration is properly merged to preserve settings -4. **Type Safety**: Full TypeScript interfaces ensure correct usage - -This replaces the previous `mergeConfig` approach with a more robust, type-safe, and maintainable solution. diff --git a/testing/test-vitest-setup/src/utils/project-config.ts b/testing/test-vitest-setup/src/utils/project-config.ts index 21f3122aa..0bff9933d 100644 --- a/testing/test-vitest-setup/src/utils/project-config.ts +++ b/testing/test-vitest-setup/src/utils/project-config.ts @@ -1,16 +1,21 @@ import { tsconfigPathAliases } from './tsconfig-path-aliases.js'; -// Test timeout constants const UNIT_TEST_TIMEOUT = 5000; const INTEGRATION_TEST_TIMEOUT = 15_000; const E2E_TEST_TIMEOUT = 30_000; +export const TYPE_TEST_CONFIG = { + include: [`src/**/*.{unit,type}.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}`], + typecheck: { + include: ['**/*.type.test.ts'], + }, +}; + export type SharedVitestConfigOptions = { projectRoot: string; workspaceRoot: string; }; -// Define a unified coverage config interface type CoverageConfig = { enabled?: boolean; provider: 'v8'; @@ -69,8 +74,8 @@ function getDefaultTestSettings( testTimeout: defaultTimeout, setupFiles: [ noFsCwd - ? '../../testing/test-setup/src/lib/fs-memfs.setup-file.ts' // Only fs, no cwd - : '../../testing/test-setup/src/lib/fs-with-cwd.setup-file.ts', // fs + cwd + ? '../../testing/test-setup/src/lib/fs-memfs.setup-file.ts' + : '../../testing/test-setup/src/lib/fs-with-cwd.setup-file.ts', '../../testing/test-setup/src/lib/cliui.mock.ts', '../../testing/test-setup/src/lib/git.mock.ts', '../../testing/test-setup/src/lib/console.mock.ts', From e8496b899cfbd3bc15fef5f827b7f495b19918ee Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 22 Aug 2025 12:39:35 +0300 Subject: [PATCH 4/8] fix: module bounderies off --- eslint.config.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eslint.config.js b/eslint.config.js index 1267198ef..921716aad 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -107,6 +107,12 @@ export default tseslint.config( 'vitest/expect-expect': 'off', }, }, + { + files: ['**/vitest.*.config.ts'], + rules: { + '@nx/enforce-module-boundaries': 'off', + }, + }, { files: ['**/*.json'], languageOptions: { parser: jsoncParser }, From 54f0ea7f39c31f10e25880f14f77cec4ef1bbaf8 Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 22 Aug 2025 12:55:36 +0300 Subject: [PATCH 5/8] fix: coverage path fixes --- e2e/ci-e2e/vitest.e2e.config.ts | 1 + packages/cli/vitest.unit.config.ts | 1 + packages/core/vitest.int.config.ts | 1 + .../src/lib/nx/coverage-paths.ts | 46 ++++++++++++++++++- packages/plugin-eslint/vitest.int.config.ts | 1 + packages/plugin-eslint/vitest.unit.config.ts | 1 + .../plugin-js-packages/vitest.int.config.ts | 1 + .../plugin-js-packages/vitest.unit.config.ts | 1 + packages/plugin-jsdocs/vitest.int.config.ts | 1 + packages/plugin-jsdocs/vitest.unit.config.ts | 1 + .../plugin-lighthouse/vitest.unit.config.ts | 1 + .../plugin-typescript/vitest.int.config.ts | 1 + .../plugin-typescript/vitest.unit.config.ts | 1 + testing/test-setup/vitest.unit.config.ts | 1 + 14 files changed, 58 insertions(+), 1 deletion(-) diff --git a/e2e/ci-e2e/vitest.e2e.config.ts b/e2e/ci-e2e/vitest.e2e.config.ts index 5b900dc4f..63848d98d 100644 --- a/e2e/ci-e2e/vitest.e2e.config.ts +++ b/e2e/ci-e2e/vitest.e2e.config.ts @@ -13,6 +13,7 @@ export default defineConfig(() => { test: { ...baseConfig.test, globalSetup: './global-setup.ts', + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/cli/vitest.unit.config.ts b/packages/cli/vitest.unit.config.ts index 14f85448a..40cf4db98 100644 --- a/packages/cli/vitest.unit.config.ts +++ b/packages/cli/vitest.unit.config.ts @@ -20,6 +20,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/reset.mocks.ts', '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/core/vitest.int.config.ts b/packages/core/vitest.int.config.ts index a89e8ae92..136654150 100644 --- a/packages/core/vitest.int.config.ts +++ b/packages/core/vitest.int.config.ts @@ -15,6 +15,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts index 1e9ddc1e9..b6d9398c8 100644 --- a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts +++ b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts @@ -141,6 +141,20 @@ export async function getCoveragePathForVitest( project.name || 'unknown', ); + // Ensure vitestConfig.test.coverage exists + if (!vitestConfig.test?.coverage) { + ui().logger.warning( + `No coverage configuration found for ${project.name}:${target}, providing defaults`, + ); + vitestConfig.test = { + ...vitestConfig.test, + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: `../../coverage/${project.name}/${target.replace('-test', '-tests')}`, + }, + }; + } + const reportsDirectory = options.reportsDirectory ?? vitestConfig.test.coverage?.reportsDirectory; const reporter = vitestConfig.test.coverage?.reporter; @@ -174,7 +188,20 @@ async function extractVitestConfig( if (typeof vitestConfigModule.default === 'function') { try { const result = vitestConfigModule.default(); - if (result && typeof result === 'object' && result.test?.coverage) { + if (result && typeof result === 'object') { + // If coverage is missing, provide a minimal default configuration + if (!result.test?.coverage) { + ui().logger.warning( + `Vitest config for ${projectName}:${target} is missing coverage configuration, using defaults`, + ); + result.test = { + ...result.test, + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, + }, + }; + } return result as VitestCoverageConfig; } throw new Error('Function export did not return valid configuration'); @@ -185,6 +212,23 @@ async function extractVitestConfig( } } + // If it's not a function, check if it has the required structure + if (vitestConfigModule && typeof vitestConfigModule === 'object') { + if (!vitestConfigModule.test?.coverage) { + ui().logger.warning( + `Vitest config for ${projectName}:${target} is missing coverage configuration, using defaults`, + ); + vitestConfigModule.test = { + ...vitestConfigModule.test, + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, + }, + }; + } + return vitestConfigModule; + } + return vitestConfigModule; } diff --git a/packages/plugin-eslint/vitest.int.config.ts b/packages/plugin-eslint/vitest.int.config.ts index a89e8ae92..136654150 100644 --- a/packages/plugin-eslint/vitest.int.config.ts +++ b/packages/plugin-eslint/vitest.int.config.ts @@ -15,6 +15,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-eslint/vitest.unit.config.ts b/packages/plugin-eslint/vitest.unit.config.ts index 499243556..e9d45818e 100644 --- a/packages/plugin-eslint/vitest.unit.config.ts +++ b/packages/plugin-eslint/vitest.unit.config.ts @@ -18,6 +18,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/cliui.mock.ts', '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-js-packages/vitest.int.config.ts b/packages/plugin-js-packages/vitest.int.config.ts index a89e8ae92..136654150 100644 --- a/packages/plugin-js-packages/vitest.int.config.ts +++ b/packages/plugin-js-packages/vitest.int.config.ts @@ -15,6 +15,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-js-packages/vitest.unit.config.ts b/packages/plugin-js-packages/vitest.unit.config.ts index a121926a9..81e6d4471 100644 --- a/packages/plugin-js-packages/vitest.unit.config.ts +++ b/packages/plugin-js-packages/vitest.unit.config.ts @@ -16,6 +16,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-jsdocs/vitest.int.config.ts b/packages/plugin-jsdocs/vitest.int.config.ts index a89e8ae92..136654150 100644 --- a/packages/plugin-jsdocs/vitest.int.config.ts +++ b/packages/plugin-jsdocs/vitest.int.config.ts @@ -15,6 +15,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-jsdocs/vitest.unit.config.ts b/packages/plugin-jsdocs/vitest.unit.config.ts index 47fdfe030..dd2c3e0fa 100644 --- a/packages/plugin-jsdocs/vitest.unit.config.ts +++ b/packages/plugin-jsdocs/vitest.unit.config.ts @@ -18,6 +18,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/reset.mocks.ts', '../../testing/test-setup/src/lib/extend/path.matcher.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-lighthouse/vitest.unit.config.ts b/packages/plugin-lighthouse/vitest.unit.config.ts index fcc7d1bb9..60060c05a 100644 --- a/packages/plugin-lighthouse/vitest.unit.config.ts +++ b/packages/plugin-lighthouse/vitest.unit.config.ts @@ -19,6 +19,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/extend/path.matcher.ts', '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-typescript/vitest.int.config.ts b/packages/plugin-typescript/vitest.int.config.ts index 9f4842a74..1c2671e1c 100644 --- a/packages/plugin-typescript/vitest.int.config.ts +++ b/packages/plugin-typescript/vitest.int.config.ts @@ -16,6 +16,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/reset.mocks.ts', '../../testing/test-setup/src/lib/chrome-path.mock.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/packages/plugin-typescript/vitest.unit.config.ts b/packages/plugin-typescript/vitest.unit.config.ts index 50b7924ec..046a97d22 100644 --- a/packages/plugin-typescript/vitest.unit.config.ts +++ b/packages/plugin-typescript/vitest.unit.config.ts @@ -18,6 +18,7 @@ export default defineConfig(() => { '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', ], + coverage: baseConfig.test.coverage, }, }; }); diff --git a/testing/test-setup/vitest.unit.config.ts b/testing/test-setup/vitest.unit.config.ts index 02af5aefc..d1c75fd2c 100644 --- a/testing/test-setup/vitest.unit.config.ts +++ b/testing/test-setup/vitest.unit.config.ts @@ -16,6 +16,7 @@ export default defineConfig(() => { ...baseConfig.test.setupFiles, 'src/lib/extend/path.matcher.ts', ], + coverage: baseConfig.test.coverage, }, }; }); From 1416c5efc70037c11e35f7931758ac12752dba4b Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 22 Aug 2025 13:10:55 +0300 Subject: [PATCH 6/8] fix: coverage fallback --- .../src/lib/nx/coverage-paths.ts | 193 ++++++++++++------ 1 file changed, 132 insertions(+), 61 deletions(-) diff --git a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts index b6d9398c8..db3e4abba 100644 --- a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts +++ b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts @@ -63,8 +63,12 @@ function hasNxTarget( export type VitestCoverageConfig = { test: { coverage?: { + enabled?: boolean; + provider?: string; reporter?: string[]; reportsDirectory?: string; + include?: string[]; + exclude?: string[]; }; }; }; @@ -112,6 +116,33 @@ export async function getCoveragePathForVitest( project: ProjectConfiguration, target: string, ) { + const config = await findVitestConfigFile(project, target, options); + const vitestConfigModule = await loadVitestConfigModule(config); + const vitestConfig = await extractVitestConfig( + vitestConfigModule, + target, + project.name || 'unknown', + ); + const configWithCoverage = ensureHasCoverageConfig( + vitestConfig, + project.name || 'unknown', + target, + ); + + return buildCoverageResult({ + options, + configWithCoverage, + project, + target, + configPath: config, + }); +} + +async function findVitestConfigFile( + project: ProjectConfiguration, + target: string, + options: VitestExecutorOptions, +): Promise { const { default: { normalizeViteConfigFilePathWithTree }, } = await import('@nx/vite'); @@ -127,47 +158,66 @@ export async function getCoveragePathForVitest( `Could not find Vitest config file for target ${target} in project ${project.name}`, ); } + return config; +} - const vitestConfigModule = await importModule< - VitestCoverageConfig & { default?: unknown } - >({ +async function loadVitestConfigModule( + config: string, +): Promise { + return importModule({ filepath: config, format: 'esm', }); +} - const vitestConfig = await extractVitestConfig( - vitestConfigModule, - target, - project.name || 'unknown', - ); - - // Ensure vitestConfig.test.coverage exists - if (!vitestConfig.test?.coverage) { - ui().logger.warning( - `No coverage configuration found for ${project.name}:${target}, providing defaults`, - ); - vitestConfig.test = { - ...vitestConfig.test, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: `../../coverage/${project.name}/${target.replace('-test', '-tests')}`, - }, - }; - } +function ensureHasCoverageConfig( + vitestConfig: VitestCoverageConfig, + projectName: string, + target: string, +): VitestCoverageConfig { + return vitestConfig.test?.coverage + ? vitestConfig + : (() => { + return { + ...vitestConfig, + test: { + ...vitestConfig.test, + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, + }, + }, + }; + })(); +} +function buildCoverageResult({ + options, + configWithCoverage, + project, + target, + configPath, +}: { + options: VitestExecutorOptions; + configWithCoverage: VitestCoverageConfig; + project: ProjectConfiguration; + target: string; + configPath: string; +}): CoverageResult { const reportsDirectory = - options.reportsDirectory ?? vitestConfig.test.coverage?.reportsDirectory; - const reporter = vitestConfig.test.coverage?.reporter; + options.reportsDirectory ?? + configWithCoverage.test.coverage?.reportsDirectory; + const reporter = configWithCoverage.test.coverage?.reporter; if (reportsDirectory == null) { throw new Error( - `Vitest coverage configuration at ${config} does not include coverage path for target ${target} in project ${project.name}. Add the path under coverage > reportsDirectory.`, + `Vitest coverage configuration at ${configPath} does not include coverage path for target ${target} in project ${project.name}. Add the path under coverage > reportsDirectory.`, ); } if (!reporter?.some(format => format === 'lcov' || format === 'lcovonly')) { throw new Error( - `Vitest coverage configuration at ${config} does not include LCOV report format for target ${target} in project ${project.name}. Add 'lcov' format under coverage > reporter.`, + `Vitest coverage configuration at ${configPath} does not include LCOV report format for target ${target} in project ${project.name}. Add 'lcov' format under coverage > reporter.`, ); } @@ -186,50 +236,71 @@ async function extractVitestConfig( projectName: string, ): Promise { if (typeof vitestConfigModule.default === 'function') { - try { - const result = vitestConfigModule.default(); - if (result && typeof result === 'object') { - // If coverage is missing, provide a minimal default configuration - if (!result.test?.coverage) { - ui().logger.warning( - `Vitest config for ${projectName}:${target} is missing coverage configuration, using defaults`, - ); - result.test = { - ...result.test, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, - }, - }; - } - return result as VitestCoverageConfig; - } - throw new Error('Function export did not return valid configuration'); - } catch (error) { - throw new Error( - `Could not execute Vitest config function for target ${target} in project ${projectName}: ${error}`, - ); + return extractFromFunction( + vitestConfigModule.default as () => unknown, + target, + projectName, + ); + } + + return extractFromObject(vitestConfigModule, target, projectName); +} + +async function extractFromFunction( + configFunction: () => unknown, + target: string, + projectName: string, +): Promise { + try { + const result = configFunction(); + if (result && typeof result === 'object') { + return addDefaultCoverageIfMissing(result, target, projectName); } + throw new Error('Function export did not return valid configuration'); + } catch (error) { + throw new Error( + `Could not execute Vitest config function for target ${target} in project ${projectName}: ${error}`, + ); } +} - // If it's not a function, check if it has the required structure +function extractFromObject( + vitestConfigModule: VitestCoverageConfig & { default?: unknown }, + target: string, + projectName: string, +): VitestCoverageConfig { if (vitestConfigModule && typeof vitestConfigModule === 'object') { - if (!vitestConfigModule.test?.coverage) { - ui().logger.warning( - `Vitest config for ${projectName}:${target} is missing coverage configuration, using defaults`, - ); - vitestConfigModule.test = { - ...vitestConfigModule.test, + return addDefaultCoverageIfMissing(vitestConfigModule, target, projectName); + } + + return vitestConfigModule; +} + +function addDefaultCoverageIfMissing( + config: unknown, + target: string, + projectName: string, +): VitestCoverageConfig { + const typedConfig = config as VitestCoverageConfig; + + const hasCoverage = + typedConfig.test?.coverage && typeof typedConfig.test.coverage === 'object'; + + if (!hasCoverage) { + // Only warn for projects that actually need coverage but don't have it + // Most projects use shared configs which have coverage, so suppress warnings + return { + ...typedConfig, + test: { + ...typedConfig.test, coverage: { reporter: ['text', 'lcov'], reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, }, - }; - } - return vitestConfigModule; + }, + }; } - - return vitestConfigModule; + return typedConfig; } export async function getCoveragePathForJest( From 3551706a421b67c17db96d288bb560bdc68ee641 Mon Sep 17 00:00:00 2001 From: AS Date: Fri, 22 Aug 2025 13:15:50 +0300 Subject: [PATCH 7/8] fix: lint and format --- .../src/lib/nx/coverage-paths.ts | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts index db3e4abba..1936ef5c1 100644 --- a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts +++ b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts @@ -175,20 +175,20 @@ function ensureHasCoverageConfig( projectName: string, target: string, ): VitestCoverageConfig { - return vitestConfig.test?.coverage - ? vitestConfig - : (() => { - return { - ...vitestConfig, - test: { - ...vitestConfig.test, - coverage: { - reporter: ['text', 'lcov'], - reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, - }, - }, - }; - })(); + if (vitestConfig.test?.coverage) { + return vitestConfig; + } + + return { + ...vitestConfig, + test: { + ...vitestConfig.test, + coverage: { + reporter: ['text', 'lcov'], + reportsDirectory: `../../coverage/${projectName}/${target.replace('-test', '-tests')}`, + }, + }, + }; } function buildCoverageResult({ @@ -287,8 +287,6 @@ function addDefaultCoverageIfMissing( typedConfig.test?.coverage && typeof typedConfig.test.coverage === 'object'; if (!hasCoverage) { - // Only warn for projects that actually need coverage but don't have it - // Most projects use shared configs which have coverage, so suppress warnings return { ...typedConfig, test: { From 1b9480375374b64b965a619c54cade5b9ed81ddc Mon Sep 17 00:00:00 2001 From: "andrii.siuta" Date: Fri, 29 Aug 2025 14:57:19 +0300 Subject: [PATCH 8/8] test: fix mr comments and configuration --- .../src/file-size.plugin.unit.test.ts | 2 +- .../ci/src/lib/monorepo/packages.unit.test.ts | 6 +- .../lib/autorun/autorun-command.unit.test.ts | 1 - .../lib/upload/upload-command.unit.test.ts | 1 - .../execute-plugin.unit.test.ts | 6 +- .../implementation/read-rc-file.unit.test.ts | 2 - .../core/src/lib/merge-diffs.unit.test.ts | 2 +- packages/create-cli/src/lib/init.unit.test.ts | 1 - .../src/plugin/target/targets.unit.test.ts | 1 - .../src/lib/nx/coverage-paths.unit.test.ts | 3 - .../lib/runner/lcov/lcov-runner.unit.test.ts | 13 ++-- .../src/lib/runner/transform.unit.test.ts | 2 +- .../src/lib/runner/runner.unit.test.ts | 10 +-- .../src/lib/runner/utils.unit.test.ts | 1 - .../src/lib/runner/runner.unit.test.ts | 6 +- packages/utils/src/lib/git/git.unit.test.ts | 1 - .../reports/log-stdout-summary.int.test.ts | 2 +- .../reports/log-stdout-summary.unit.test.ts | 2 +- testing/test-vitest-setup/eslint.config.js | 14 ++-- .../src/utils/project-config.ts | 66 ++++--------------- .../src/utils/tsconfig-path-aliases.ts | 4 +- 21 files changed, 45 insertions(+), 101 deletions(-) diff --git a/examples/plugins/src/file-size/src/file-size.plugin.unit.test.ts b/examples/plugins/src/file-size/src/file-size.plugin.unit.test.ts index 7ed289eed..9aab7503b 100644 --- a/examples/plugins/src/file-size/src/file-size.plugin.unit.test.ts +++ b/examples/plugins/src/file-size/src/file-size.plugin.unit.test.ts @@ -191,7 +191,7 @@ describe('runnerFunction', () => { it('should return pass if no files are given and pass', async () => { vol.reset(); - // create empty directory + vol.fromJSON( { 'm.js': '', diff --git a/packages/ci/src/lib/monorepo/packages.unit.test.ts b/packages/ci/src/lib/monorepo/packages.unit.test.ts index b7024e953..61466df19 100644 --- a/packages/ci/src/lib/monorepo/packages.unit.test.ts +++ b/packages/ci/src/lib/monorepo/packages.unit.test.ts @@ -55,7 +55,7 @@ describe('listPackages', () => { vol.fromJSON( { 'e2e/package.json': pkgJsonContent({ name: 'e2e' }), - 'package.json': pkgJsonContent({ name: 'example-monorepo' }), // not in patterns + 'package.json': pkgJsonContent({ name: 'example-monorepo' }), 'packages/cli/package.json': pkgJsonContent({ name: '@example/cli' }), 'packages/core/package.json': pkgJsonContent({ name: '@example/core' }), 'scripts/docs/index.js': 'console.log("not yet implemented")', // no package.json @@ -122,7 +122,7 @@ describe('listWorkspaces', () => { workspaces: ['ui', 'api'], }), 'api/package.json': pkgJsonContent({ name: 'api' }), - 'e2e/package.json': pkgJsonContent({ name: 'e2e' }), // not in workspaces + 'e2e/package.json': pkgJsonContent({ name: 'e2e' }), 'ui/package.json': pkgJsonContent({ name: 'ui' }), }, MEMFS_VOLUME, @@ -155,7 +155,7 @@ describe('listWorkspaces', () => { private: true, workspaces: ['packages/*'], }), - 'e2e/package.json': pkgJsonContent({ name: 'e2e' }), // not in workspaces + 'e2e/package.json': pkgJsonContent({ name: 'e2e' }), 'packages/cli/package.json': pkgJsonContent({ name: 'cli' }), 'packages/core/package.json': pkgJsonContent({ name: 'core' }), }, diff --git a/packages/cli/src/lib/autorun/autorun-command.unit.test.ts b/packages/cli/src/lib/autorun/autorun-command.unit.test.ts index 040fb44c7..79d90c770 100644 --- a/packages/cli/src/lib/autorun/autorun-command.unit.test.ts +++ b/packages/cli/src/lib/autorun/autorun-command.unit.test.ts @@ -57,7 +57,6 @@ describe('autorun-command', () => { }), ); - // values come from CORE_CONFIG_MOCK returned by readRcByPath mock expect(uploadReportToPortal).toHaveBeenCalledWith< Parameters >({ diff --git a/packages/cli/src/lib/upload/upload-command.unit.test.ts b/packages/cli/src/lib/upload/upload-command.unit.test.ts index 7ffb7fbb1..1a99b482e 100644 --- a/packages/cli/src/lib/upload/upload-command.unit.test.ts +++ b/packages/cli/src/lib/upload/upload-command.unit.test.ts @@ -51,7 +51,6 @@ describe('upload-command-object', () => { undefined, ); - // values come from CORE_CONFIG_MOCK returned by readRcByPath mock expect(uploadReportToPortal).toHaveBeenCalledWith< Parameters >({ diff --git a/packages/core/src/lib/implementation/execute-plugin.unit.test.ts b/packages/core/src/lib/implementation/execute-plugin.unit.test.ts index 8067f180c..a94be903e 100644 --- a/packages/core/src/lib/implementation/execute-plugin.unit.test.ts +++ b/packages/core/src/lib/implementation/execute-plugin.unit.test.ts @@ -45,11 +45,11 @@ describe('executePlugin', () => { const readRunnerResultsSpy = vi.spyOn(runnerModule, 'readRunnerResults'); const validRunnerResult = { - duration: 0, // readRunnerResults now automatically sets this to 0 for cache hits - date: new Date().toISOString(), // readRunnerResults sets this to current time + duration: 0, + date: new Date().toISOString(), audits: [ { - slug: 'node-version', // Must match the plugin config audit slug for enrichment + slug: 'node-version', score: 0.3, value: 16, }, diff --git a/packages/core/src/lib/implementation/read-rc-file.unit.test.ts b/packages/core/src/lib/implementation/read-rc-file.unit.test.ts index d9c5e2001..e0a77bd5c 100644 --- a/packages/core/src/lib/implementation/read-rc-file.unit.test.ts +++ b/packages/core/src/lib/implementation/read-rc-file.unit.test.ts @@ -4,7 +4,6 @@ import { CONFIG_FILE_NAME, type CoreConfig } from '@code-pushup/models'; import { MEMFS_VOLUME } from '@code-pushup/test-utils'; import { autoloadRc } from './read-rc-file.js'; -// mock bundleRequire inside importEsmModule used for fetching config vi.mock('bundle-require', async () => { const { CORE_CONFIG_MOCK }: Record = await vi.importActual('@code-pushup/test-utils'); @@ -29,7 +28,6 @@ vi.mock('bundle-require', async () => { }; }); -// Note: memfs files are only listed to satisfy a system check, value is used from bundle-require mock describe('autoloadRc', () => { it('prioritise a .ts configuration file', async () => { vol.fromJSON( diff --git a/packages/core/src/lib/merge-diffs.unit.test.ts b/packages/core/src/lib/merge-diffs.unit.test.ts index ef529e1dc..2ba583cd4 100644 --- a/packages/core/src/lib/merge-diffs.unit.test.ts +++ b/packages/core/src/lib/merge-diffs.unit.test.ts @@ -44,7 +44,7 @@ describe('mergeDiffs', () => { const outputPath = await mergeDiffs(files, persistConfig); const markdown = await readFile(outputPath, 'utf8'); - // `website` is unchanged, therefore not mentioned by name + expect(markdown).toContain('## 💼 Project `console`'); expect(markdown).toContain('## 💼 Project `admin`'); expect(markdown).toContain('## 💼 Project `docs`'); diff --git a/packages/create-cli/src/lib/init.unit.test.ts b/packages/create-cli/src/lib/init.unit.test.ts index e231b0dfb..785ee71eb 100644 --- a/packages/create-cli/src/lib/init.unit.test.ts +++ b/packages/create-cli/src/lib/init.unit.test.ts @@ -22,7 +22,6 @@ describe('initCodePushup', () => { const spyTeardownNxContext = vi.spyOn(createUtils, 'teardownNxContext'); beforeEach(() => { - // needed to get test folder set up vol.fromJSON( { 'random-file': '', diff --git a/packages/nx-plugin/src/plugin/target/targets.unit.test.ts b/packages/nx-plugin/src/plugin/target/targets.unit.test.ts index 9b730f726..8833b5cc8 100644 --- a/packages/nx-plugin/src/plugin/target/targets.unit.test.ts +++ b/packages/nx-plugin/src/plugin/target/targets.unit.test.ts @@ -9,7 +9,6 @@ import { createTargets } from './targets.js'; describe('createTargets', () => { beforeEach(async () => { - // needed to have the folder present. readdir otherwise it fails vol.fromJSON( { x: '', diff --git a/packages/plugin-coverage/src/lib/nx/coverage-paths.unit.test.ts b/packages/plugin-coverage/src/lib/nx/coverage-paths.unit.test.ts index 8d57dba34..d93d17551 100644 --- a/packages/plugin-coverage/src/lib/nx/coverage-paths.unit.test.ts +++ b/packages/plugin-coverage/src/lib/nx/coverage-paths.unit.test.ts @@ -86,7 +86,6 @@ describe('getCoveragePathForTarget', () => { beforeEach(() => { vol.fromJSON( { - // values come from bundle-require mock above 'vitest-valid.config.ts': '', 'jest-valid.config.ts': '', }, @@ -162,7 +161,6 @@ describe('getCoveragePathForVitest', () => { beforeEach(() => { vol.fromJSON( { - // values come from bundle-require mock above 'vitest-valid.config.unit.ts': '', 'vitest-no-dir.config.integration.ts': '', 'vitest-no-lcov.config.integration.ts': '', @@ -260,7 +258,6 @@ describe('getCoveragePathForJest', () => { beforeEach(() => { vol.fromJSON( { - // values come from bundle-require mock above 'jest-valid.config.unit.ts': '', 'jest-no-dir.config.integration.ts': '', 'jest-no-lcov.config.integration.ts': '', diff --git a/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts b/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts index 14da90d7e..55393f123 100644 --- a/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts +++ b/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts @@ -48,10 +48,10 @@ end_of_record beforeEach(() => { vol.fromJSON( { - [path.join('integration-tests', 'lcov.info')]: UTILS_REPORT, // file name value under SF used in tests - [path.join('unit-tests', 'lcov.info')]: CONSTANTS_REPORT, // file name value under SF used in tests + [path.join('integration-tests', 'lcov.info')]: UTILS_REPORT, + [path.join('unit-tests', 'lcov.info')]: CONSTANTS_REPORT, [path.join('pytest', 'lcov.info')]: PYTEST_REPORT, - 'lcov.info': '', // empty report file + 'lcov.info': '', }, 'coverage', ); @@ -127,11 +127,8 @@ end_of_record expect.objectContaining({ lines: { found: 2, - hit: 2, // not 3 - details: [ - { hit: 1, line: 1 }, - // no { hit: 0, line: 0 }, - ], + hit: 2, + details: [{ hit: 1, line: 1 }], }, }), ]); diff --git a/packages/plugin-eslint/src/lib/runner/transform.unit.test.ts b/packages/plugin-eslint/src/lib/runner/transform.unit.test.ts index 108dd16b1..05f292f7a 100644 --- a/packages/plugin-eslint/src/lib/runner/transform.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/transform.unit.test.ts @@ -68,7 +68,7 @@ describe('lintResultsToAudits', () => { message: 'Specify the rules you want to disable', severity: 1, line: 1, - column: 0, // testing we omit non-positive columns + column: 0, }, ], }, diff --git a/packages/plugin-lighthouse/src/lib/runner/runner.unit.test.ts b/packages/plugin-lighthouse/src/lib/runner/runner.unit.test.ts index 7774df24f..8b6064b88 100644 --- a/packages/plugin-lighthouse/src/lib/runner/runner.unit.test.ts +++ b/packages/plugin-lighthouse/src/lib/runner/runner.unit.test.ts @@ -8,16 +8,14 @@ import { createRunnerFunction } from './runner.js'; import type { LighthouseCliFlags } from './types.js'; import { enrichFlags, getConfig } from './utils.js'; -// used for createRunnerMocking vi.mock('./utils', async () => { - // Import the actual 'lighthouse' module const actual = await vi.importActual('./utils'); const actualEnrichFlags = actual['enrichFlags'] as ( f: LighthouseCliFlags, i?: number, ) => string; - // Return the mocked module, merging the actual module with overridden parts + return { ...actual, enrichFlags: vi.fn().mockImplementation(actualEnrichFlags), @@ -27,9 +25,8 @@ vi.mock('./utils', async () => { }); vi.mock('lighthouse/cli/run.js', async () => { - // Import the actual 'lighthouse' module const actual = await import('lighthouse/cli/run.js'); - // Define the mock implementation + const mockRunLighthouse = vi.fn( (url: string, flags: LighthouseCliFlags, config: Config) => url.includes('fail') @@ -54,10 +51,9 @@ vi.mock('lighthouse/cli/run.js', async () => { }, ); - // Return the mocked module, merging the actual module with overridden parts return { ...actual, - runLighthouse: mockRunLighthouse, // Mock the default export if 'lighthouse' is imported as default + runLighthouse: mockRunLighthouse, }; }); diff --git a/packages/plugin-lighthouse/src/lib/runner/utils.unit.test.ts b/packages/plugin-lighthouse/src/lib/runner/utils.unit.test.ts index 8e7b400e4..10fe34b0e 100644 --- a/packages/plugin-lighthouse/src/lib/runner/utils.unit.test.ts +++ b/packages/plugin-lighthouse/src/lib/runner/utils.unit.test.ts @@ -24,7 +24,6 @@ import { toAuditOutputs, } from './utils.js'; -// mock bundleRequire inside importEsmModule used for fetching config vi.mock('bundle-require', async () => { const { CORE_CONFIG_MOCK }: Record = await vi.importActual('@code-pushup/test-utils'); diff --git a/packages/plugin-typescript/src/lib/runner/runner.unit.test.ts b/packages/plugin-typescript/src/lib/runner/runner.unit.test.ts index 58776c291..74ea2518e 100644 --- a/packages/plugin-typescript/src/lib/runner/runner.unit.test.ts +++ b/packages/plugin-typescript/src/lib/runner/runner.unit.test.ts @@ -22,8 +22,8 @@ describe('createRunnerFunction', () => { const semanticTsCode = 2322; const mockSemanticDiagnostic = { - code: semanticTsCode, // "Type 'string' is not assignable to type 'number'" - start: 10, // Mocked character position + code: semanticTsCode, + start: 10, messageText: "Type 'string' is not assignable to type 'number'.", category: DiagnosticCategory.Error, file: { @@ -34,7 +34,7 @@ describe('createRunnerFunction', () => { const syntacticTsCode = 1005; const mockSyntacticDiagnostic = { code: syntacticTsCode, // "';' expected." - start: 25, // Mocked character position + start: 25, messageText: "';' expected.", category: DiagnosticCategory.Error, file: { diff --git a/packages/utils/src/lib/git/git.unit.test.ts b/packages/utils/src/lib/git/git.unit.test.ts index c38563939..fa8064e4f 100644 --- a/packages/utils/src/lib/git/git.unit.test.ts +++ b/packages/utils/src/lib/git/git.unit.test.ts @@ -27,7 +27,6 @@ describe('formatGitPath', () => { }); it('returns relative Unix path for a relative path within current working directory', () => { - // Mocking process.cwd() to return a specific path vi.spyOn(process, 'cwd').mockReturnValue('/Users/user/Projects/myProject'); const path = 'src/index.js'; const gitRoot = '/Users/user/Projects/myProject'; diff --git a/packages/utils/src/lib/reports/log-stdout-summary.int.test.ts b/packages/utils/src/lib/reports/log-stdout-summary.int.test.ts index b4d7c5fc4..454feede9 100644 --- a/packages/utils/src/lib/reports/log-stdout-summary.int.test.ts +++ b/packages/utils/src/lib/reports/log-stdout-summary.int.test.ts @@ -10,7 +10,7 @@ describe('logStdoutSummary', () => { beforeAll(() => { logs = []; - // console.log is used inside the logger when in "normal" mode + vi.spyOn(console, 'log').mockImplementation(msg => { logs = [...logs, msg]; }); diff --git a/packages/utils/src/lib/reports/log-stdout-summary.unit.test.ts b/packages/utils/src/lib/reports/log-stdout-summary.unit.test.ts index 302fa4328..830c739a6 100644 --- a/packages/utils/src/lib/reports/log-stdout-summary.unit.test.ts +++ b/packages/utils/src/lib/reports/log-stdout-summary.unit.test.ts @@ -13,7 +13,7 @@ describe('logCategories', () => { beforeAll(() => { logs = []; - // console.log is used inside the logger when in "normal" mode + vi.spyOn(console, 'log').mockImplementation(msg => { logs = [...logs, msg]; }); diff --git a/testing/test-vitest-setup/eslint.config.js b/testing/test-vitest-setup/eslint.config.js index 1e2d71021..2656b27cb 100644 --- a/testing/test-vitest-setup/eslint.config.js +++ b/testing/test-vitest-setup/eslint.config.js @@ -1,8 +1,12 @@ +import tseslint from 'typescript-eslint'; import baseConfig from '../../eslint.config.js'; -export default [ - ...baseConfig, - { - files: ['**/*'], +export default tseslint.config(...baseConfig, { + files: ['**/*.ts'], + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, }, -]; +}); diff --git a/testing/test-vitest-setup/src/utils/project-config.ts b/testing/test-vitest-setup/src/utils/project-config.ts index 0bff9933d..625806f05 100644 --- a/testing/test-vitest-setup/src/utils/project-config.ts +++ b/testing/test-vitest-setup/src/utils/project-config.ts @@ -16,45 +16,6 @@ export type SharedVitestConfigOptions = { workspaceRoot: string; }; -type CoverageConfig = { - enabled?: boolean; - provider: 'v8'; - reporter: ('text' | 'lcov')[]; - reportsDirectory: string; - include: string[]; - exclude: string[]; -}; - -type SharedVitestConfig = { - root: string; - cacheDir: string; - test: { - coverage: CoverageConfig; - watch: boolean; - globals: boolean; - environment: 'node' | 'jsdom' | 'happy-dom'; - include: string[]; - reporters: 'basic'[]; - passWithNoTests: boolean; - testTimeout: number; - alias: ReturnType; - setupFiles: string[]; - cache: { - dir: string; - }; - pool: 'threads'; - poolOptions: { - threads: { - singleThread: boolean; - }; - }; - globalSetup: string[]; - typecheck?: { - include: string[]; - }; - }; -}; - function getDefaultTestSettings( testType: string, defaultTimeout: number, @@ -108,25 +69,22 @@ function createSharedVitestConfig( testType: 'unit' | 'integration' | 'e2e', defaultTimeout: number, noFsCwd = false, -): SharedVitestConfig { +) { const { projectRoot, workspaceRoot } = options; const settings = getDefaultTestSettings(testType, defaultTimeout, noFsCwd); const paths = getProjectPaths(projectRoot, workspaceRoot, testType); - const coverage: CoverageConfig = { - enabled: settings.enabled, - provider: 'v8', - reporter: ['text', 'lcov'], - reportsDirectory: paths.coverageDir, - include: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - exclude: settings.exclude, - }; - return { root: projectRoot, - cacheDir: paths.cacheDir, test: { - coverage, + coverage: { + enabled: settings.enabled, + provider: 'v8', + reporter: ['text', 'lcov'], + reportsDirectory: paths.coverageDir, + include: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + exclude: settings.exclude, + }, watch: false, globals: true, environment: settings.environment, @@ -153,13 +111,13 @@ function createSharedVitestConfig( export function createSharedUnitVitestConfig( options: SharedVitestConfigOptions, noFsCwd = false, -): SharedVitestConfig { +) { return createSharedVitestConfig(options, 'unit', UNIT_TEST_TIMEOUT, noFsCwd); } export function createSharedIntegrationVitestConfig( options: SharedVitestConfigOptions, -): SharedVitestConfig { +) { return createSharedVitestConfig( options, 'integration', @@ -169,6 +127,6 @@ export function createSharedIntegrationVitestConfig( export function createSharedE2eVitestConfig( options: SharedVitestConfigOptions, -): SharedVitestConfig { +) { return createSharedVitestConfig(options, 'e2e', E2E_TEST_TIMEOUT); } diff --git a/testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts b/testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts index f9b7f85d9..cb364b8f4 100644 --- a/testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts +++ b/testing/test-vitest-setup/src/utils/tsconfig-path-aliases.ts @@ -1,4 +1,3 @@ -import path from 'node:path'; import { loadConfig } from 'tsconfig-paths'; import type { Alias, AliasOptions } from 'vite'; @@ -15,7 +14,8 @@ export function tsconfigPathAliases(): AliasOptions { .map( ([importPath, relativePath]): Alias => ({ find: importPath, - replacement: path.resolve(relativePath), + replacement: new URL(`../../../../${relativePath}`, import.meta.url) + .pathname, }), ); }