diff --git a/docs/guide/workspace.md b/docs/guide/workspace.md index 579ca2c02fcc..c53e08e16ece 100644 --- a/docs/guide/workspace.md +++ b/docs/guide/workspace.md @@ -44,7 +44,7 @@ export default defineConfig({ Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If this glob pattern matches any file it will be considered a Vitest config even if it doesn't have a `vitest` in its name. ::: warning -Vitest does not treat the root `vitest.config` file as a workspace project unless it is explicitly specified in the workspace configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. +Vitest does not treat the root `vitest.config` file as a workspace project unless it is explicitly specified in the workspace configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. Note that Vitest will always run certain plugin hooks, like `apply`, `config`, `configResolved` or `configureServer`, specified in the root config file. Vitest also uses the same plugins to execute global setups, workspace files and custom coverage provider. ::: You can also reference projects with their config files: @@ -233,7 +233,7 @@ bun test --project e2e --project unit ## Configuration -None of the configuration options are inherited from the root-level config file. You can create a shared config file and merge it with the project config yourself: +None of the configuration options are inherited from the root-level config file, even if the workspace is defined inside that config and not in a separate `vitest.workspace` file. You can create a shared config file and merge it with the project config yourself: ```ts [packages/a/vitest.config.ts] import { defineProject, mergeConfig } from 'vitest/config' diff --git a/packages/vitest/src/node/project.ts b/packages/vitest/src/node/project.ts index 213d23f43222..081404e40cdb 100644 --- a/packages/vitest/src/node/project.ts +++ b/packages/vitest/src/node/project.ts @@ -717,7 +717,6 @@ export interface SerializedTestProject { interface InitializeProjectOptions extends UserWorkspaceConfig { configFile: string | false - extends?: string } export async function initializeProject( @@ -727,7 +726,7 @@ export async function initializeProject( ) { const project = new TestProject(workspacePath, ctx, options) - const { extends: extendsConfig, configFile, ...restOptions } = options + const { configFile, ...restOptions } = options const config: ViteInlineConfig = { ...restOptions, diff --git a/packages/vitest/src/node/workspace/resolveWorkspace.ts b/packages/vitest/src/node/workspace/resolveWorkspace.ts index aa5a8d4bfb8d..f6a31b3cd716 100644 --- a/packages/vitest/src/node/workspace/resolveWorkspace.ts +++ b/packages/vitest/src/node/workspace/resolveWorkspace.ts @@ -62,11 +62,9 @@ export async function resolveWorkspace( // if extends a config file, resolve the file path const configFile = typeof options.extends === 'string' ? resolve(configRoot, options.extends) - : false - // if extends a root config, use the users root options - const rootOptions = options.extends === true - ? vitest._options - : {} + : options.extends === true + ? (vitest.vite.config.configFile || false) + : false // if `root` is configured, resolve it relative to the workspace file or vite root (like other options) // if `root` is not specified, inline configs use the same root as the root project const root = options.root @@ -75,7 +73,7 @@ export async function resolveWorkspace( projectPromises.push(concurrent(() => initializeProject( index, vitest, - mergeConfig(rootOptions, { ...options, root, configFile }) as any, + { ...options, root, configFile }, ))) }) diff --git a/test/config/fixtures/workspace/browser/workspace-with-browser.ts b/test/config/fixtures/workspace/browser/workspace-with-browser.ts index 96764a79256c..948776d8ea34 100644 --- a/test/config/fixtures/workspace/browser/workspace-with-browser.ts +++ b/test/config/fixtures/workspace/browser/workspace-with-browser.ts @@ -7,7 +7,7 @@ export default defineWorkspace([ browser: { enabled: true, provider: 'webdriverio', - name: 'chrome' + name: 'chrome', }, } } diff --git a/test/config/fixtures/workspace/config-extends/repro.test.js b/test/config/fixtures/workspace/config-extends/repro.test.js new file mode 100644 index 000000000000..955b1d336ed6 --- /dev/null +++ b/test/config/fixtures/workspace/config-extends/repro.test.js @@ -0,0 +1,6 @@ +import { test, expect } from 'vitest'; +import repro from 'virtual:repro'; + +test('importing a virtual module', () => { + expect(repro).toBe('Hello, world!'); +}); diff --git a/test/config/fixtures/workspace/config-extends/vitest.config.ts b/test/config/fixtures/workspace/config-extends/vitest.config.ts new file mode 100644 index 000000000000..8f3374e7c148 --- /dev/null +++ b/test/config/fixtures/workspace/config-extends/vitest.config.ts @@ -0,0 +1,30 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [ + { + name: 'virtual', + resolveId(source) { + if (source === 'virtual:repro') { + return '\0virtual:repro'; + } + }, + load(id) { + if (id === '\0virtual:repro') { + return `export default "Hello, world!"`; + } + }, + }, + ], + test: { + workspace: [ + { + extends: true, + test: { + name: 'node', + environment: 'node', + }, + }, + ], + }, +}); diff --git a/test/config/test/workspace.test.ts b/test/config/test/workspace.test.ts index 7979d6fb6390..15ec6ac35faf 100644 --- a/test/config/test/workspace.test.ts +++ b/test/config/test/workspace.test.ts @@ -126,3 +126,11 @@ it('can define inline workspace config programmatically', async () => { expect(stdout).toContain('project-3') expect(stdout).toContain('3 passed') }) + +it('correctly inherits the root config', async () => { + const { stderr, stdout } = await runVitest({ + root: 'fixtures/workspace/config-extends', + }) + expect(stderr).toBe('') + expect(stdout).toContain('repro.test.js > importing a virtual module') +})