Skip to content

Commit

Permalink
fix(vitest): don't fail if the working directory starts with a lowerc…
Browse files Browse the repository at this point in the history
…ase drive letter (#6779)
  • Loading branch information
sheremet-va authored Oct 25, 2024
1 parent 169028f commit df6d750
Show file tree
Hide file tree
Showing 20 changed files with 64 additions and 24 deletions.
4 changes: 3 additions & 1 deletion packages/browser/src/client/public/error-catcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ async function reportUnexpectedError(
error,
) {
const processedError = serializeError(error)
await client.rpc.onUnhandledError(processedError, type)
await client.waitForConnection().then(() => {
return client.rpc.onUnhandledError(processedError, type)
}).catch(console.error)
const state = __vitest_browser_runner__

if (state.type === 'orchestrator') {
Expand Down
1 change: 1 addition & 0 deletions packages/browser/src/node/serverTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export async function resolveTester(
try {
const indexhtml = await server.vite.transformIndexHtml(url.pathname, testerHtml)
return replacer(indexhtml, {
__VITEST_FAVICON__: server.faviconUrl,
__VITEST_INJECTOR__: injector,
__VITEST_APPEND__: `
__vitest_browser_runner__.runningFiles = ${tests}
Expand Down
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"codemirror-theme-vars": "^0.1.2",
"d3-graph-controller": "^3.0.11",
"floating-vue": "^5.2.2",
"rollup": "^4.24.0",
"splitpanes": "^3.1.5",
"unocss": "^0.63.6",
"unplugin-auto-import": "^0.18.3",
Expand Down
4 changes: 1 addition & 3 deletions packages/vite-node/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type { HotContext, ModuleCache, ViteNodeRunnerOptions } from './types'

import { createRequire } from 'node:module'
// we need native dirname, because windows __dirname has \\
import { dirname } from 'node:path'
import { dirname, resolve } from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'
import vm from 'node:vm'
import createDebug from 'debug'
import { resolve } from 'pathe'
import { extractSourceMap } from './source-map'
import {
cleanUrl,
Expand Down
4 changes: 3 additions & 1 deletion packages/vite-node/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export function normalizeRequestId(id: string, base?: string): string {
id = `/${id.slice(base.length)}`
}

// keep drive the same as in process cwd
// keep drive the same as in process cwd. ideally, this should be resolved on Vite side
// Vite always resolves drive letters to the upper case because of the use of `realpathSync`
// https://github.com/vitejs/vite/blob/0ab20a3ee26eacf302415b3087732497d0a2f358/packages/vite/src/node/utils.ts#L635
if (driveRegexp && !driveRegexp?.test(id) && driveOppositeRegext?.test(id)) {
id = id.replace(driveOppositeRegext, `${drive}$1`)
}
Expand Down
4 changes: 3 additions & 1 deletion packages/vitest/src/node/plugins/mocks.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { Plugin } from 'vite'
import { automockPlugin, hoistMocksPlugin } from '@vitest/mocker/node'
import { normalize } from 'pathe'
import { distDir } from '../../paths'
import { generateCodeFrame } from '../error'

export function MocksPlugins(): Plugin[] {
const normalizedDistDir = normalize(distDir)
return [
hoistMocksPlugin({
filter(id) {
if (id.includes(distDir)) {
if (id.includes(normalizedDistDir)) {
return false
}
return true
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/forks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import type { SerializedConfig } from '../types/config'
import type { WorkspaceProject } from '../workspace'
import EventEmitter from 'node:events'
import * as nodeos from 'node:os'
import { resolve } from 'node:path'
import v8 from 'node:v8'
import { createBirpc } from 'birpc'
import { resolve } from 'pathe'
import { Tinypool } from 'tinypool'
import { groupBy } from '../../utils/base'
import { wrapSerializableConfig } from '../../utils/config-helpers'
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import type { SerializedConfig } from '../types/config'
import type { WorkerContext } from '../types/worker'
import type { WorkspaceProject } from '../workspace'
import * as nodeos from 'node:os'
import { resolve } from 'node:path'
import { MessageChannel } from 'node:worker_threads'
import { createBirpc } from 'birpc'
import { resolve } from 'pathe'
import Tinypool from 'tinypool'
import { groupBy } from '../../utils/base'
import { envsOrder, groupFilesByEnv } from '../../utils/test-helpers'
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/vmForks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import type { ResolvedConfig, SerializedConfig } from '../types/config'
import type { WorkspaceProject } from '../workspace'
import EventEmitter from 'node:events'
import * as nodeos from 'node:os'
import { resolve } from 'node:path'
import v8 from 'node:v8'
import { createBirpc } from 'birpc'
import { resolve } from 'pathe'
import Tinypool from 'tinypool'
import { rootDir } from '../../paths'
import { wrapSerializableConfig } from '../../utils/config-helpers'
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/pools/vmThreads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import type { ResolvedConfig, SerializedConfig } from '../types/config'
import type { WorkerContext } from '../types/worker'
import type { WorkspaceProject } from '../workspace'
import * as nodeos from 'node:os'
import { resolve } from 'node:path'
import { MessageChannel } from 'node:worker_threads'
import { createBirpc } from 'birpc'
import { resolve } from 'pathe'
import Tinypool from 'tinypool'
import { rootDir } from '../../paths'
import { getWorkerMemoryLimit, stringToBytes } from '../../utils/memory-limit'
Expand Down
11 changes: 7 additions & 4 deletions packages/vitest/src/node/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import type {
import { promises as fs } from 'node:fs'
import { rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { deepMerge, nanoid } from '@vitest/utils'
import path from 'node:path'
import { deepMerge, nanoid, slash } from '@vitest/utils'
import fg from 'fast-glob'
import mm from 'micromatch'
import {
Expand All @@ -27,7 +28,6 @@ import {
join,
relative,
resolve,
toNamespacedPath,
} from 'pathe'
import { ViteNodeRunner } from 'vite-node/client'
import { ViteNodeServer } from 'vite-node/server'
Expand Down Expand Up @@ -302,7 +302,10 @@ export class WorkspaceProject {
}

const files = await fg(include, globOptions)
return files.map(file => resolve(cwd, file))
// keep the slashes consistent with Vite
// we are not using the pathe here because it normalizes the drive letter on Windows
// and we want to keep it the same as working dir
return files.map(file => slash(path.resolve(cwd, file)))
}

async isTargetFile(id: string, source?: string): Promise<boolean> {
Expand All @@ -329,7 +332,7 @@ export class WorkspaceProject {

filterFiles(testFiles: string[], filters: string[], dir: string) {
if (filters.length && process.platform === 'win32') {
filters = filters.map(f => toNamespacedPath(f))
filters = filters.map(f => slash(f))
}

if (filters.length) {
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/paths.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { resolve } from 'node:path'
import url from 'node:url'
import { resolve } from 'pathe'

export const rootDir = resolve(url.fileURLToPath(import.meta.url), '../../')
export const distDir = resolve(
Expand Down
4 changes: 3 additions & 1 deletion packages/vitest/src/runtime/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
import { distDir } from '../paths'
import { VitestMocker } from './mocker'

const normalizedDistDir = normalize(distDir)

const { readFileSync } = fs

export interface ExecuteOptions extends ViteNodeRunnerOptions {
Expand Down Expand Up @@ -112,7 +114,7 @@ export async function startVitestExecutor(options: ContextExecutorOptions) {
}
// always externalize Vitest because we import from there before running tests
// so we already have it cached by Node.js
if (id.includes(distDir)) {
if (id.includes(distDir) || id.includes(normalizedDistDir)) {
const { path } = toFilePath(id, state().config.root)
const externalize = pathToFileURL(path).toString()
externalizeMap.set(id, externalize)
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/runtime/mocker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { ManualMockedModule, MockedModuleType } from '@vitest/mocker'
import type { MockFactory, MockOptions, PendingSuiteMock } from '../types/mocker'
import type { VitestExecutor } from './execute'
import { isAbsolute, resolve } from 'node:path'
import vm from 'node:vm'
import { AutomockedModule, MockerRegistry, mockObject, RedirectedModule } from '@vitest/mocker'
import { findMockRedirect } from '@vitest/mocker/redirect'
import { highlight } from '@vitest/utils'
import { isAbsolute, resolve } from 'pathe'
import { distDir } from '../paths'

const spyModulePath = resolve(distDir, 'spy.js')
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/runtime/runners/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { VitestRunner, VitestRunnerConstructor } from '@vitest/runner'
import type { SerializedConfig } from '../config'
import type { VitestExecutor } from '../execute'
import { resolve } from 'pathe'
import { resolve } from 'node:path'
import { takeCoverageInsideWorker } from '../../integrations/coverage'
import { distDir } from '../../paths'
import { rpc } from '../rpc'
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/benchmark/test/reporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { runVitest } from '../../test-utils'
it('summary', async () => {
const root = pathe.join(import.meta.dirname, '../fixtures/reporter')
const result = await runVitest({ root }, ['summary.bench.ts'], 'benchmark')
expect(result.stderr).toBe('')
expect(result.stdout).not.toContain('NaNx')
expect(result.stdout.split('BENCH Summary')[1].replaceAll(/[0-9.]+x/g, '(?)')).toMatchSnapshot()
})
Expand Down
5 changes: 5 additions & 0 deletions test/cli/fixtures/windows-drive-case/basic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { expect, test } from 'vitest'

test('basic test', () => {
expect(1).toBe(1)
})
13 changes: 7 additions & 6 deletions test/cli/test/public-api.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { File, TaskResultPack, UserConfig } from 'vitest'
import type { RunnerTaskResultPack, RunnerTestFile } from 'vitest'
import type { UserConfig } from 'vitest/node'
import { resolve } from 'pathe'
import { expect, it } from 'vitest'
import { runVitest } from '../../test-utils'
Expand All @@ -15,15 +16,15 @@ it.each([
headless: true,
},
},
] as UserConfig[])('passes down metadata when $name', { timeout: 60_000, retry: 3 }, async (config) => {
const taskUpdate: TaskResultPack[] = []
const finishedFiles: File[] = []
const collectedFiles: File[] = []
] as UserConfig[])('passes down metadata when $name', { timeout: 60_000, retry: 1 }, async (config) => {
const taskUpdate: RunnerTaskResultPack[] = []
const finishedFiles: RunnerTestFile[] = []
const collectedFiles: RunnerTestFile[] = []
const { ctx, stdout, stderr } = await runVitest({
root: resolve(__dirname, '..', 'fixtures', 'public-api'),
include: ['**/*.spec.ts'],
reporters: [
'verbose',
['verbose', { isTTY: false }],
{
onTaskUpdate(packs) {
taskUpdate.push(...packs.filter(i => i[1]?.state === 'pass'))
Expand Down
19 changes: 19 additions & 0 deletions test/cli/test/windows-drive-case.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { join } from 'pathe'
import { expect, test } from 'vitest'
import { runVitestCli } from '../../test-utils'

const _DRIVE_LETTER_START_RE = /^[A-Z]:\//i
const root = join(import.meta.dirname, '../fixtures/windows-drive-case')
const cwd = root.replace(_DRIVE_LETTER_START_RE, r => r.toLowerCase())

test.runIf(process.platform === 'win32')(`works on windows with a lowercase drive: ${cwd}`, async () => {
const { stderr, stdout } = await runVitestCli({
nodeOptions: {
cwd,
},
}, '--no-watch')

expect(cwd[0]).toEqual(cwd[0].toLowerCase())
expect(stderr).toBe('')
expect(stdout).toContain('1 passed')
})

0 comments on commit df6d750

Please sign in to comment.