diff --git a/docs/api/index.md b/docs/api/index.md
index 7e2576977298..ee69e878d9ce 100644
--- a/docs/api/index.md
+++ b/docs/api/index.md
@@ -940,7 +940,7 @@ These hooks will throw an error if they are called outside of the test body.
This hook is always called after the test has finished running. It is called after `afterEach` hooks since they can influence the test result. It receives a `TaskResult` object with the current test result.
-```ts
+```ts {1,5}
import { onTestFinished, test } from 'vitest'
test('performs a query', () => {
@@ -953,12 +953,12 @@ test('performs a query', () => {
::: warning
If you are running tests concurrently, you should always use `onTestFinished` hook from the test context since Vitest doesn't track concurrent tests in global hooks:
-```ts
+```ts {3,5}
import { test } from 'vitest'
-test.concurrent('performs a query', (t) => {
+test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb()
- t.onTestFinished(() => db.close())
+ onTestFinished(() => db.close())
db.query('SELECT * FROM users')
})
```
@@ -993,7 +993,7 @@ test('performs an organization query', async () => {
This hook is called only after the test has failed. It is called after `afterEach` hooks since they can influence the test result. It receives a `TaskResult` object with the current test result. This hook is useful for debugging.
-```ts
+```ts {1,5-7}
import { onTestFailed, test } from 'vitest'
test('performs a query', () => {
@@ -1008,10 +1008,10 @@ test('performs a query', () => {
::: warning
If you are running tests concurrently, you should always use `onTestFailed` hook from the test context since Vitest doesn't track concurrent tests in global hooks:
-```ts
+```ts {3,5-7}
import { test } from 'vitest'
-test.concurrent('performs a query', (t) => {
+test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb()
onTestFailed((result) => {
console.log(result.errors)
diff --git a/docs/config/index.md b/docs/config/index.md
index c7ab349fd30a..c0d73e06e1ae 100644
--- a/docs/config/index.md
+++ b/docs/config/index.md
@@ -1736,18 +1736,10 @@ Test above this limit will be queued to run when available slot appears.
### cache
-- **Type**: `false | { dir? }`
+- **Type**: `false`
- **CLI**: `--no-cache`, `--cache=false`
-Options to configure Vitest cache policy. At the moment Vitest stores cache for test results to run the longer and failed tests first.
-
-#### cache.dir
-
-- **Type**: `string`
-- **Default**: `node_modules/.vitest`
-- **CLI**: `--cache.dir=./cache`
-
-Path to cache directory.
+Use this option if you want to disable the cache feature. At the moment Vitest stores cache for test results to run the longer and failed tests first.
### sequence
@@ -1964,7 +1956,7 @@ Retry the test specific number of times if it fails.
### onConsoleLog
-- **Type**: `(log: string, type: 'stdout' | 'stderr') => false | void`
+- **Type**: `(log: string, type: 'stdout' | 'stderr') => boolean | void`
Custom handler for `console.log` in tests. If you return `false`, Vitest will not print the log to the console.
@@ -1975,9 +1967,8 @@ import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
- onConsoleLog(log: string, type: 'stdout' | 'stderr'): false | void {
- if (log === 'message from third party library' && type === 'stdout')
- return false
+ onConsoleLog(log: string, type: 'stdout' | 'stderr'): boolean | void {
+ return !(log === 'message from third party library' && type === 'stdout')
},
},
})
diff --git a/examples/playwright/test/basic.test.ts b/examples/playwright/test/basic.test.ts
index 44cee93046d7..4c6631c55b81 100644
--- a/examples/playwright/test/basic.test.ts
+++ b/examples/playwright/test/basic.test.ts
@@ -20,9 +20,10 @@ describe.runIf(process.platform !== 'win32')('basic', async () => {
})
afterAll(async () => {
- await browser.close()
+ // hook timed out and we already have another error
+ await browser?.close()
await new Promise((resolve, reject) => {
- server.httpServer.close(error => error ? reject(error) : resolve())
+ server?.httpServer.close(error => error ? reject(error) : resolve())
})
})
diff --git a/package.json b/package.json
index 7ad6f1127b27..a2f527c5c5ab 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/monorepo",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"private": true,
"packageManager": "pnpm@8.10.3",
"description": "Next generation testing framework powered by Vite",
diff --git a/packages/browser/package.json b/packages/browser/package.json
index 50bd9fe486c9..e645b755552a 100644
--- a/packages/browser/package.json
+++ b/packages/browser/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/browser",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Browser running for Vitest",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/browser/src/client/runner.ts b/packages/browser/src/client/runner.ts
index 1725b93883d2..f316715a541d 100644
--- a/packages/browser/src/client/runner.ts
+++ b/packages/browser/src/client/runner.ts
@@ -127,7 +127,7 @@ async function updateFilesLocations(files: File[]) {
if (task.location) {
const { line, column } = originalPositionFor(traceMap, task.location)
if (line != null && column != null)
- task.location = { line, column: column + 1 }
+ task.location = { line, column: task.each ? column : column + 1 }
}
if ('tasks' in task)
task.tasks.forEach(updateLocation)
diff --git a/packages/coverage-istanbul/package.json b/packages/coverage-istanbul/package.json
index c0887f07f678..df6732f1a85b 100644
--- a/packages/coverage-istanbul/package.json
+++ b/packages/coverage-istanbul/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/coverage-istanbul",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Istanbul coverage provider for Vitest",
"author": "Anthony Fu ",
"license": "MIT",
diff --git a/packages/coverage-v8/package.json b/packages/coverage-v8/package.json
index d01b01765276..33cf11cae857 100644
--- a/packages/coverage-v8/package.json
+++ b/packages/coverage-v8/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/coverage-v8",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "V8 coverage provider for Vitest",
"author": "Anthony Fu ",
"license": "MIT",
diff --git a/packages/expect/package.json b/packages/expect/package.json
index 7557cf28aa2d..cd29c7bd7c73 100644
--- a/packages/expect/package.json
+++ b/packages/expect/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/expect",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Jest's expect matchers as a Chai plugin",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/runner/package.json b/packages/runner/package.json
index c35d6b56d047..ca6e0e7f40ea 100644
--- a/packages/runner/package.json
+++ b/packages/runner/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/runner",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Vitest test runner",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/runner/src/suite.ts b/packages/runner/src/suite.ts
index 0f5feb6b787d..b1761b5c20fc 100644
--- a/packages/runner/src/suite.ts
+++ b/packages/runner/src/suite.ts
@@ -153,7 +153,7 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
Error.stackTraceLimit = 10
const error = new Error('stacktrace').stack!
Error.stackTraceLimit = limit
- const stack = findStackTrace(error)
+ const stack = findStackTrace(error, task.each ?? false)
if (stack)
task.location = stack
}
@@ -226,7 +226,9 @@ function createSuiteCollector(name: string, factory: SuiteFactory = () => { }, m
if (stack) {
suite.location = {
line: stack.line,
- column: stack.column,
+ // because source map is boundary based, this line leads to ")" in test.each()[(]),
+ // but it should be the next opening bracket - here we assume it's on the same line
+ column: each ? stack.column + 1 : stack.column,
}
}
}
@@ -430,7 +432,7 @@ function formatTemplateString(cases: any[], args: any[]): any[] {
return res
}
-function findStackTrace(error: string) {
+function findStackTrace(error: string, each: boolean) {
// first line is the error message
// and the first 3 stacks are always from the collector
const lines = error.split('\n').slice(4)
@@ -439,7 +441,13 @@ function findStackTrace(error: string) {
if (stack && stack.file === getTestFilepath()) {
return {
line: stack.line,
- column: stack.column,
+ /**
+ * test.each([1, 2])('name')
+ * ^ leads here, but should
+ * ^ lead here
+ * in source maps it's the same boundary, so it just points to the start of it
+ */
+ column: each ? stack.column + 1 : stack.column,
}
}
}
diff --git a/packages/snapshot/package.json b/packages/snapshot/package.json
index d5d49f769722..5c7eff4acf75 100644
--- a/packages/snapshot/package.json
+++ b/packages/snapshot/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/snapshot",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Vitest snapshot manager",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/spy/package.json b/packages/spy/package.json
index 90e61ed1a47b..29d66681d392 100644
--- a/packages/spy/package.json
+++ b/packages/spy/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/spy",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Lightweight Jest compatible spy implementation",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 7f03bae2ae92..191131452671 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/ui",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "UI for Vitest",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/utils/package.json b/packages/utils/package.json
index e2876799baa8..cc5cc8d38698 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/utils",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Shared Vitest utility functions",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/vite-node/package.json b/packages/vite-node/package.json
index 7ad8e7725d85..75503d358839 100644
--- a/packages/vite-node/package.json
+++ b/packages/vite-node/package.json
@@ -1,7 +1,7 @@
{
"name": "vite-node",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Vite as Node.js runtime",
"author": "Anthony Fu ",
"license": "MIT",
diff --git a/packages/vitest/package.json b/packages/vitest/package.json
index 886cc1966ec0..c41c7faa182c 100644
--- a/packages/vitest/package.json
+++ b/packages/vitest/package.json
@@ -1,7 +1,7 @@
{
"name": "vitest",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Next generation testing framework powered by Vite",
"author": "Anthony Fu ",
"license": "MIT",
diff --git a/packages/vitest/src/api/setup.ts b/packages/vitest/src/api/setup.ts
index 754406300697..f236f08816e0 100644
--- a/packages/vitest/src/api/setup.ts
+++ b/packages/vitest/src/api/setup.ts
@@ -200,7 +200,7 @@ export class WebSocketReporter implements Reporter {
if (this.clients.size === 0)
return
this.clients.forEach((client) => {
- client.onCollected?.(files).catch(noop)
+ client.onCollected?.(files)?.catch?.(noop)
})
}
@@ -222,25 +222,25 @@ export class WebSocketReporter implements Reporter {
})
this.clients.forEach((client) => {
- client.onTaskUpdate?.(packs).catch(noop)
+ client.onTaskUpdate?.(packs)?.catch?.(noop)
})
}
onFinished(files?: File[], errors?: unknown[]) {
this.clients.forEach((client) => {
- client.onFinished?.(files, errors).catch(noop)
+ client.onFinished?.(files, errors)?.catch?.(noop)
})
}
onFinishedReportCoverage() {
this.clients.forEach((client) => {
- client.onFinishedReportCoverage?.().catch(noop)
+ client.onFinishedReportCoverage?.()?.catch?.(noop)
})
}
onUserConsoleLog(log: UserConsoleLog) {
this.clients.forEach((client) => {
- client.onUserConsoleLog?.(log).catch(noop)
+ client.onUserConsoleLog?.(log)?.catch?.(noop)
})
}
}
diff --git a/packages/vitest/src/node/cache/index.ts b/packages/vitest/src/node/cache/index.ts
index 6783736ba23a..209722e78862 100644
--- a/packages/vitest/src/node/cache/index.ts
+++ b/packages/vitest/src/node/cache/index.ts
@@ -21,8 +21,8 @@ export class VitestCache {
return this.stats.getStats(key)
}
- static resolveCacheDir(root: string, dir: string | undefined, projectName: string | undefined) {
- const baseDir = slash(dir || 'node_modules/.vitest')
+ static resolveCacheDir(root: string, dir?: string, projectName?: string) {
+ const baseDir = slash(dir || 'node_modules/.vite/vitest')
return projectName
? resolve(root, baseDir, crypto.createHash('md5').update(projectName, 'utf-8').digest('hex'))
: resolve(root, baseDir)
diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts
index 622fb13f50a7..b5e16b9f526c 100644
--- a/packages/vitest/src/node/cli/cli-config.ts
+++ b/packages/vitest/src/node/cli/cli-config.ts
@@ -549,14 +549,13 @@ export const cliOptionsConfig: VitestCLIOptions = {
description: 'Enable cache',
argument: '', // allow only boolean
subcommands: {
- dir: {
- description: 'Path to the cache directory',
- argument: '',
- normalize: true,
- },
+ dir: null,
},
+ default: true,
// cache can only be "false" or an object
transform(cache) {
+ if (typeof cache !== 'boolean' && cache)
+ throw new Error('--cache.dir is deprecated')
if (cache)
return {}
return cache
diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config.ts
index a6d3b3810a85..9d1c96a18fa3 100644
--- a/packages/vitest/src/node/config.ts
+++ b/packages/vitest/src/node/config.ts
@@ -446,9 +446,21 @@ export function resolveConfig(
resolved.css.modules.classNameStrategy ??= 'stable'
}
- resolved.cache ??= { dir: '' }
- if (resolved.cache)
- resolved.cache.dir = VitestCache.resolveCacheDir(resolved.root, resolved.cache.dir, resolved.name)
+ if (resolved.cache !== false) {
+ let cacheDir = VitestCache.resolveCacheDir('', resolve(viteConfig.cacheDir, 'vitest'), resolved.name)
+
+ if (resolved.cache && resolved.cache.dir) {
+ console.warn(
+ c.yellow(
+ `${c.inverse(c.yellow(' Vitest '))} "cache.dir" is deprecated, use Vite's "cacheDir" instead if you want to change the cache director. Note caches will be written to "cacheDir\/vitest"`,
+ ),
+ )
+
+ cacheDir = VitestCache.resolveCacheDir(resolved.root, resolved.cache.dir, resolved.name)
+ }
+
+ resolved.cache = { dir: cacheDir }
+ }
resolved.sequence ??= {} as any
if (resolved.sequence.shuffle && typeof resolved.sequence.shuffle === 'object') {
diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts
index a2d3d3154a2a..18146a0c1e4f 100644
--- a/packages/vitest/src/node/core.ts
+++ b/packages/vitest/src/node/core.ts
@@ -13,7 +13,6 @@ import type { defineWorkspace } from 'vitest/config'
import type { ArgumentsType, CoverageProvider, OnServerRestartHandler, Reporter, ResolvedConfig, UserConfig, UserWorkspaceConfig, VitestRunMode } from '../types'
import { hasFailed, noop, slash, toArray, wildcardPatternToRegExp } from '../utils'
import { getCoverageProvider } from '../integrations/coverage'
-import type { BrowserProvider } from '../types/browser'
import { CONFIG_NAMES, configFiles, workspacesFiles as workspaceFiles } from '../constants'
import { rootDir } from '../paths'
import { WebSocketReporter } from '../api/setup'
@@ -43,7 +42,6 @@ export class Vitest {
cache: VitestCache = undefined!
reporters: Reporter[] = undefined!
coverageProvider: CoverageProvider | null | undefined
- browserProvider: BrowserProvider | undefined
logger: Logger
pool: ProcessPool | undefined
@@ -51,6 +49,7 @@ export class Vitest {
invalidates: Set = new Set()
changedTests: Set = new Set()
+ watchedTests: Set = new Set()
filenamePattern?: string
runningPromise?: Promise
closingPromise?: Promise
@@ -623,6 +622,14 @@ export class Vitest {
return
this._rerunTimer = setTimeout(async () => {
+ // run only watched tests
+ if (this.watchedTests.size) {
+ this.changedTests.forEach((test) => {
+ if (!this.watchedTests.has(test))
+ this.changedTests.delete(test)
+ })
+ }
+
if (this.changedTests.size === 0) {
this.invalidates.clear()
return
@@ -665,6 +672,15 @@ export class Vitest {
})
}
+ /**
+ * Watch only the specified tests. If no tests are provided, all tests will be watched.
+ */
+ public watchTests(tests: string[]) {
+ this.watchedTests = new Set(
+ tests.map(test => slash(test)),
+ )
+ }
+
private unregisterWatcher = noop
private registerWatcher() {
const updateLastChanged = (filepath: string) => {
diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts
index 09969d21f1bf..c0b1d9b237b0 100644
--- a/packages/vitest/src/node/plugins/index.ts
+++ b/packages/vitest/src/node/plugins/index.ts
@@ -45,8 +45,8 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t
const testConfig = deepMerge(
{} as UserConfig,
configDefaults,
- options,
removeUndefinedValues(viteConfig.test ?? {}),
+ options,
)
testConfig.api = resolveApiServerConfig(testConfig)
diff --git a/packages/vitest/src/runtime/console.ts b/packages/vitest/src/runtime/console.ts
index 45f8a7b20718..14ea15532325 100644
--- a/packages/vitest/src/runtime/console.ts
+++ b/packages/vitest/src/runtime/console.ts
@@ -85,7 +85,7 @@ export function createCustomConsole(state: WorkerGlobalState) {
const stdout = new Writable({
write(data, encoding, callback) {
- const id = state?.current?.id ?? getTaskIdByStack(state.ctx.config.root)
+ const id = state?.current?.id || state?.current?.file?.id || getTaskIdByStack(state.ctx.config.root)
let timer = timers.get(id)
if (timer) {
timer.stdoutTime = timer.stdoutTime || RealDate.now()
@@ -106,7 +106,7 @@ export function createCustomConsole(state: WorkerGlobalState) {
})
const stderr = new Writable({
write(data, encoding, callback) {
- const id = state?.current?.id ?? getTaskIdByStack(state.ctx.config.root)
+ const id = state?.current?.id || state?.current?.file?.id || getTaskIdByStack(state.ctx.config.root)
let timer = timers.get(id)
if (timer) {
timer.stderrTime = timer.stderrTime || RealDate.now()
diff --git a/packages/vitest/src/runtime/runners/test.ts b/packages/vitest/src/runtime/runners/test.ts
index c79231941708..e567506e75fc 100644
--- a/packages/vitest/src/runtime/runners/test.ts
+++ b/packages/vitest/src/runtime/runners/test.ts
@@ -27,6 +27,10 @@ export class VitestTestRunner implements VitestRunner {
this.snapshotClient.clear()
}
+ onAfterRunFiles() {
+ this.workerState.current = undefined
+ }
+
async onAfterRunSuite(suite: Suite) {
if (this.config.logHeapUsage && typeof process !== 'undefined')
suite.result!.heap = process.memoryUsage().heapUsed
@@ -44,6 +48,8 @@ export class VitestTestRunner implements VitestRunner {
if (result)
await rpc().snapshotSaved(result)
}
+
+ this.workerState.current = suite.suite
}
onAfterRunTask(test: Task) {
@@ -52,7 +58,7 @@ export class VitestTestRunner implements VitestRunner {
if (this.config.logHeapUsage && typeof process !== 'undefined')
test.result!.heap = process.memoryUsage().heapUsed
- this.workerState.current = undefined
+ this.workerState.current = test.suite
}
onCancel(_reason: CancelReason) {
@@ -81,6 +87,8 @@ export class VitestTestRunner implements VitestRunner {
// (e.g. `toMatchSnapshot`) specifies "filepath" / "name" pair explicitly
await this.snapshotClient.startCurrentRun(suite.filepath, '__default_name_', this.workerState.config.snapshotOptions)
}
+
+ this.workerState.current = suite
}
onBeforeTryTask(test: Task) {
diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts
index 3dc2d42ef633..f75c660558c1 100644
--- a/packages/vitest/src/types/config.ts
+++ b/packages/vitest/src/types/config.ts
@@ -624,10 +624,13 @@ export interface InlineConfig {
/**
* Options for configuring cache policy.
- * @default { dir: 'node_modules/.vitest' }
+ * @default { dir: 'node_modules/.vite/vitest' }
*/
cache?: false | {
- dir?: string
+ /**
+ * @deprecated Use Vite's "cacheDir" instead if you want to change the cache director. Note caches will be written to "cacheDir\/vitest".
+ */
+ dir: string
}
/**
@@ -854,6 +857,9 @@ export interface ResolvedConfig extends Omit, 'config' | 'f
}
cache: {
+ /**
+ * @deprecated
+ */
dir: string
} | false
diff --git a/packages/web-worker/package.json b/packages/web-worker/package.json
index 930586920df9..dae5b31f084a 100644
--- a/packages/web-worker/package.json
+++ b/packages/web-worker/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/web-worker",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "Web Worker support for testing in Vitest",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
diff --git a/packages/ws-client/package.json b/packages/ws-client/package.json
index 67782a4a93b0..05ffc7751cae 100644
--- a/packages/ws-client/package.json
+++ b/packages/ws-client/package.json
@@ -1,7 +1,7 @@
{
"name": "@vitest/ws-client",
"type": "module",
- "version": "1.3.1",
+ "version": "1.4.0",
"description": "WebSocket client wrapper for communicating with Vitest",
"author": "Anthony Fu ",
"license": "MIT",
diff --git a/test/config/fixtures/cache/basic.test.ts b/test/config/fixtures/cache/basic.test.ts
new file mode 100644
index 000000000000..36c7cc207dde
--- /dev/null
+++ b/test/config/fixtures/cache/basic.test.ts
@@ -0,0 +1,5 @@
+import { expect, test } from "vitest";
+
+test('', () => {
+ expect(true).toBe(true)
+})
diff --git a/test/config/test/cache.test.ts b/test/config/test/cache.test.ts
new file mode 100644
index 000000000000..379ddbc93d38
--- /dev/null
+++ b/test/config/test/cache.test.ts
@@ -0,0 +1,123 @@
+import { describe, expect, test } from 'vitest'
+import { resolve } from 'pathe'
+import { runVitest } from '../../test-utils'
+
+const root = resolve(__dirname, '../fixtures/cache')
+const project = resolve(__dirname, '../')
+
+test('default', async () => {
+ const { vitest, stdout, stderr } = await runVitest({
+ root,
+ include: ['*.test.ts'],
+ })
+
+ expect(stdout).toContain('✓ basic.test.ts >')
+ expect(stderr).toBe('')
+
+ const cachePath = vitest!.cache.results.getCachePath()
+ const path = resolve(project, 'node_modules/.vite/vitest/results.json')
+ expect(cachePath).toMatch(path)
+})
+
+test('use cache.dir', async () => {
+ const { vitest, stdout, stderr } = await runVitest(
+ {
+ root,
+ include: ['*.test.ts'],
+ cache: {
+ dir: 'node_modules/.vitest-custom',
+ },
+ },
+ )
+
+ expect(stdout).toContain('✓ basic.test.ts >')
+ expect(stderr).toContain('"cache.dir" is deprecated')
+
+ const cachePath = vitest!.cache.results.getCachePath()
+ const path = resolve(root, 'node_modules/.vitest-custom/results.json')
+ expect(cachePath).toMatch(path)
+})
+
+test('use cacheDir', async () => {
+ const { vitest, stdout, stderr } = await runVitest(
+ {
+ root,
+ include: ['*.test.ts'],
+ },
+ [],
+ 'test',
+ { cacheDir: 'node_modules/.vite-custom' },
+ )
+
+ expect(stdout).toContain('✓ basic.test.ts >')
+ expect(stderr).toBe('')
+
+ const cachePath = vitest!.cache.results.getCachePath()
+ const path = resolve(root, 'node_modules/.vite-custom/vitest/results.json')
+ expect(cachePath).toMatch(path)
+})
+
+describe('with optimizer enabled', () => {
+ const deps = {
+ optimizer: {
+ web: {
+ enabled: true,
+ },
+ },
+ }
+
+ test('default', async () => {
+ const { vitest, stdout, stderr } = await runVitest({
+ root,
+ include: ['*.test.ts'],
+ deps,
+ })
+
+ expect(stdout).toContain('✓ basic.test.ts >')
+ expect(stderr).toBe('')
+
+ const cachePath = vitest!.cache.results.getCachePath()
+ const path = resolve(project, 'node_modules/.vite/vitest/results.json')
+ expect(cachePath).toBe(path)
+ })
+
+ test('use cache.dir', async () => {
+ const { vitest, stdout, stderr } = await runVitest(
+ {
+ root,
+ include: ['*.test.ts'],
+ deps,
+ cache: {
+ dir: 'node_modules/.vitest-custom',
+ },
+ },
+ )
+
+ expect(stdout).toContain('✓ basic.test.ts >')
+ expect(stderr).toContain('"cache.dir" is deprecated')
+
+ const cachePath = vitest!.cache.results.getCachePath()
+ const path = resolve(root, 'node_modules/.vitest-custom/results.json')
+ expect(cachePath).toBe(path)
+ })
+
+ test('use cacheDir', async () => {
+ const { vitest, stdout, stderr } = await runVitest(
+ {
+ root,
+ include: ['*.test.ts'],
+ deps,
+ },
+ [],
+ 'test',
+ { cacheDir: 'node_modules/.vite-custom' },
+ )
+
+ expect(stdout).toContain('✓ basic.test.ts >')
+ expect(stderr).toBe('')
+
+ const cachePath = vitest!.cache.results.getCachePath()
+ const path = resolve(root, 'node_modules/.vite-custom/vitest/results.json')
+ expect(cachePath).toBe(path)
+ })
+})
diff --git a/test/config/test/resolution.test.ts b/test/config/test/resolution.test.ts
index 63d6009dbfc3..f36b522e5831 100644
--- a/test/config/test/resolution.test.ts
+++ b/test/config/test/resolution.test.ts
@@ -235,3 +235,31 @@ describe('correctly defines inline and noExternal flags', async () => {
])
})
})
+
+describe('correctly defines api flag', () => {
+ it('CLI overrides disabling api', async () => {
+ const c = await vitest({ api: false }, {
+ api: {
+ port: 1234,
+ },
+ watch: true,
+ })
+ expect(c.server.config.server.middlewareMode).toBe(true)
+ expect(c.config.api).toEqual({
+ middlewareMode: true,
+ })
+ })
+
+ it('CLI overrides inlined value', async () => {
+ const c = await vitest({ api: { port: 4321 } }, {
+ api: {
+ port: 1234,
+ },
+ watch: true,
+ })
+ expect(c.server.config.server.port).toBe(4321)
+ expect(c.config.api).toEqual({
+ port: 4321,
+ })
+ })
+})
diff --git a/test/core/test/cli-test.test.ts b/test/core/test/cli-test.test.ts
index 90f5123799d4..1d4a3ce636cf 100644
--- a/test/core/test/cli-test.test.ts
+++ b/test/core/test/cli-test.test.ts
@@ -213,16 +213,7 @@ test('maxConcurrency is parsed correctly', () => {
test('cache is parsed correctly', () => {
expect(getCLIOptions('--cache')).toEqual({ cache: {} })
expect(getCLIOptions('--no-cache')).toEqual({ cache: false })
-
- expect(getCLIOptions('--cache.dir=./test/cache.json')).toEqual({
- cache: { dir: 'test/cache.json' },
- })
- expect(getCLIOptions('--cache.dir ./test/cache.json')).toEqual({
- cache: { dir: 'test/cache.json' },
- })
- expect(getCLIOptions('--cache.dir .\\test\\cache.json')).toEqual({
- cache: { dir: 'test/cache.json' },
- })
+ expect(() => getCLIOptions('--cache.dir=./cache')).toThrowError('--cache.dir is deprecated')
})
test('shuffle is parsed correctly', () => {
diff --git a/test/optimize-deps/test/ssr.test.ts b/test/optimize-deps/test/ssr.test.ts
index dc59d558b84b..38d519ecad22 100644
--- a/test/optimize-deps/test/ssr.test.ts
+++ b/test/optimize-deps/test/ssr.test.ts
@@ -8,5 +8,5 @@ import { importMetaUrl } from '@vitest/test-dep-url'
// TODO: flaky on Windows
// https://github.com/vitest-dev/vitest/pull/5215#discussion_r1492066033
test.skipIf(process.platform === 'win32')('import.meta.url', () => {
- expect(importMetaUrl).toContain('/node_modules/.vitest/deps_ssr/')
+ expect(importMetaUrl).toContain('/node_modules/.vite/vitest/deps_ssr/')
})
diff --git a/test/optimize-deps/test/web.test.ts b/test/optimize-deps/test/web.test.ts
index 308e7730640f..88af98f6f4af 100644
--- a/test/optimize-deps/test/web.test.ts
+++ b/test/optimize-deps/test/web.test.ts
@@ -6,5 +6,5 @@ import { expect, test } from 'vitest'
import { importMetaUrl } from '@vitest/test-dep-url'
test('import.meta.url', () => {
- expect(importMetaUrl).toContain('/node_modules/.vitest/deps/')
+ expect(importMetaUrl).toContain('/node_modules/.vite/vitest/deps/')
})
diff --git a/test/public-api/fixtures/custom.spec.ts b/test/public-api/fixtures/custom.spec.ts
index 6d604c5b15a4..866ee53f9a0e 100644
--- a/test/public-api/fixtures/custom.spec.ts
+++ b/test/public-api/fixtures/custom.spec.ts
@@ -14,3 +14,7 @@ afterAll((suite) => {
test('custom', ({ task }) => {
task.meta.custom = 'some-custom-hanlder'
})
+
+test.each([1, 2])('custom %s', () => {
+ // support locations
+})
diff --git a/test/public-api/tests/runner.spec.ts b/test/public-api/tests/runner.spec.ts
index e8160d4aa7f9..963c9d06c3fe 100644
--- a/test/public-api/tests/runner.spec.ts
+++ b/test/public-api/tests/runner.spec.ts
@@ -47,7 +47,7 @@ it.each([
const suiteMeta = { done: true }
const testMeta = { custom: 'some-custom-hanlder' }
- expect(taskUpdate).toHaveLength(2)
+ expect(taskUpdate).toHaveLength(4)
expect(finishedFiles).toHaveLength(1)
const files = vitest?.state.getFiles() || []
@@ -87,4 +87,13 @@ it.each([
line: 14,
column: 1,
})
+
+ const eachTests = [1, 2]
+ eachTests.forEach((name, index) => {
+ expect(files[0].tasks[index + 1].name).toBe(`custom ${name}`)
+ expect(files[0].tasks[index + 1].location).toEqual({
+ line: 18,
+ column: 18,
+ })
+ })
})
diff --git a/test/reporters/fixtures/console.test.ts b/test/reporters/fixtures/console.test.ts
new file mode 100644
index 000000000000..dde0264286f0
--- /dev/null
+++ b/test/reporters/fixtures/console.test.ts
@@ -0,0 +1,39 @@
+import { afterAll, beforeAll, describe, expect, test } from 'vitest'
+
+beforeAll(() => {
+ console.log('beforeAll')
+ console.error('beforeAll')
+})
+
+afterAll(() => {
+ console.log('afterAll')
+ console.error('afterAll')
+})
+
+describe('suite', () => {
+ beforeAll(() => {
+ console.log('beforeAll')
+ console.error('beforeAll')
+ })
+
+ afterAll(() => {
+ console.log('afterAll')
+ console.error('afterAll')
+ })
+
+ describe('nested suite', () => {
+ beforeAll(() => {
+ console.log('beforeAll')
+ console.error('beforeAll')
+ })
+
+ afterAll(() => {
+ console.log('afterAll')
+ console.error('afterAll')
+ })
+
+ test('test', () => {
+ expect(true).toBe(true)
+ })
+ })
+})
diff --git a/test/reporters/tests/console.test.ts b/test/reporters/tests/console.test.ts
new file mode 100644
index 000000000000..b84f6e8f968f
--- /dev/null
+++ b/test/reporters/tests/console.test.ts
@@ -0,0 +1,41 @@
+import { resolve } from 'pathe'
+import { expect, test } from 'vitest'
+import { runVitest } from '../../test-utils'
+
+test('should print logs correctly', async () => {
+ const filename = resolve('./fixtures/console.test.ts')
+ const { stdout, stderr } = await runVitest({ root: './fixtures' }, [filename])
+
+ expect(stdout).toBeTruthy()
+ expect(stderr).toBeTruthy()
+
+ expect(stdout).toContain(
+`
+stdout | console.test.ts > suite > nested suite
+beforeAll
+afterAll
+
+stdout | console.test.ts > suite
+beforeAll
+afterAll
+
+stdout | console.test.ts
+beforeAll
+afterAll
+`,
+ )
+
+ expect(stderr).toContain(
+`stderr | console.test.ts > suite > nested suite
+beforeAll
+afterAll
+
+stderr | console.test.ts > suite
+beforeAll
+afterAll
+
+stderr | console.test.ts
+beforeAll
+afterAll`,
+ )
+})
diff --git a/test/ui/fixtures/console.test.ts b/test/ui/fixtures/console.test.ts
index 2550b9a32503..8318c03bd7aa 100644
--- a/test/ui/fixtures/console.test.ts
+++ b/test/ui/fixtures/console.test.ts
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
-import { it } from "vitest";
-import { prettyDOM } from "@testing-library/dom"
+import { afterAll, beforeAll, it, describe, expect } from "vitest";
+import { prettyDOM } from "@testing-library/dom";
// https://github.com/vitest-dev/vitest/issues/2765
it('regexp', () => {
@@ -31,3 +31,42 @@ it('html-pretty', () => {
`.replaceAll(/\n */gm, ""); // strip new liens
console.log(prettyDOM(div))
})
+
+
+beforeAll(() => {
+ console.log('beforeAll')
+ console.error('beforeAll')
+})
+
+afterAll(() => {
+ console.log('afterAll')
+ console.error('afterAll')
+})
+
+describe('suite', () => {
+ beforeAll(() => {
+ console.log('beforeAll')
+ console.error('beforeAll')
+ })
+
+ afterAll(() => {
+ console.log('afterAll')
+ console.error('afterAll')
+ })
+
+ describe('nested suite', () => {
+ beforeAll(() => {
+ console.log('beforeAll')
+ console.error('beforeAll')
+ })
+
+ afterAll(() => {
+ console.log('afterAll')
+ console.error('afterAll')
+ })
+
+ it('test', () => {
+ expect(true).toBe(true)
+ })
+ })
+})
diff --git a/test/ui/test/html-report.spec.ts b/test/ui/test/html-report.spec.ts
index 0fd7530b024d..b7b732460684 100644
--- a/test/ui/test/html-report.spec.ts
+++ b/test/ui/test/html-report.spec.ts
@@ -32,7 +32,7 @@ test.describe('html report', () => {
await page.goto(pageUrl)
// dashbaord
- await expect(page.locator('[aria-labelledby=tests]')).toContainText('5 Pass 1 Fail 6 Total')
+ await expect(page.locator('[aria-labelledby=tests]')).toContainText('6 Pass 1 Fail 7 Total')
// unhandled errors
await expect(page.getByTestId('unhandled-errors')).toContainText(
diff --git a/test/ui/test/ui.spec.ts b/test/ui/test/ui.spec.ts
index a54e1a2c608d..e2703dffed0c 100644
--- a/test/ui/test/ui.spec.ts
+++ b/test/ui/test/ui.spec.ts
@@ -23,7 +23,7 @@ test.describe('ui', () => {
await page.goto(pageUrl)
// dashbaord
- await expect(page.locator('[aria-labelledby=tests]')).toContainText('5 Pass 1 Fail 6 Total')
+ await expect(page.locator('[aria-labelledby=tests]')).toContainText('6 Pass 1 Fail 7 Total')
// unhandled errors
await expect(page.getByTestId('unhandled-errors')).toContainText(
@@ -61,6 +61,9 @@ test.describe('ui', () => {
await page.getByText('fixtures/console.test.ts').click()
await page.getByTestId('btn-console').click()
await page.getByText('/(?\\w)/').click()
+
+ expect(await page.getByText('beforeAll').all()).toHaveLength(6)
+ expect(await page.getByText('afterAll').all()).toHaveLength(6)
})
test('error', async ({ page }) => {