diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 597681811827..46f9e0f80d97 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -315,23 +315,22 @@ export class Vitest { const cwd = process.cwd() - const projects: (() => Promise)[] = [] + const projects: WorkspaceProject[] = [] try { // we have to resolve them one by one because CWD should depend on the project for (const filepath of filteredWorkspaces) { if (this.server.config.configFile === filepath) { const project = await this.createCoreProject() - projects.push(() => Promise.resolve(project)) + projects.push(project) continue } const dir = filepath.endsWith('/') ? filepath.slice(0, -1) : dirname(filepath) if (isMainThread) process.chdir(dir) - // this just resolves the config, later we also wait when the server is resolved, - // but we can do that in parallel because it doesn't depend on process.cwd() - // this is strictly a performance optimization so we don't need to wait for server to start - projects.push(await initializeProject(filepath, this, { workspaceConfigPath, test: cliOverrides })) + projects.push( + await initializeProject(filepath, this, { workspaceConfigPath, test: cliOverrides }), + ) } } finally { @@ -339,7 +338,7 @@ export class Vitest { process.chdir(cwd) } - const projectPromises: Promise<() => Promise>[] = [] + const projectPromises: Promise[] = [] projectsOptions.forEach((options, index) => { // we can resolve these in parallel because process.cwd() is not changed @@ -349,14 +348,10 @@ export class Vitest { if (!projects.length && !projectPromises.length) return [await this.createCoreProject()] - const resolvedProjectsReceivers = [ + const resolvedProjects = await Promise.all([ ...projects, ...await Promise.all(projectPromises), - ] - // we need to wait when the server is resolved, we can do that in parallel - const resolvedProjects = await Promise.all( - resolvedProjectsReceivers.map(receiver => receiver()), - ) + ]) const names = new Set() for (const project of resolvedProjects) { diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index 8b8a52af1551..57f838b0b994 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -12,7 +12,6 @@ import { deepMerge } from '../utils' import type { Typechecker } from '../typecheck/typechecker' import type { BrowserProvider } from '../types/browser' import { getBrowserProvider } from '../integrations/browser' -import { createDefer } from '../public/utils' import { isBrowserEnabled, resolveConfig } from './config' import { WorkspaceVitestPlugin } from './plugins/workspace' import { createViteServer } from './vite' @@ -40,40 +39,22 @@ export async function initializeProject(workspacePath: string | number, ctx: Vit : workspacePath.endsWith('/') ? workspacePath : dirname(workspacePath) ) - return new Promise<() => Promise>((resolve, reject) => { - const resolution = createDefer() - let configResolved = false - const config: ViteInlineConfig = { - ...options, - root, - logLevel: 'error', - configFile, - // this will make "mode": "test" | "benchmark" inside defineConfig - mode: options.test?.mode || options.mode || ctx.config.mode, - plugins: [ - { - name: 'vitest:workspace:resolve', - configResolved() { - configResolved = true - resolve(() => resolution) - }, - }, - ...options.plugins || [], - WorkspaceVitestPlugin(project, { ...options, root, workspacePath }), - ], - } + const config: ViteInlineConfig = { + ...options, + root, + logLevel: 'error', + configFile, + // this will make "mode": "test" | "benchmark" inside defineConfig + mode: options.test?.mode || options.mode || ctx.config.mode, + plugins: [ + ...options.plugins || [], + WorkspaceVitestPlugin(project, { ...options, root, workspacePath }), + ], + } - createViteServer(config) - .then(() => resolution.resolve(project)) - .catch((err) => { - if (configResolved) - resolution.reject(err) - else - reject(err) - }) + await createViteServer(config) - return project - }) + return project } export class WorkspaceProject { diff --git a/test/workspaces/cwdPlugin.d.ts b/test/workspaces/cwdPlugin.d.ts new file mode 100644 index 000000000000..9ebe0c31f11a --- /dev/null +++ b/test/workspaces/cwdPlugin.d.ts @@ -0,0 +1,3 @@ +import type { Plugin } from 'vite' + +export function cwdPlugin(name: string): Plugin diff --git a/test/workspaces/cwdPlugin.js b/test/workspaces/cwdPlugin.js new file mode 100644 index 000000000000..acedf5d214ae --- /dev/null +++ b/test/workspaces/cwdPlugin.js @@ -0,0 +1,13 @@ +// @ts-check + +export function cwdPlugin(name) { + return { + name: `vitest:test:workspace-${name}`, + configResolved() { + process.env[`${name}_CWD_CONFIG`] = process.cwd() + }, + configureServer() { + process.env[`${name}_CWD_SERVER`] = process.cwd() + }, + } +} diff --git a/test/workspaces/globalTest.ts b/test/workspaces/globalTest.ts index 5267232fb7e2..3ad6b6a5421e 100644 --- a/test/workspaces/globalTest.ts +++ b/test/workspaces/globalTest.ts @@ -33,8 +33,8 @@ export async function teardown() { try { assert.ok(results.success) assert.equal(results.numTotalTestSuites, 28) - assert.equal(results.numTotalTests, 30) - assert.equal(results.numPassedTests, 30) + assert.equal(results.numTotalTests, 31) + assert.equal(results.numPassedTests, 31) const shared = results.testResults.filter((r: any) => r.name.includes('space_shared/test.spec.ts')) diff --git a/test/workspaces/space_1/test/env-injected.spec.ts b/test/workspaces/space_1/test/env-injected.spec.ts index 9ac381fa72de..6fb705198d2d 100644 --- a/test/workspaces/space_1/test/env-injected.spec.ts +++ b/test/workspaces/space_1/test/env-injected.spec.ts @@ -1,3 +1,4 @@ +import { resolve } from 'node:path' import { expect, test } from 'vitest' declare global { @@ -23,3 +24,13 @@ test('env variable is assigned', () => { expect(process.env.CONFIG_LOCAL).toBe('local') expect(process.env.CONFIG_OVERRIDE).toBe('local') }) + +test('cwd is resolved correctly', () => { + const spaceRoot = resolve(import.meta.dirname, '..') + const rootPath = resolve(spaceRoot, '..') + + expect(process.env.ROOT_CWD_CONFIG).toBe(rootPath) + expect(process.env.ROOT_CWD_SERVER).toBe(rootPath) + expect(process.env.SPACE_2_CWD_CONFIG).toBe(spaceRoot) + expect(process.env.SPACE_2_CWD_SERVER).toBe(spaceRoot) +}) diff --git a/test/workspaces/space_1/vite.config.ts b/test/workspaces/space_1/vite.config.ts index 2423c17577bd..2280fe0ef5c3 100644 --- a/test/workspaces/space_1/vite.config.ts +++ b/test/workspaces/space_1/vite.config.ts @@ -1,7 +1,9 @@ import { defineProject } from 'vitest/config' +import { cwdPlugin } from '../cwdPlugin' export default defineProject({ envPrefix: ['VITE_', 'CUSTOM_'], + plugins: [cwdPlugin('SPACE_2')], define: { __DEV__: 'true', }, diff --git a/test/workspaces/vitest.config.ts b/test/workspaces/vitest.config.ts index 5377d72a8ebf..52540c401d50 100644 --- a/test/workspaces/vitest.config.ts +++ b/test/workspaces/vitest.config.ts @@ -1,4 +1,5 @@ import { defineConfig } from 'vitest/config' +import { cwdPlugin } from './cwdPlugin.js' if (process.env.TEST_WATCH) { // Patch stdin on the process so that we can fake it to seem like a real interactive terminal and pass the TTY checks @@ -8,6 +9,7 @@ if (process.env.TEST_WATCH) { export default defineConfig({ envPrefix: ['VITE_', 'CUSTOM_', 'ROOT_'], + plugins: [cwdPlugin('ROOT')], test: { coverage: { enabled: true,