From 583dd8a986c404be45cb701ba5552138a9f958f2 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 3 Jul 2024 17:51:33 +0200 Subject: [PATCH 1/6] feat(vitest)!: add "vitest list" API to print collected tests without running them (#6013) --- docs/advanced/pool.md | 3 + docs/guide/cli.md | 30 +++ packages/browser/src/client/tester/tester.ts | 19 +- packages/browser/src/node/pool.ts | 16 +- packages/browser/src/node/serverTester.ts | 6 +- packages/browser/src/node/state.ts | 3 +- packages/runner/src/index.ts | 2 +- packages/runner/src/run.ts | 11 ++ packages/vitest/LICENSE.md | 21 --- packages/vitest/src/browser.ts | 2 +- packages/vitest/src/node/cli/cac.ts | 55 +++++- packages/vitest/src/node/cli/cli-api.ts | 164 ++++++++++++++--- packages/vitest/src/node/cli/cli-config.ts | 15 +- packages/vitest/src/node/core.ts | 72 ++++++++ packages/vitest/src/node/pool.ts | 16 +- packages/vitest/src/node/pools/forks.ts | 1 + packages/vitest/src/node/pools/threads.ts | 1 + packages/vitest/src/node/pools/typecheck.ts | 27 ++- packages/vitest/src/node/pools/vmForks.ts | 1 + packages/vitest/src/node/pools/vmThreads.ts | 1 + packages/vitest/src/node/workspace.ts | 16 +- packages/vitest/src/runtime/runBaseTests.ts | 10 +- packages/vitest/src/runtime/runVmTests.ts | 10 +- packages/vitest/src/runtime/worker.ts | 16 +- packages/vitest/src/runtime/workers/base.ts | 3 +- packages/vitest/src/runtime/workers/forks.ts | 12 +- .../vitest/src/runtime/workers/threads.ts | 6 +- packages/vitest/src/runtime/workers/types.ts | 1 + packages/vitest/src/runtime/workers/vm.ts | 4 +- .../vitest/src/runtime/workers/vmForks.ts | 12 +- .../vitest/src/runtime/workers/vmThreads.ts | 6 +- packages/vitest/src/typecheck/typechecker.ts | 5 + packages/vitest/src/types/browser.ts | 3 +- packages/vitest/src/types/config.ts | 2 + packages/vitest/src/workers.ts | 2 +- .../fixtures/custom-pool/pool/custom-pool.ts | 3 + test/cli/fixtures/list/basic.test.ts | 21 +++ test/cli/fixtures/list/custom.config.ts | 9 + test/cli/fixtures/list/describe-error.test.ts | 9 + test/cli/fixtures/list/fail.config.ts | 7 + test/cli/fixtures/list/math.test.ts | 9 + .../cli/fixtures/list/top-level-error.test.ts | 1 + test/cli/fixtures/list/vitest.config.ts | 13 ++ test/cli/test/__snapshots__/list.test.ts.snap | 98 ++++++++++ test/cli/test/list.test.ts | 174 ++++++++++++++++++ test/core/package.json | 3 +- test/test-utils/index.ts | 2 +- 47 files changed, 815 insertions(+), 108 deletions(-) create mode 100644 test/cli/fixtures/list/basic.test.ts create mode 100644 test/cli/fixtures/list/custom.config.ts create mode 100644 test/cli/fixtures/list/describe-error.test.ts create mode 100644 test/cli/fixtures/list/fail.config.ts create mode 100644 test/cli/fixtures/list/math.test.ts create mode 100644 test/cli/fixtures/list/top-level-error.test.ts create mode 100644 test/cli/fixtures/list/vitest.config.ts create mode 100644 test/cli/test/__snapshots__/list.test.ts.snap create mode 100644 test/cli/test/list.test.ts diff --git a/docs/advanced/pool.md b/docs/advanced/pool.md index d4f8d9c56..0024e60d2 100644 --- a/docs/advanced/pool.md +++ b/docs/advanced/pool.md @@ -45,6 +45,7 @@ import { ProcessPool, WorkspaceProject } from 'vitest/node' export interface ProcessPool { name: string runTests: (files: [project: WorkspaceProject, testFile: string][], invalidates?: string[]) => Promise + collectTests: (files: [project: WorkspaceProject, testFile: string][], invalidates?: string[]) => Promise close?: () => Promise } ``` @@ -57,6 +58,8 @@ Vitest will wait until `runTests` is executed before finishing a run (i.e., it w If you are using a custom pool, you will have to provide test files and their results yourself - you can reference [`vitest.state`](https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/state.ts) for that (most important are `collectFiles` and `updateTasks`). Vitest uses `startTests` function from `@vitest/runner` package to do that. +Vitest will call `collectTests` if `vitest.collect` is called or `vitest list` is invoked via a CLI command. It works the same way as `runTests`, but you don't have to run test callbacks, only report their tasks by calling `vitest.state.collectFiles(files)`. + To communicate between different processes, you can create methods object using `createMethodsRPC` from `vitest/node`, and use any form of communication that you prefer. For example, to use WebSockets with `birpc` you can write something like this: ```ts diff --git a/docs/guide/cli.md b/docs/guide/cli.md index 0b4807ef5..f6d4270e8 100644 --- a/docs/guide/cli.md +++ b/docs/guide/cli.md @@ -55,6 +55,36 @@ export default { Run only [benchmark](https://vitest.dev/guide/features.html#benchmarking-experimental) tests, which compare performance results. +### `vitest init` + +`vitest init ` can be used to setup project configuration. At the moment, it only supports [`browser`](/guide/browser) value: + +```bash +vitest init browser +``` + +### `vitest list` + +`vitest list` command inherits all `vitest` options to print the list of all matching tests. This command ignores `reporters` option. By default, it will print the names of all tests that matched the file filter and name pattern: + +```shell +vitest list filename.spec.ts -t="some-test" +``` + +```txt +describe > some-test +describe > some-test > test 1 +describe > some-test > test 2 +``` + +You can pass down `--json` flag to print tests in JSON format or save it in a separate file: + +```bash +vitest list filename.spec.ts -t="some-test" --json=./file.json +``` + +If `--json` flag doesn't receive a value, it will output the JSON into stdout. + ## Options diff --git a/packages/browser/src/client/tester/tester.ts b/packages/browser/src/client/tester/tester.ts index 07732a53e..7be42128f 100644 --- a/packages/browser/src/client/tester/tester.ts +++ b/packages/browser/src/client/tester/tester.ts @@ -1,4 +1,4 @@ -import { SpyModule, setupCommonEnv, startTests } from 'vitest/browser' +import { SpyModule, collectTests, setupCommonEnv, startTests } from 'vitest/browser' import { getBrowserState, getConfig, getWorkerState } from '../utils' import { channel, client, onCancel } from '../client' import { setupDialogsSpy } from './dialog' @@ -65,8 +65,6 @@ async function prepareTestEnvironment(files: string[]) { runner, config, state, - setupCommonEnv, - startTests, } } @@ -78,7 +76,7 @@ function done(files: string[]) { }) } -async function runTests(files: string[]) { +async function executeTests(method: 'run' | 'collect', files: string[]) { await client.waitForConnection() debug('client is connected to ws server') @@ -107,7 +105,7 @@ async function runTests(files: string[]) { debug('runner resolved successfully') - const { config, runner, state, setupCommonEnv, startTests } = preparedData + const { config, runner, state } = preparedData state.durations.prepare = performance.now() - state.durations.prepare @@ -116,7 +114,12 @@ async function runTests(files: string[]) { try { await setupCommonEnv(config) for (const file of files) { - await startTests([file], runner) + if (method === 'run') { + await startTests([file], runner) + } + else { + await collectTests([file], runner) + } } } finally { @@ -127,4 +130,6 @@ async function runTests(files: string[]) { } // @ts-expect-error untyped global for internal use -window.__vitest_browser_runner__.runTests = runTests +window.__vitest_browser_runner__.runTests = files => executeTests('run', files) +// @ts-expect-error untyped global for internal use +window.__vitest_browser_runner__.collectTests = files => executeTests('collect', files) diff --git a/packages/browser/src/node/pool.ts b/packages/browser/src/node/pool.ts index e0b6b53a6..e1a0b5ea6 100644 --- a/packages/browser/src/node/pool.ts +++ b/packages/browser/src/node/pool.ts @@ -10,15 +10,16 @@ export function createBrowserPool(ctx: Vitest): ProcessPool { const providers = new Set() const waitForTests = async ( + method: 'run' | 'collect', contextId: string, project: WorkspaceProject, files: string[], ) => { - const context = project.browser!.state.createAsyncContext(contextId, files) + const context = project.browser!.state.createAsyncContext(method, contextId, files) return await context } - const runTests = async (project: WorkspaceProject, files: string[]) => { + const executeTests = async (method: 'run' | 'collect', project: WorkspaceProject, files: string[]) => { ctx.state.clearFiles(project, files) const browser = project.browser! @@ -67,13 +68,13 @@ export function createBrowserPool(ctx: Vitest): ProcessPool { contextId, [...files.map(f => relative(project.config.root, f))].join(', '), ) - const promise = waitForTests(contextId, project, files) + const promise = waitForTests(method, contextId, project, files) promises.push(promise) orchestrator.createTesters(files) } else { const contextId = crypto.randomUUID() - const waitPromise = waitForTests(contextId, project, files) + const waitPromise = waitForTests(method, contextId, project, files) debug?.( 'Opening a new context %s for files: %s', contextId, @@ -91,7 +92,7 @@ export function createBrowserPool(ctx: Vitest): ProcessPool { await Promise.all(promises) } - const runWorkspaceTests = async (specs: [WorkspaceProject, string][]) => { + const runWorkspaceTests = async (method: 'run' | 'collect', specs: [WorkspaceProject, string][]) => { const groupedFiles = new Map() for (const [project, file] of specs) { const files = groupedFiles.get(project) || [] @@ -110,7 +111,7 @@ export function createBrowserPool(ctx: Vitest): ProcessPool { break } - await runTests(project, files) + await executeTests(method, project, files) } } @@ -140,6 +141,7 @@ export function createBrowserPool(ctx: Vitest): ProcessPool { await Promise.all([...providers].map(provider => provider.close())) providers.clear() }, - runTests: runWorkspaceTests, + runTests: files => runWorkspaceTests('run', files), + collectTests: files => runWorkspaceTests('collect', files), } } diff --git a/packages/browser/src/node/serverTester.ts b/packages/browser/src/node/serverTester.ts index 9b1ba337a..d756efa0b 100644 --- a/packages/browser/src/node/serverTester.ts +++ b/packages/browser/src/node/serverTester.ts @@ -29,7 +29,9 @@ export async function resolveTester( ? '__vitest_browser_runner__.files' : JSON.stringify([testFile]) const iframeId = JSON.stringify(testFile) - const files = state.getContext(contextId)?.files ?? [] + const context = state.getContext(contextId) + const files = context?.files ?? [] + const method = context?.method ?? 'run' const injectorJs = typeof server.injectorJs === 'string' ? server.injectorJs @@ -74,7 +76,7 @@ export async function resolveTester( ``, }) } diff --git a/packages/browser/src/node/state.ts b/packages/browser/src/node/state.ts index 9f008a6ff..03d8c8f02 100644 --- a/packages/browser/src/node/state.ts +++ b/packages/browser/src/node/state.ts @@ -14,10 +14,11 @@ export class BrowserServerState implements IBrowserServerState { return this.contexts.get(contextId) } - createAsyncContext(contextId: string, files: string[]): Promise { + createAsyncContext(method: 'run' | 'collect', contextId: string, files: string[]): Promise { const defer = createDefer() this.contexts.set(contextId, { files, + method, resolve: () => { defer.resolve() this.contexts.delete(contextId) diff --git a/packages/runner/src/index.ts b/packages/runner/src/index.ts index 0d8cd9064..56c5cc592 100644 --- a/packages/runner/src/index.ts +++ b/packages/runner/src/index.ts @@ -1,4 +1,4 @@ -export { startTests, updateTask } from './run' +export { startTests, updateTask, collectTests } from './run' export { test, it, diff --git a/packages/runner/src/run.ts b/packages/runner/src/run.ts index 308ef41a7..68b6623c8 100644 --- a/packages/runner/src/run.ts +++ b/packages/runner/src/run.ts @@ -512,3 +512,14 @@ export async function startTests(paths: string[], runner: VitestRunner) { return files } + +async function publicCollect(paths: string[], runner: VitestRunner) { + await runner.onBeforeCollect?.(paths) + + const files = await collectTests(paths, runner) + + await runner.onCollected?.(files) + return files +} + +export { publicCollect as collectTests } diff --git a/packages/vitest/LICENSE.md b/packages/vitest/LICENSE.md index e012ba886..c98f8251b 100644 --- a/packages/vitest/LICENSE.md +++ b/packages/vitest/LICENSE.md @@ -438,27 +438,6 @@ License: MIT By: Mathias Bynens Repository: https://github.com/mathiasbynens/emoji-regex.git -> Copyright Mathias Bynens -> -> Permission is hereby granted, free of charge, to any person obtaining -> a copy of this software and associated documentation files (the -> "Software"), to deal in the Software without restriction, including -> without limitation the rights to use, copy, modify, merge, publish, -> distribute, sublicense, and/or sell copies of the Software, and to -> permit persons to whom the Software is furnished to do so, subject to -> the following conditions: -> -> The above copyright notice and this permission notice shall be -> included in all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------- ## expect-type diff --git a/packages/vitest/src/browser.ts b/packages/vitest/src/browser.ts index e9eb3ea0c..2aedb49fb 100644 --- a/packages/vitest/src/browser.ts +++ b/packages/vitest/src/browser.ts @@ -1,4 +1,4 @@ -export { startTests, processError } from '@vitest/runner' +export { startTests, collectTests, processError } from '@vitest/runner' export { setupCommonEnv, loadDiffConfig, diff --git a/packages/vitest/src/node/cli/cac.ts b/packages/vitest/src/node/cli/cac.ts index 6c11444ce..fe3c61c8f 100644 --- a/packages/vitest/src/node/cli/cac.ts +++ b/packages/vitest/src/node/cli/cac.ts @@ -3,10 +3,10 @@ import cac, { type CAC, type Command } from 'cac' import c from 'picocolors' import { version } from '../../../package.json' with { type: 'json' } import { toArray } from '../../utils/base' -import type { Vitest, VitestRunMode } from '../../types' +import type { VitestRunMode } from '../../types' import type { CliOptions } from './cli-api' import type { CLIOption, CLIOptions as CLIOptionsConfig } from './cli-config' -import { benchCliOptionsConfig, cliOptionsConfig } from './cli-config' +import { benchCliOptionsConfig, cliOptionsConfig, collectCliOptionsConfig } from './cli-config' function addCommand(cli: CAC | Command, name: string, option: CLIOption) { const commandName = option.alias || name @@ -182,6 +182,13 @@ export function createCLI(options: CLIOptions = {}) { .command('init ', undefined, options) .action(init) + addCliOptions( + cli + .command('list [...filters]', undefined, options) + .action((filters, options) => collect('test', filters, options)), + collectCliOptionsConfig, + ) + cli .command('[...filters]', undefined, options) .action((filters, options) => start('test', filters, options)) @@ -249,7 +256,7 @@ function normalizeCliOptions(argv: CliOptions): CliOptions { return argv } -async function start(mode: VitestRunMode, cliFilters: string[], options: CliOptions): Promise { +async function start(mode: VitestRunMode, cliFilters: string[], options: CliOptions): Promise { try { process.title = 'node (vitest)' } @@ -261,7 +268,6 @@ async function start(mode: VitestRunMode, cliFilters: string[], options: CliOpti if (!ctx?.shouldKeepServer()) { await ctx?.exit() } - return ctx } catch (e) { const { divider } = await import('../reporters/renderers/utils') @@ -286,3 +292,44 @@ async function init(project: string) { const { create } = await import('../../create/browser/creator') await create() } + +async function collect(mode: VitestRunMode, cliFilters: string[], options: CliOptions): Promise { + try { + process.title = 'node (vitest)' + } + catch {} + + try { + const { prepareVitest, processCollected } = await import('./cli-api') + const ctx = await prepareVitest(mode, { + ...normalizeCliOptions(options), + watch: false, + run: true, + }) + + const { tests, errors } = await ctx.collect(cliFilters.map(normalize)) + + if (errors.length) { + console.error('\nThere were unhandled errors during test collection') + errors.forEach(e => console.error(e)) + console.error('\n\n') + await ctx.close() + return + } + + processCollected(ctx, tests, options) + await ctx.close() + } + catch (e) { + const { divider } = await import('../reporters/renderers/utils') + console.error(`\n${c.red(divider(c.bold(c.inverse(' Collect Error '))))}`) + console.error(e) + console.error('\n\n') + + if (process.exitCode == null) { + process.exitCode = 1 + } + + process.exit() + } +} diff --git a/packages/vitest/src/node/cli/cli-api.ts b/packages/vitest/src/node/cli/cli-api.ts index 9d255807b..197ae804f 100644 --- a/packages/vitest/src/node/cli/cli-api.ts +++ b/packages/vitest/src/node/cli/cli-api.ts @@ -1,5 +1,9 @@ -import { resolve } from 'pathe' +/* eslint-disable no-console */ + +import { mkdirSync, writeFileSync } from 'node:fs' +import { dirname, resolve } from 'pathe' import type { UserConfig as ViteUserConfig } from 'vite' +import type { File, Suite, Task } from '@vitest/runner' import { CoverageProviderMap } from '../../integrations/coverage' import { getEnvPackageName } from '../../integrations/env' import type { UserConfig, Vitest, VitestRunMode } from '../../types' @@ -7,6 +11,7 @@ import { createVitest } from '../create' import { registerConsoleShortcuts } from '../stdin' import type { VitestOptions } from '../core' import { FilesNotFoundError, GitNotFoundError } from '../errors' +import { getNames, getTests } from '../../utils' export interface CliOptions extends UserConfig { /** @@ -17,6 +22,10 @@ export interface CliOptions extends UserConfig { * Removes colors from the console output */ color?: boolean + /** + * Output collected tests as JSON or to a file + */ + json?: string | boolean } /** @@ -31,27 +40,14 @@ export async function startVitest( viteOverrides?: ViteUserConfig, vitestOptions?: VitestOptions, ): Promise { - process.env.TEST = 'true' - process.env.VITEST = 'true' - process.env.NODE_ENV ??= 'test' - - if (options.run) { - options.watch = false - } - - // this shouldn't affect _application root_ that can be changed inside config const root = resolve(options.root || process.cwd()) - // running "vitest --browser.headless" - if (typeof options.browser === 'object' && !('enabled' in options.browser)) { - options.browser.enabled = true - } - - if (typeof options.typecheck?.only === 'boolean') { - options.typecheck.enabled ??= true - } - - const ctx = await createVitest(mode, options, viteOverrides, vitestOptions) + const ctx = await prepareVitest( + mode, + options, + viteOverrides, + vitestOptions, + ) if (mode === 'test' && ctx.config.coverage.enabled) { const provider = ctx.config.coverage.provider || 'v8' @@ -67,16 +63,6 @@ export async function startVitest( } } - const environmentPackage = getEnvPackageName(ctx.config.environment) - - if ( - environmentPackage - && !(await ctx.packageInstaller.ensureInstalled(environmentPackage, root)) - ) { - process.exitCode = 1 - return ctx - } - const stdin = vitestOptions?.stdin || process.stdin const stdout = vitestOptions?.stdout || process.stdout let stdinCleanup @@ -132,3 +118,121 @@ export async function startVitest( await ctx.close() return ctx } + +export async function prepareVitest( + mode: VitestRunMode, + options: CliOptions = {}, + viteOverrides?: ViteUserConfig, + vitestOptions?: VitestOptions, +): Promise { + process.env.TEST = 'true' + process.env.VITEST = 'true' + process.env.NODE_ENV ??= 'test' + + if (options.run) { + options.watch = false + } + + // this shouldn't affect _application root_ that can be changed inside config + const root = resolve(options.root || process.cwd()) + + // running "vitest --browser.headless" + if (typeof options.browser === 'object' && !('enabled' in options.browser)) { + options.browser.enabled = true + } + + if (typeof options.typecheck?.only === 'boolean') { + options.typecheck.enabled ??= true + } + + const ctx = await createVitest(mode, options, viteOverrides, vitestOptions) + + const environmentPackage = getEnvPackageName(ctx.config.environment) + + if ( + environmentPackage + && !(await ctx.packageInstaller.ensureInstalled(environmentPackage, root)) + ) { + process.exitCode = 1 + return ctx + } + + return ctx +} + +export function processCollected(ctx: Vitest, files: File[], options: CliOptions) { + let errorsPrinted = false + + forEachSuite(files, (suite) => { + const errors = suite.result?.errors || [] + errors.forEach((error) => { + errorsPrinted = true + ctx.logger.printError(error, { + project: ctx.getProjectByName(suite.file.projectName), + }) + }) + }) + + if (errorsPrinted) { + return + } + + if (typeof options.json !== 'undefined') { + return processJsonOutput(files, options) + } + + return formatCollectedAsString(files).forEach(test => console.log(test)) +} + +function processJsonOutput(files: File[], options: CliOptions) { + if (typeof options.json === 'boolean') { + return console.log(JSON.stringify(formatCollectedAsJSON(files), null, 2)) + } + + if (typeof options.json === 'string') { + const jsonPath = resolve(options.root || process.cwd(), options.json) + mkdirSync(dirname(jsonPath), { recursive: true }) + writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2)) + } +} + +function forEachSuite(tasks: Task[], callback: (suite: Suite) => void) { + tasks.forEach((task) => { + if (task.type === 'suite') { + callback(task) + forEachSuite(task.tasks, callback) + } + }) +} + +export function formatCollectedAsJSON(files: File[]) { + return files.map((file) => { + const tests = getTests(file).filter(test => test.mode === 'run' || test.mode === 'only') + return tests.map((test) => { + const result: any = { + name: getNames(test).slice(1).join(' > '), + file: file.filepath, + } + if (test.file.projectName) { + result.projectName = test.file.projectName + } + if (test.location) { + result.location = test.location + } + return result + }) + }).flat() +} + +export function formatCollectedAsString(files: File[]) { + return files.map((file) => { + const tests = getTests(file).filter(test => test.mode === 'run' || test.mode === 'only') + return tests.map((test) => { + const name = getNames(test).join(' > ') + if (test.file.projectName) { + return `[${test.file.projectName}] ${name}` + } + return name + }) + }).flat() +} diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts index c6b28c078..3a9981431 100644 --- a/packages/vitest/src/node/cli/cli-config.ts +++ b/packages/vitest/src/node/cli/cli-config.ts @@ -792,6 +792,7 @@ export const cliOptionsConfig: VitestCLIOptions = { snapshotEnvironment: null, compare: null, outputJson: null, + json: null, } export const benchCliOptionsConfig: Pick< @@ -799,11 +800,21 @@ export const benchCliOptionsConfig: Pick< 'compare' | 'outputJson' > = { compare: { - description: 'benchmark output file to compare against', + description: 'Benchmark output file to compare against', argument: '', }, outputJson: { - description: 'benchmark output file', + description: 'Benchmark output file', argument: '', }, } + +export const collectCliOptionsConfig: Pick< + VitestCLIOptions, + 'json' +> = { + json: { + description: 'Print collected tests as JSON or write to a file (Default: false)', + argument: '[true/path]', + }, +} diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 41ca9c8b7..8d3b88e2d 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -466,6 +466,28 @@ export class Vitest { await this.coverageProvider?.mergeReports?.(coverages) } + async collect(filters?: string[]) { + this._onClose = [] + + await this.initBrowserProviders() + + const files = await this.filterTestsBySource( + await this.globTestFiles(filters), + ) + + // if run with --changed, don't exit if no tests are found + if (!files.length) { + return { tests: [], errors: [] } + } + + await this.collectFiles(files) + + return { + tests: this.state.getFiles(), + errors: this.state.getUnhandledErrors(), + } + } + async start(filters?: string[]) { this._onClose = [] @@ -705,6 +727,56 @@ export class Vitest { return await this.runningPromise } + async collectFiles(specs: WorkspaceSpec[]) { + await this.initializeDistPath() + + const filepaths = specs.map(([, file]) => file) + this.state.collectPaths(filepaths) + + // previous run + await this.runningPromise + this._onCancelListeners = [] + this.isCancelling = false + + // schedule the new run + this.runningPromise = (async () => { + if (!this.pool) { + this.pool = createPool(this) + } + + const invalidates = Array.from(this.invalidates) + this.invalidates.clear() + this.snapshot.clear() + this.state.clearErrors() + + await this.initializeGlobalSetup(specs) + + try { + await this.pool.collectTests(specs, invalidates) + } + catch (err) { + this.state.catchError(err, 'Unhandled Error') + } + + const files = this.state.getFiles() + + // can only happen if there was a syntax error in describe block + // or there was an error importing a file + if (hasFailed(files)) { + process.exitCode = 1 + } + })() + .finally(async () => { + this.runningPromise = undefined + + // all subsequent runs will treat this as a fresh run + this.config.changed = false + this.config.related = undefined + }) + + return await this.runningPromise + } + async cancelCurrentRun(reason: CancelReason) { this.isCancelling = true await Promise.all(this._onCancelListeners.splice(0).map(listener => listener(reason))) diff --git a/packages/vitest/src/node/pool.ts b/packages/vitest/src/node/pool.ts index ef183ef10..5dd244fea 100644 --- a/packages/vitest/src/node/pool.ts +++ b/packages/vitest/src/node/pool.ts @@ -21,6 +21,7 @@ type LocalPool = Exclude export interface ProcessPool { name: string runTests: RunWithFiles + collectTests: RunWithFiles close?: () => Awaitable } @@ -104,7 +105,7 @@ export function createPool(ctx: Vitest): ProcessPool { || execArg.startsWith('--diagnostic-dir'), ) - async function runTests(files: WorkspaceSpec[], invalidate?: string[]) { + async function executeTests(method: 'runTests' | 'collectTests', files: WorkspaceSpec[], invalidate?: string[]) { const options: PoolProcessOptions = { execArgv: [...execArgv, ...conditions], env: { @@ -144,9 +145,9 @@ export function createPool(ctx: Vitest): ProcessPool { `Custom pool "${filepath}" should return an object with "name" property`, ) } - if (typeof poolInstance?.runTests !== 'function') { + if (typeof poolInstance?.[method] !== 'function') { throw new TypeError( - `Custom pool "${filepath}" should return an object with "runTests" method`, + `Custom pool "${filepath}" should return an object with "${method}" method`, ) } @@ -201,7 +202,7 @@ export function createPool(ctx: Vitest): ProcessPool { if (pool in factories) { const factory = factories[pool] pools[pool] ??= factory() - return pools[pool]!.runTests(specs, invalidate) + return pools[pool]![method](specs, invalidate) } if (pool === 'browser') { @@ -209,19 +210,20 @@ export function createPool(ctx: Vitest): ProcessPool { const { createBrowserPool } = await import('@vitest/browser') return createBrowserPool(ctx) })() - return pools[pool]!.runTests(specs, invalidate) + return pools[pool]![method](specs, invalidate) } const poolHandler = await resolveCustomPool(pool) pools[poolHandler.name] ??= poolHandler - return poolHandler.runTests(specs, invalidate) + return poolHandler[method](specs, invalidate) }), ) } return { name: 'default', - runTests, + runTests: (files, invalidates) => executeTests('runTests', files, invalidates), + collectTests: (files, invalidates) => executeTests('collectTests', files, invalidates), async close() { await Promise.all(Object.values(pools).map(p => p?.close?.())) }, diff --git a/packages/vitest/src/node/pools/forks.ts b/packages/vitest/src/node/pools/forks.ts index bfc739cc5..5d54d911b 100644 --- a/packages/vitest/src/node/pools/forks.ts +++ b/packages/vitest/src/node/pools/forks.ts @@ -290,6 +290,7 @@ export function createForksPool( return { name: 'forks', runTests: runWithFiles('run'), + collectTests: runWithFiles('collect'), close: () => pool.destroy(), } } diff --git a/packages/vitest/src/node/pools/threads.ts b/packages/vitest/src/node/pools/threads.ts index 38bdec730..0fcf5c02a 100644 --- a/packages/vitest/src/node/pools/threads.ts +++ b/packages/vitest/src/node/pools/threads.ts @@ -286,6 +286,7 @@ export function createThreadsPool( return { name: 'threads', runTests: runWithFiles('run'), + collectTests: runWithFiles('collect'), close: () => pool.destroy(), } } diff --git a/packages/vitest/src/node/pools/typecheck.ts b/packages/vitest/src/node/pools/typecheck.ts index 3c86225e5..a88c29ae5 100644 --- a/packages/vitest/src/node/pools/typecheck.ts +++ b/packages/vitest/src/node/pools/typecheck.ts @@ -87,11 +87,31 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool { }) await checker.prepare() - await checker.collectTests() - checker.start() return checker } + async function startTypechecker(project: WorkspaceProject, files: string[]) { + if (project.typechecker) { + return project.typechecker + } + const checker = await createWorkspaceTypechecker(project, files) + await checker.collectTests() + await checker.start() + } + + async function collectTests(specs: WorkspaceSpec[]) { + const specsByProject = groupBy(specs, ([project]) => project.getName()) + for (const name in specsByProject) { + const project = specsByProject[name][0][0] + const files = specsByProject[name].map(([_, file]) => file) + const checker = await createWorkspaceTypechecker(project, files) + checker.setFiles(files) + await checker.collectTests() + ctx.state.collectFiles(checker.getTestFiles()) + await ctx.report('onCollected') + } + } + async function runTests(specs: WorkspaceSpec[]) { const specsByProject = groupBy(specs, ([project]) => project.getName()) const promises: Promise[] = [] @@ -122,7 +142,7 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool { } promises.push(promise) promisesMap.set(project, promise) - createWorkspaceTypechecker(project, files) + startTypechecker(project, files) } await Promise.all(promises) @@ -131,6 +151,7 @@ export function createTypecheckPool(ctx: Vitest): ProcessPool { return { name: 'typescript', runTests, + collectTests, async close() { const promises = ctx.projects.map(project => project.typechecker?.stop(), diff --git a/packages/vitest/src/node/pools/vmForks.ts b/packages/vitest/src/node/pools/vmForks.ts index 5c55a3181..c34bdb990 100644 --- a/packages/vitest/src/node/pools/vmForks.ts +++ b/packages/vitest/src/node/pools/vmForks.ts @@ -208,6 +208,7 @@ export function createVmForksPool( return { name: 'vmForks', runTests: runWithFiles('run'), + collectTests: runWithFiles('collect'), close: () => pool.destroy(), } } diff --git a/packages/vitest/src/node/pools/vmThreads.ts b/packages/vitest/src/node/pools/vmThreads.ts index 92f982cd7..09654cf2f 100644 --- a/packages/vitest/src/node/pools/vmThreads.ts +++ b/packages/vitest/src/node/pools/vmThreads.ts @@ -200,6 +200,7 @@ export function createVmThreadsPool( return { name: 'vmThreads', runTests: runWithFiles('run'), + collectTests: runWithFiles('collect'), close: () => pool.destroy(), } } diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index e2f5b8002..d5e66e54b 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -407,14 +407,14 @@ export class WorkspaceProject { return isBrowserEnabled(this.config) } - getSerializableConfig() { + getSerializableConfig(method: 'run' | 'collect' = 'run') { const optimizer = this.config.deps?.optimizer const poolOptions = this.config.poolOptions // Resolve from server.config to avoid comparing against default value const isolate = this.server?.config?.test?.isolate - return deepMerge( + const config = deepMerge( { ...this.config, @@ -500,6 +500,18 @@ export class WorkspaceProject { }, this.ctx.configOverride || ({} as any), ) as ResolvedConfig + + // disable heavy features when collecting because they are not needed + if (method === 'collect') { + config.coverage.enabled = false + if (config.browser.provider && config.browser.provider !== 'preview') { + config.browser.headless = true + } + config.snapshotSerializers = [] + config.diff = undefined + } + + return config } close() { diff --git a/packages/vitest/src/runtime/runBaseTests.ts b/packages/vitest/src/runtime/runBaseTests.ts index 2e2acf279..4bcc9c04c 100644 --- a/packages/vitest/src/runtime/runBaseTests.ts +++ b/packages/vitest/src/runtime/runBaseTests.ts @@ -1,5 +1,5 @@ import { performance } from 'node:perf_hooks' -import { startTests } from '@vitest/runner' +import { collectTests, startTests } from '@vitest/runner' import type { ResolvedConfig, ResolvedTestEnvironment } from '../types' import { getWorkerState, resetModules } from '../utils' import { vi } from '../integrations/vi' @@ -15,6 +15,7 @@ import { closeInspector } from './inspector' // browser shouldn't call this! export async function run( + method: 'run' | 'collect', files: string[], config: ResolvedConfig, environment: ResolvedTestEnvironment, @@ -62,7 +63,12 @@ export async function run( workerState.filepath = file - await startTests([file], runner) + if (method === 'run') { + await startTests([file], runner) + } + else { + await collectTests([file], runner) + } // reset after tests, because user might call `vi.setConfig` in setupFile vi.resetConfig() diff --git a/packages/vitest/src/runtime/runVmTests.ts b/packages/vitest/src/runtime/runVmTests.ts index 57a651b4e..a989d7d6f 100644 --- a/packages/vitest/src/runtime/runVmTests.ts +++ b/packages/vitest/src/runtime/runVmTests.ts @@ -3,7 +3,7 @@ import { createRequire } from 'node:module' import util from 'node:util' import timers from 'node:timers' import { performance } from 'node:perf_hooks' -import { startTests } from '@vitest/runner' +import { collectTests, startTests } from '@vitest/runner' import { createColors, setupColors } from '@vitest/utils' import { installSourcemapsSupport } from 'vite-node/source-map' import { setupChaiConfig } from '../integrations/chai/config' @@ -21,6 +21,7 @@ import { setupCommonEnv } from './setup-common' import { closeInspector } from './inspector' export async function run( + method: 'run' | 'collect', files: string[], config: ResolvedConfig, executor: VitestExecutor, @@ -81,7 +82,12 @@ export async function run( for (const file of files) { workerState.filepath = file - await startTests([file], runner) + if (method === 'run') { + await startTests([file], runner) + } + else { + await collectTests([file], runner) + } // reset after tests, because user might call `vi.setConfig` in setupFile vi.resetConfig() diff --git a/packages/vitest/src/runtime/worker.ts b/packages/vitest/src/runtime/worker.ts index f5ce651b3..f55a5b8ad 100644 --- a/packages/vitest/src/runtime/worker.ts +++ b/packages/vitest/src/runtime/worker.ts @@ -13,7 +13,7 @@ if (isChildProcess()) { } // this is what every pool executes when running tests -export async function run(ctx: ContextRPC) { +async function execute(mehtod: 'run' | 'collect', ctx: ContextRPC) { const prepareStart = performance.now() const inspectorCleanup = setupInspect(ctx) @@ -75,16 +75,26 @@ export async function run(ctx: ContextRPC) { providedContext: ctx.providedContext, } - if (!worker.runTests || typeof worker.runTests !== 'function') { + const methodName = mehtod === 'collect' ? 'collectTests' : 'runTests' + + if (!worker[methodName] || typeof worker[methodName] !== 'function') { throw new TypeError( `Test worker should expose "runTests" method. Received "${typeof worker.runTests}".`, ) } - await worker.runTests(state) + await worker[methodName](state) } finally { await rpcDone().catch(() => {}) inspectorCleanup() } } + +export function run(ctx: ContextRPC) { + return execute('run', ctx) +} + +export function collect(ctx: ContextRPC) { + return execute('collect', ctx) +} diff --git a/packages/vitest/src/runtime/workers/base.ts b/packages/vitest/src/runtime/workers/base.ts index a8cdc7562..740f170ef 100644 --- a/packages/vitest/src/runtime/workers/base.ts +++ b/packages/vitest/src/runtime/workers/base.ts @@ -19,7 +19,7 @@ async function startViteNode(options: ContextExecutorOptions) { return _viteNode } -export async function runBaseTests(state: WorkerGlobalState) { +export async function runBaseTests(method: 'run' | 'collect', state: WorkerGlobalState) { const { ctx } = state // state has new context, but we want to reuse existing ones state.moduleCache = moduleCache @@ -40,6 +40,7 @@ export async function runBaseTests(state: WorkerGlobalState) { import('../runBaseTests'), ]) await run( + method, ctx.files, ctx.config, { environment: state.environment, options: ctx.environment.options }, diff --git a/packages/vitest/src/runtime/workers/forks.ts b/packages/vitest/src/runtime/workers/forks.ts index 65b0e9197..5d4e8d564 100644 --- a/packages/vitest/src/runtime/workers/forks.ts +++ b/packages/vitest/src/runtime/workers/forks.ts @@ -9,19 +9,27 @@ class ForksBaseWorker implements VitestWorker { return createForksRpcOptions(v8) } - async runTests(state: WorkerGlobalState) { + async executeTests(method: 'run' | 'collect', state: WorkerGlobalState) { // TODO: don't rely on reassigning process.exit // https://github.com/vitest-dev/vitest/pull/4441#discussion_r1443771486 const exit = process.exit state.ctx.config = unwrapSerializableConfig(state.ctx.config) try { - await runBaseTests(state) + await runBaseTests(method, state) } finally { process.exit = exit } } + + runTests(state: WorkerGlobalState) { + return this.executeTests('run', state) + } + + collectTests(state: WorkerGlobalState) { + return this.executeTests('collect', state) + } } export default new ForksBaseWorker() diff --git a/packages/vitest/src/runtime/workers/threads.ts b/packages/vitest/src/runtime/workers/threads.ts index 38fb1a5ab..77fb7eb96 100644 --- a/packages/vitest/src/runtime/workers/threads.ts +++ b/packages/vitest/src/runtime/workers/threads.ts @@ -10,7 +10,11 @@ class ThreadsBaseWorker implements VitestWorker { } runTests(state: WorkerGlobalState): unknown { - return runBaseTests(state) + return runBaseTests('run', state) + } + + collectTests(state: WorkerGlobalState): unknown { + return runBaseTests('collect', state) } } diff --git a/packages/vitest/src/runtime/workers/types.ts b/packages/vitest/src/runtime/workers/types.ts index 577cbdeb4..0cbdc515d 100644 --- a/packages/vitest/src/runtime/workers/types.ts +++ b/packages/vitest/src/runtime/workers/types.ts @@ -11,4 +11,5 @@ export type WorkerRpcOptions = Pick< export interface VitestWorker { getRpcOptions: (ctx: ContextRPC) => WorkerRpcOptions runTests: (state: WorkerGlobalState) => Awaitable + collectTests: (state: WorkerGlobalState) => Awaitable } diff --git a/packages/vitest/src/runtime/workers/vm.ts b/packages/vitest/src/runtime/workers/vm.ts index 6553e2f8e..ebd9e75f5 100644 --- a/packages/vitest/src/runtime/workers/vm.ts +++ b/packages/vitest/src/runtime/workers/vm.ts @@ -15,7 +15,7 @@ const entryFile = pathToFileURL(resolve(distDir, 'workers/runVmTests.js')).href const fileMap = new FileMap() const packageCache = new Map() -export async function runVmTests(state: WorkerGlobalState) { +export async function runVmTests(method: 'run' | 'collect', state: WorkerGlobalState) { const { environment, ctx, rpc } = state if (!environment.setupVM) { @@ -90,7 +90,7 @@ export async function runVmTests(state: WorkerGlobalState) { )) as typeof import('../runVmTests') try { - await run(ctx.files, ctx.config, executor) + await run(method, ctx.files, ctx.config, executor) } finally { await vm.teardown?.() diff --git a/packages/vitest/src/runtime/workers/vmForks.ts b/packages/vitest/src/runtime/workers/vmForks.ts index 365c76348..d93a9052f 100644 --- a/packages/vitest/src/runtime/workers/vmForks.ts +++ b/packages/vitest/src/runtime/workers/vmForks.ts @@ -9,17 +9,25 @@ class ForksVmWorker implements VitestWorker { return createForksRpcOptions(v8) } - async runTests(state: WorkerGlobalState) { + async executeTests(method: 'run' | 'collect', state: WorkerGlobalState) { const exit = process.exit state.ctx.config = unwrapSerializableConfig(state.ctx.config) try { - await runVmTests(state) + await runVmTests(method, state) } finally { process.exit = exit } } + + runTests(state: WorkerGlobalState) { + return this.executeTests('run', state) + } + + collectTests(state: WorkerGlobalState) { + return this.executeTests('collect', state) + } } export default new ForksVmWorker() diff --git a/packages/vitest/src/runtime/workers/vmThreads.ts b/packages/vitest/src/runtime/workers/vmThreads.ts index 8040b8dfc..3197cd34b 100644 --- a/packages/vitest/src/runtime/workers/vmThreads.ts +++ b/packages/vitest/src/runtime/workers/vmThreads.ts @@ -10,7 +10,11 @@ class ThreadsVmWorker implements VitestWorker { } runTests(state: WorkerGlobalState): unknown { - return runVmTests(state) + return runVmTests('run', state) + } + + collectTests(state: WorkerGlobalState): unknown { + return runVmTests('collect', state) } } diff --git a/packages/vitest/src/typecheck/typechecker.ts b/packages/vitest/src/typecheck/typechecker.ts index d50d239c8..b4bc264d3 100644 --- a/packages/vitest/src/typecheck/typechecker.ts +++ b/packages/vitest/src/typecheck/typechecker.ts @@ -266,6 +266,7 @@ export class Typechecker { public async stop() { await this.clear() this.process?.kill() + this.process = undefined } protected async ensurePackageInstalled(ctx: Vitest, checker: string) { @@ -294,6 +295,10 @@ export class Typechecker { } public async start() { + if (this.process) { + return + } + if (!this.tempConfigPath) { throw new Error('tsconfig was not initialized') } diff --git a/packages/vitest/src/types/browser.ts b/packages/vitest/src/types/browser.ts index a6de0e759..4f8ed9cb8 100644 --- a/packages/vitest/src/types/browser.ts +++ b/packages/vitest/src/types/browser.ts @@ -170,6 +170,7 @@ export interface BrowserCommandContext { export interface BrowserServerStateContext { files: string[] + method: 'run' | 'collect' resolve: () => void reject: (v: unknown) => void } @@ -182,7 +183,7 @@ export interface BrowserOrchestrator { export interface BrowserServerState { orchestrators: Map getContext: (contextId: string) => BrowserServerStateContext | undefined - createAsyncContext: (contextId: string, files: string[]) => Promise + createAsyncContext: (method: 'collect' | 'run', contextId: string, files: string[]) => Promise } export interface BrowserServer { diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts index 6b230a80c..b564e061a 100644 --- a/packages/vitest/src/types/config.ts +++ b/packages/vitest/src/types/config.ts @@ -954,10 +954,12 @@ export interface ResolvedConfig | 'poolOptions' | 'pool' | 'cliExclude' + | 'diff' > { mode: VitestRunMode base?: string + diff?: string config?: string filters?: string[] diff --git a/packages/vitest/src/workers.ts b/packages/vitest/src/workers.ts index 1a6e839c2..5601196ce 100644 --- a/packages/vitest/src/workers.ts +++ b/packages/vitest/src/workers.ts @@ -4,7 +4,7 @@ export { unwrapSerializableConfig, } from './runtime/workers/utils' export { provideWorkerState } from './utils/global' -export { run as runVitestWorker } from './runtime/worker' +export { run as runVitestWorker, collect as collectVitestWorkerTests } from './runtime/worker' export { runVmTests } from './runtime/workers/vm' export { runBaseTests } from './runtime/workers/base' export type { WorkerRpcOptions, VitestWorker } from './runtime/workers/types' diff --git a/test/cli/fixtures/custom-pool/pool/custom-pool.ts b/test/cli/fixtures/custom-pool/pool/custom-pool.ts index eaaf2d54d..5f40830ac 100644 --- a/test/cli/fixtures/custom-pool/pool/custom-pool.ts +++ b/test/cli/fixtures/custom-pool/pool/custom-pool.ts @@ -8,6 +8,9 @@ export default (ctx: Vitest): ProcessPool => { const options = ctx.config.poolOptions?.custom as any return { name: 'custom', + async collectTests() { + throw new Error('Not implemented') + }, async runTests(specs) { ctx.logger.console.warn('[pool] printing:', options.print) ctx.logger.console.warn('[pool] array option', options.array) diff --git a/test/cli/fixtures/list/basic.test.ts b/test/cli/fixtures/list/basic.test.ts new file mode 100644 index 000000000..37f68c1bd --- /dev/null +++ b/test/cli/fixtures/list/basic.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest' + +describe('basic suite', () => { + describe('inner suite', () => { + it('some test', () => { + expect(1).toBe(1) + }) + + it('another test', () => { + expect(1).toBe(1) + }) + }) + + it('basic test', () => { + expect(1).toBe(1) + }) +}) + +it('outside test', () => { + expect(1).toBe(1) +}) diff --git a/test/cli/fixtures/list/custom.config.ts b/test/cli/fixtures/list/custom.config.ts new file mode 100644 index 000000000..841db817e --- /dev/null +++ b/test/cli/fixtures/list/custom.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + include: ['basic.test.ts', 'math.test.ts'], + name: 'custom', + includeTaskLocation: true, + }, +}) diff --git a/test/cli/fixtures/list/describe-error.test.ts b/test/cli/fixtures/list/describe-error.test.ts new file mode 100644 index 000000000..3238cceab --- /dev/null +++ b/test/cli/fixtures/list/describe-error.test.ts @@ -0,0 +1,9 @@ +import { describe, expect, it } from 'vitest'; + +describe('describe error', () => { + throw new Error('describe error') + + it('wont run', () => { + expect(true).toBe(true) + }) +}) \ No newline at end of file diff --git a/test/cli/fixtures/list/fail.config.ts b/test/cli/fixtures/list/fail.config.ts new file mode 100644 index 000000000..16d254a9a --- /dev/null +++ b/test/cli/fixtures/list/fail.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + include: ['top-level-error.test.ts', 'describe-error.test.ts'], + }, +}) diff --git a/test/cli/fixtures/list/math.test.ts b/test/cli/fixtures/list/math.test.ts new file mode 100644 index 000000000..c39601812 --- /dev/null +++ b/test/cli/fixtures/list/math.test.ts @@ -0,0 +1,9 @@ +import { expect, it } from 'vitest' + +it('1 plus 1', () => { + expect(1 + 1).toBe(2) +}) + +it('failing test', () => { + expect(1 + 1).toBe(3) +}) diff --git a/test/cli/fixtures/list/top-level-error.test.ts b/test/cli/fixtures/list/top-level-error.test.ts new file mode 100644 index 000000000..59922e3fd --- /dev/null +++ b/test/cli/fixtures/list/top-level-error.test.ts @@ -0,0 +1 @@ +throw new Error('top level error') diff --git a/test/cli/fixtures/list/vitest.config.ts b/test/cli/fixtures/list/vitest.config.ts new file mode 100644 index 000000000..e64489065 --- /dev/null +++ b/test/cli/fixtures/list/vitest.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + include: ['basic.test.ts', 'math.test.ts'], + browser: { + name: 'chromium', + provider: 'playwright', + headless: true, + api: 7523, + } + }, +}) diff --git a/test/cli/test/__snapshots__/list.test.ts.snap b/test/cli/test/__snapshots__/list.test.ts.snap new file mode 100644 index 000000000..efc6f0b46 --- /dev/null +++ b/test/cli/test/__snapshots__/list.test.ts.snap @@ -0,0 +1,98 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`basic output shows error 1`] = ` +"Error: top level error + ❯ top-level-error.test.ts:1:7 + 1| throw new Error('top level error') + | ^ + 2| + +Error: describe error + ❯ describe-error.test.ts:4:9 + 2| + 3| describe('describe error', () => { + 4| throw new Error('describe error') + | ^ + 5| + 6| it('wont run', () => { + +" +`; + +exports[`correctly outputs all tests with args: "--browser.enabled" 1`] = ` +"basic.test.ts > basic suite > inner suite > some test +basic.test.ts > basic suite > inner suite > another test +basic.test.ts > basic suite > basic test +basic.test.ts > outside test +math.test.ts > 1 plus 1 +math.test.ts > failing test +" +`; + +exports[`correctly outputs all tests with args: "--pool=forks" 1`] = ` +"basic.test.ts > basic suite > inner suite > some test +basic.test.ts > basic suite > inner suite > another test +basic.test.ts > basic suite > basic test +basic.test.ts > outside test +math.test.ts > 1 plus 1 +math.test.ts > failing test +" +`; + +exports[`correctly outputs all tests with args: "--pool=threads" 1`] = ` +"basic.test.ts > basic suite > inner suite > some test +basic.test.ts > basic suite > inner suite > another test +basic.test.ts > basic suite > basic test +basic.test.ts > outside test +math.test.ts > 1 plus 1 +math.test.ts > failing test +" +`; + +exports[`correctly outputs all tests with args: "--pool=vmForks" 1`] = ` +"basic.test.ts > basic suite > inner suite > some test +basic.test.ts > basic suite > inner suite > another test +basic.test.ts > basic suite > basic test +basic.test.ts > outside test +math.test.ts > 1 plus 1 +math.test.ts > failing test +" +`; + +exports[`json output shows error 1`] = ` +"Error: top level error + ❯ top-level-error.test.ts:1:7 + 1| throw new Error('top level error') + | ^ + 2| + +Error: describe error + ❯ describe-error.test.ts:4:9 + 2| + 3| describe('describe error', () => { + 4| throw new Error('describe error') + | ^ + 5| + 6| it('wont run', () => { + +" +`; + +exports[`json with a file output shows error 1`] = ` +"Error: top level error + ❯ top-level-error.test.ts:1:7 + 1| throw new Error('top level error') + | ^ + 2| + +Error: describe error + ❯ describe-error.test.ts:4:9 + 2| + 3| describe('describe error', () => { + 4| throw new Error('describe error') + | ^ + 5| + 6| it('wont run', () => { + +" +`; diff --git a/test/cli/test/list.test.ts b/test/cli/test/list.test.ts new file mode 100644 index 000000000..6fc3597cb --- /dev/null +++ b/test/cli/test/list.test.ts @@ -0,0 +1,174 @@ +import { readFileSync, rmSync } from 'node:fs' +import { expect, onTestFinished, test } from 'vitest' +import { runVitestCli } from '../../test-utils' + +test.each([ + ['--pool=threads'], + ['--pool=forks'], + ['--pool=vmForks'], + ['--browser.enabled'], +])('correctly outputs all tests with args: "%s"', async (...args) => { + const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', ...args) + expect(stdout).toMatchSnapshot() + expect(exitCode).toBe(0) +}) + +test.each([ + ['basic'], + ['json', '--json'], + ['json with a file', '--json=./list.json'], +])('%s output shows error', async () => { + const { stderr, stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '-c=fail.config.ts') + expect(stdout).toBe('') + expect(stderr).toMatchSnapshot() + expect(exitCode).toBe(1) +}) + +test('correctly outputs json', async () => { + const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json') + expect(relative(stdout)).toMatchInlineSnapshot(` + "[ + { + "name": "basic suite > inner suite > some test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "basic suite > inner suite > another test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "basic suite > basic test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "outside test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "1 plus 1", + "file": "/fixtures/list/math.test.ts" + }, + { + "name": "failing test", + "file": "/fixtures/list/math.test.ts" + } + ] + " + `) + expect(exitCode).toBe(0) +}) + +test('correctly saves json', async () => { + const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json=./list.json') + onTestFinished(() => { + rmSync('./fixtures/list/list.json') + }) + const json = readFileSync('./fixtures/list/list.json', 'utf-8') + expect(stdout).toBe('') + expect(relative(json)).toMatchInlineSnapshot(` + "[ + { + "name": "basic suite > inner suite > some test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "basic suite > inner suite > another test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "basic suite > basic test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "outside test", + "file": "/fixtures/list/basic.test.ts" + }, + { + "name": "1 plus 1", + "file": "/fixtures/list/math.test.ts" + }, + { + "name": "failing test", + "file": "/fixtures/list/math.test.ts" + } + ]" + `) + expect(exitCode).toBe(0) +}) + +test('correctly filters by file', async () => { + const { stdout, exitCode } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list') + expect(stdout).toMatchInlineSnapshot(` + "math.test.ts > 1 plus 1 + math.test.ts > failing test + " + `) + expect(exitCode).toBe(0) +}) + +test('correctly prints project name in basic report', async () => { + const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--config=./custom.config.ts') + expect(stdout).toMatchInlineSnapshot(` + "[custom] math.test.ts > 1 plus 1 + [custom] math.test.ts > failing test + " + `) +}) + +test('correctly prints project name and locations in json report', async () => { + const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--json', '--config=./custom.config.ts') + expect(relative(stdout)).toMatchInlineSnapshot(` + "[ + { + "name": "1 plus 1", + "file": "/fixtures/list/math.test.ts", + "projectName": "custom", + "location": { + "line": 3, + "column": 1 + } + }, + { + "name": "failing test", + "file": "/fixtures/list/math.test.ts", + "projectName": "custom", + "location": { + "line": 7, + "column": 1 + } + } + ] + " + `) +}) + +test('correctly filters by test name', async () => { + const { stdout } = await runVitestCli('list', '-t=inner', '-r=./fixtures/list') + expect(stdout).toMatchInlineSnapshot(` + "basic.test.ts > basic suite > inner suite > some test + basic.test.ts > basic suite > inner suite > another test + " + `) +}) + +test('ignores watch flag', async () => { + // if it ends, it works - otherwise it will hang + const { stdout } = await runVitestCli('list', '-r=./fixtures/list', '--watch') + expect(stdout).toMatchInlineSnapshot(` + "basic.test.ts > basic suite > inner suite > some test + basic.test.ts > basic suite > inner suite > another test + basic.test.ts > basic suite > basic test + basic.test.ts > outside test + math.test.ts > 1 plus 1 + math.test.ts > failing test + " + `) +}) + +function relative(stdout: string) { + return stdout.replace(new RegExp(slash(process.cwd()), 'gi'), '') +} + +function slash(stdout: string) { + return stdout.replace(/\\/g, '/') +} diff --git a/test/core/package.json b/test/core/package.json index b06f3139a..ce41f04ea 100644 --- a/test/core/package.json +++ b/test/core/package.json @@ -8,7 +8,8 @@ "test:forks": "vitest --project forks", "test:vmThreads": "vitest --project vmThreads", "dev": "vite", - "coverage": "vitest run --coverage" + "coverage": "vitest run --coverage", + "collect": "vitest list" }, "devDependencies": { "@types/debug": "^4.1.12", diff --git a/test/test-utils/index.ts b/test/test-utils/index.ts index b1e212139..ce8980f1e 100644 --- a/test/test-utils/index.ts +++ b/test/test-utils/index.ts @@ -136,7 +136,7 @@ export async function runCli(command: string, _options?: Options | string, ...ar return output() } - if (args.includes('--watch')) { + if (args[0] !== 'list' && args.includes('--watch')) { if (command === 'vitest') { // Wait for initial test run to complete await cli.waitForStdout('Waiting for file changes') -- 2.51.2 From 42bd4a2593b141492c60537a13fbae3deec2d19d Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 3 Jul 2024 21:02:03 +0200 Subject: [PATCH 2/6] fix: include pretty-format in @vitest/runner for optimization on npm Fixes #6023 --- packages/browser/src/node/plugin.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/browser/src/node/plugin.ts b/packages/browser/src/node/plugin.ts index 5d1489bea..69b726495 100644 --- a/packages/browser/src/node/plugin.ts +++ b/packages/browser/src/node/plugin.ts @@ -158,6 +158,9 @@ export default (browserServer: BrowserServer, base = '/'): Plugin[] => { return { define, + resolve: { + dedupe: ['vitest'], + }, optimizeDeps: { entries, exclude: [ @@ -188,6 +191,7 @@ export default (browserServer: BrowserServer, base = '/'): Plugin[] => { 'vitest > pretty-format > ansi-regex', 'vitest > chai', 'vitest > chai > loupe', + 'vitest > @vitest/runner > pretty-format', 'vitest > @vitest/utils > diff-sequences', 'vitest > @vitest/utils > loupe', '@vitest/browser > @testing-library/user-event', -- 2.51.2 From 057b4f34b2fd1c1139e841f9e597af834e9ef8c5 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Thu, 4 Jul 2024 11:35:12 +0200 Subject: [PATCH 3/6] fix(browser): correctly mock optimized cjs dependencies (#6035) --- packages/browser/src/client/tester/mocker.ts | 23 ++++++++++--- packages/browser/src/client/tester/msw.ts | 8 ++--- packages/browser/src/node/resolveMock.ts | 33 +++++++++++++++++-- packages/browser/src/node/types.ts | 1 + .../fixtures/mocking/mocking-dep.test.ts | 12 +++++++ .../browser/fixtures/mocking/vitest.config.ts | 4 +++ 6 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 test/browser/fixtures/mocking/mocking-dep.test.ts diff --git a/packages/browser/src/client/tester/mocker.ts b/packages/browser/src/client/tester/mocker.ts index 8ff6b7f05..5aad7c1e9 100644 --- a/packages/browser/src/client/tester/mocker.ts +++ b/packages/browser/src/client/tester/mocker.ts @@ -138,16 +138,24 @@ export class VitestBrowserClientMocker { public queueMock(id: string, importer: string, factory?: () => any) { const promise = rpc() .resolveMock(id, importer, !!factory) - .then(async ({ mockPath, resolvedId }) => { + .then(async ({ mockPath, resolvedId, needsInterop }) => { this.ids.add(resolvedId) - const urlPaths = resolveMockPaths(resolvedId) + const urlPaths = resolveMockPaths(cleanVersion(resolvedId)) const resolvedMock = typeof mockPath === 'string' - ? new URL(resolvedMockedPath(mockPath), location.href).toString() + ? new URL(resolvedMockedPath(cleanVersion(mockPath)), location.href).toString() : mockPath + const _factory = factory && needsInterop + ? async () => { + const data = await factory() + return { default: data } + } + : factory urlPaths.forEach((url) => { this.mocks[url] = resolvedMock - this.factories[url] = factory! + if (_factory) { + this.factories[url] = _factory + } }) channel.postMessage({ type: 'mock', @@ -170,7 +178,7 @@ export class VitestBrowserClientMocker { return } this.ids.delete(resolved.id) - const urlPaths = resolveMockPaths(resolved.id) + const urlPaths = resolveMockPaths(cleanVersion(resolved.id)) urlPaths.forEach((url) => { delete this.mocks[url] delete this.factories[url] @@ -445,3 +453,8 @@ function resolveMockPaths(path: string) { return paths } + +const versionRegexp = /(\?|&)v=\w{8}/ +function cleanVersion(url: string) { + return url.replace(versionRegexp, '') +} diff --git a/packages/browser/src/client/tester/msw.ts b/packages/browser/src/client/tester/msw.ts index da09efd98..f66738b96 100644 --- a/packages/browser/src/client/tester/msw.ts +++ b/packages/browser/src/client/tester/msw.ts @@ -13,7 +13,7 @@ export function createModuleMocker() { const worker = setupWorker( http.get(/.+/, async ({ request }) => { - const path = removeTimestamp(request.url.slice(location.origin.length)) + const path = cleanQuery(request.url.slice(location.origin.length)) if (!mocks.has(path)) { return passthrough() } @@ -112,9 +112,9 @@ function getFactoryExports(id: string) { } const timestampRegexp = /(\?|&)t=\d{13}/ - -function removeTimestamp(url: string) { - return url.replace(timestampRegexp, '') +const versionRegexp = /(\?|&)v=\w{8}/ +function cleanQuery(url: string) { + return url.replace(timestampRegexp, '').replace(versionRegexp, '') } function passthrough() { diff --git a/packages/browser/src/node/resolveMock.ts b/packages/browser/src/node/resolveMock.ts index ff8b148a4..6326883d9 100644 --- a/packages/browser/src/node/resolveMock.ts +++ b/packages/browser/src/node/resolveMock.ts @@ -1,8 +1,9 @@ -import { existsSync, readdirSync } from 'node:fs' +import { existsSync, readFileSync, readdirSync } from 'node:fs' import { builtinModules } from 'node:module' import { basename, dirname, extname, isAbsolute, join, resolve } from 'pathe' import type { PartialResolvedId } from 'rollup' import type { ResolvedConfig } from 'vitest' +import type { ResolvedConfig as ViteConfig } from 'vite' import type { WorkspaceProject } from 'vitest/node' export async function resolveMock( @@ -14,7 +15,9 @@ export async function resolveMock( const { id, fsPath, external } = await resolveId(project, rawId, importer) if (hasFactory) { - return { type: 'factory' as const, resolvedId: id } + const needsInteropMap = viteDepsInteropMap(project.browser!.vite.config) + const needsInterop = needsInteropMap?.get(fsPath) ?? false + return { type: 'factory' as const, resolvedId: id, needsInterop } } const mockPath = resolveMockPath(project.config.root, fsPath, external) @@ -126,3 +129,29 @@ const postfixRE = /[?#].*$/ export function cleanUrl(url: string): string { return url.replace(postfixRE, '') } + +const metadata = new WeakMap>() + +function viteDepsInteropMap(config: ViteConfig) { + if (metadata.has(config)) { + return metadata.get(config)! + } + const cacheDirPath = getDepsCacheDir(config) + const metadataPath = resolve(cacheDirPath, '_metadata.json') + if (!existsSync(metadataPath)) { + return null + } + const { optimized } = JSON.parse(readFileSync(metadataPath, 'utf-8')) + const needsInteropMap = new Map() + for (const name in optimized) { + const dep = optimized[name] + const file = resolve(cacheDirPath, dep.file) + needsInteropMap.set(file, dep.needsInterop) + } + metadata.set(config, needsInteropMap) + return needsInteropMap +} + +function getDepsCacheDir(config: ViteConfig): string { + return resolve(config.cacheDir, 'deps') +} diff --git a/packages/browser/src/node/types.ts b/packages/browser/src/node/types.ts index ea766de7b..051b0b7bf 100644 --- a/packages/browser/src/node/types.ts +++ b/packages/browser/src/node/types.ts @@ -35,6 +35,7 @@ export interface WebSocketBrowserHandlers { type: 'factory' | 'redirect' | 'automock' mockPath?: string | null resolvedId: string + needsInterop?: boolean }> invalidate: (ids: string[]) => void getBrowserFileSourceMap: ( diff --git a/test/browser/fixtures/mocking/mocking-dep.test.ts b/test/browser/fixtures/mocking/mocking-dep.test.ts new file mode 100644 index 000000000..f9fe23aa1 --- /dev/null +++ b/test/browser/fixtures/mocking/mocking-dep.test.ts @@ -0,0 +1,12 @@ +import { a } from '@vitest/cjs-lib' +import { expect, test, vi } from 'vitest' + +vi.mock(import('@vitest/cjs-lib'), () => { + return { + a: 'mocked', + } +}) + +test('mocking works correctly', () => { + expect(a).toBe('mocked') +}) diff --git a/test/browser/fixtures/mocking/vitest.config.ts b/test/browser/fixtures/mocking/vitest.config.ts index 63c6c3b39..9fbb1e0da 100644 --- a/test/browser/fixtures/mocking/vitest.config.ts +++ b/test/browser/fixtures/mocking/vitest.config.ts @@ -5,6 +5,10 @@ const name = process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome') export default defineConfig({ + optimizeDeps: { + include: ['@vitest/cjs-lib'], + needsInterop: ['@vitest/cjs-lib'], + }, test: { browser: { enabled: true, -- 2.51.2 From 8f65ae906775562ecd244775cc77cface65d50ff Mon Sep 17 00:00:00 2001 From: Vladimir Date: Thu, 4 Jul 2024 15:01:33 +0200 Subject: [PATCH 4/6] fix: transpile esnext to node18 to support newest JS and TS features (#4409) --- .github/actions/setup-and-cache/action.yml | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/publish.yml | 2 +- package.json | 2 +- packages/vitest/src/node/plugins/index.ts | 3 +- packages/vitest/src/node/plugins/workspace.ts | 15 +- pnpm-lock.yaml | 638 +++++------------- test/core/test/esnext.test.ts | 52 ++ 8 files changed, 224 insertions(+), 492 deletions(-) create mode 100644 test/core/test/esnext.test.ts diff --git a/.github/actions/setup-and-cache/action.yml b/.github/actions/setup-and-cache/action.yml index 553b85f98..1a87e6900 100644 --- a/.github/actions/setup-and-cache/action.yml +++ b/.github/actions/setup-and-cache/action.yml @@ -11,7 +11,7 @@ runs: steps: - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 - name: Set node version to ${{ inputs.node-version }} uses: actions/setup-node@v4 diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 3199e08a0..3e7bb9ad0 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v4 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 - name: Install node uses: actions/setup-node@v4 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 73e1feb3e..31aeb4810 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,7 +20,7 @@ jobs: fetch-depth: 0 - name: Install pnpm - uses: pnpm/action-setup@v3 + uses: pnpm/action-setup@v4 - name: Set node version to 20 uses: actions/setup-node@v4 diff --git a/package.json b/package.json index 4190bc758..53e2efa3a 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "simple-git-hooks": "^2.11.1", "tsx": "^4.16.0", "typescript": "^5.5.2", - "vite": "^5.2.6", + "vite": "^5.3.3", "vitest": "workspace:*", "zx": "^8.1.3" }, diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index ea664d129..dcf6a2898 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -81,8 +81,9 @@ export async function VitestPlugin( viteConfig.esbuild === false ? false : { + // Lowest target Vitest supports is Node18 + target: viteConfig.esbuild?.target || 'node18', sourcemap: 'external', - // Enables using ignore hint for coverage providers with @preserve keyword legalComments: 'inline', }, diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index c6e1af2d6..ff1c79716 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -70,12 +70,15 @@ export function WorkspaceVitestPlugin( alias: testConfig.alias, conditions: ['node'], }, - esbuild: { - sourcemap: 'external', - - // Enables using ignore hint for coverage providers with @preserve keyword - legalComments: 'inline', - }, + esbuild: viteConfig.esbuild === false + ? false + : { + // Lowest target Vitest supports is Node18 + target: viteConfig.esbuild?.target || 'node18', + sourcemap: 'external', + // Enables using ignore hint for coverage providers with @preserve keyword + legalComments: 'inline', + }, server: { // disable watch mode in workspaces, // because it is handled by the top-level watcher diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1c9c4fafe..a32c48d53 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,7 +7,7 @@ settings: overrides: mlly: ^1.7.1 rollup: ^4.18.0 - vite: ^5.2.6 + vite: ^5.3.3 vitest: workspace:* patchedDependencies: @@ -36,7 +36,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: ^2.21.2 - version: 2.21.2(@vue/compiler-sfc@3.4.29)(eslint@9.6.0)(typescript@5.5.2)(vitest@packages+vitest) + version: 2.21.2(@vue/compiler-sfc@3.4.31)(eslint@9.6.0)(typescript@5.5.2)(vitest@packages+vitest) '@antfu/ni': specifier: ^0.21.12 version: 0.21.12 @@ -116,8 +116,8 @@ importers: specifier: ^5.5.2 version: 5.5.2 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:packages/vitest @@ -154,7 +154,7 @@ importers: version: 0.5.0(@vite-pwa/assets-generator@0.2.4)(vite-plugin-pwa@0.20.0) '@vitejs/plugin-vue': specifier: latest - version: 5.0.4(vite@5.2.6)(vue@3.4.31) + version: 5.0.4(vite@5.3.3)(vue@3.4.31) fast-glob: specifier: ^3.3.2 version: 3.3.2 @@ -163,16 +163,16 @@ importers: version: 4.7.1 unocss: specifier: ^0.61.0 - version: 0.61.0(postcss@8.4.38)(rollup@4.18.0)(vite@5.2.6) + version: 0.61.0(postcss@8.4.38)(rollup@4.18.0)(vite@5.3.3) unplugin-vue-components: specifier: ^0.27.2 version: 0.27.2(rollup@4.18.0)(vue@3.4.31) vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vite-plugin-pwa: specifier: ^0.20.0 - version: 0.20.0(@vite-pwa/assets-generator@0.2.4)(vite@5.2.6)(workbox-build@7.1.0)(workbox-window@7.1.0) + version: 0.20.0(@vite-pwa/assets-generator@0.2.4)(vite@5.3.3)(workbox-build@7.1.0)(workbox-window@7.1.0) vitepress: specifier: ^1.2.3 version: 1.2.3(@types/node@20.14.9)(postcss@8.4.38)(search-insights@2.9.0)(typescript@5.5.2) @@ -186,8 +186,8 @@ importers: specifier: latest version: link:../../packages/ui vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -207,8 +207,8 @@ importers: specifier: ^4.7.2 version: 4.7.2 vite: - specifier: ^5.2.6 - version: 5.2.10(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -229,8 +229,8 @@ importers: specifier: latest version: 24.0.0 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -255,7 +255,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: ^2.8.2 - version: 2.8.2(@babel/core@7.24.7)(preact@10.21.0)(vite@5.2.10) + version: 2.8.2(@babel/core@7.24.7)(preact@10.21.0)(vite@5.3.3) '@testing-library/jest-dom': specifier: ^6.4.2 version: 6.4.2(vitest@packages+vitest) @@ -269,8 +269,8 @@ importers: specifier: ^5.4.5 version: 5.4.5 vite: - specifier: ^5.2.6 - version: 5.2.10(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -300,8 +300,8 @@ importers: specifier: ^24.0.0 version: 24.0.0 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -322,11 +322,11 @@ importers: specifier: latest version: 24.0.0 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vite-plugin-solid: specifier: ^2.7.2 - version: 2.7.2(solid-js@1.8.3)(vite@5.2.6) + version: 2.7.2(solid-js@1.8.3)(vite@5.3.3) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -338,7 +338,7 @@ importers: version: 2.1.0(@sveltejs/kit@1.20.2) '@sveltejs/kit': specifier: ^1.20.2 - version: 1.20.2(svelte@3.59.1)(vite@5.2.6) + version: 1.20.2(svelte@3.59.1)(vite@5.3.3) svelte: specifier: ^3.59.1 version: 3.59.1 @@ -352,8 +352,8 @@ importers: specifier: ^5.2.2 version: 5.2.2 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -370,8 +370,8 @@ importers: specifier: ^5.2.2 version: 5.2.2 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.11.5) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.11.5) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -392,7 +392,7 @@ importers: version: 18.2.79 '@vitejs/plugin-react': specifier: ^4.2.1 - version: 4.2.1(vite@5.2.10) + version: 4.2.1(vite@5.3.3) '@vitest/ui': specifier: latest version: link:../../packages/ui @@ -412,8 +412,8 @@ importers: specifier: ^4.7.2 version: 4.7.2 vite: - specifier: ^5.2.6 - version: 5.2.10(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -719,7 +719,7 @@ importers: version: 1.1.43 '@testing-library/vue': specifier: ^8.1.0 - version: 8.1.0(@vue/compiler-sfc@3.4.29)(vue@3.4.31) + version: 8.1.0(@vue/compiler-sfc@3.4.31)(vue@3.4.31) '@types/codemirror': specifier: ^5.60.15 version: 5.60.15 @@ -737,7 +737,7 @@ importers: version: 0.61.0 '@vitejs/plugin-vue': specifier: ^5.0.5 - version: 5.0.5(vite@5.2.6)(vue@3.4.31) + version: 5.0.5(vite@5.3.3)(vue@3.4.31) '@vitest/runner': specifier: workspace:* version: link:../runner @@ -770,7 +770,7 @@ importers: version: 3.1.5 unocss: specifier: ^0.61.0 - version: 0.61.0(postcss@8.4.38)(rollup@4.18.0)(vite@5.2.6) + version: 0.61.0(postcss@8.4.38)(rollup@4.18.0)(vite@5.3.3) unplugin-auto-import: specifier: ^0.17.6 version: 0.17.6(@vueuse/core@10.11.0)(rollup@4.18.0) @@ -778,11 +778,11 @@ importers: specifier: ^0.27.2 version: 0.27.2(rollup@4.18.0)(vue@3.4.31) vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vite-plugin-pages: specifier: ^0.32.3 - version: 0.32.3(@vue/compiler-sfc@3.4.29)(vite@5.2.6)(vue-router@4.4.0) + version: 0.32.3(@vue/compiler-sfc@3.4.31)(vite@5.3.3)(vue-router@4.4.0) vue: specifier: ^3.4.31 version: 3.4.31(typescript@5.5.2) @@ -830,8 +830,8 @@ importers: specifier: ^1.0.1 version: 1.0.1 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) devDependencies: '@jridgewell/trace-mapping': specifier: ^0.3.25 @@ -894,8 +894,8 @@ importers: specifier: ^1.0.0 version: 1.0.0 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vite-node: specifier: workspace:* version: link:../vite-node @@ -1045,7 +1045,7 @@ importers: devDependencies: '@vitejs/plugin-basic-ssl': specifier: ^1.0.2 - version: 1.0.2(vite@5.2.10) + version: 1.0.2(vite@5.3.3) '@vitest/browser': specifier: workspace:* version: link:../../packages/browser @@ -1081,7 +1081,7 @@ importers: version: 8.5.9 '@vitejs/plugin-basic-ssl': specifier: ^1.0.2 - version: 1.0.2(vite@5.2.6) + version: 1.0.2(vite@5.3.3) '@vitest/runner': specifier: workspace:^ version: link:../../packages/runner @@ -1098,8 +1098,8 @@ importers: specifier: ^1.4.4 version: 1.4.4(@swc/core@1.4.1)(rollup@4.18.0) vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -1113,8 +1113,8 @@ importers: specifier: ^8.0.1 version: 8.0.1 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -1198,7 +1198,7 @@ importers: version: 3.0.3 '@vitejs/plugin-vue': specifier: latest - version: 5.0.4(vite@5.2.6)(vue@3.4.21) + version: 5.0.4(vite@5.3.3)(vue@3.4.21) '@vitest/browser': specifier: workspace:* version: link:../../packages/browser @@ -1230,8 +1230,8 @@ importers: specifier: ^1.4.4 version: 1.4.4(@swc/core@1.4.1)(rollup@4.18.0) vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -1290,8 +1290,8 @@ importers: specifier: ^7.0.1 version: 7.0.1 vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vite-node: specifier: workspace:* version: link:../../packages/vite-node @@ -1351,8 +1351,8 @@ importers: specifier: workspace:* version: link:../../packages/browser vite: - specifier: ^5.2.6 - version: 5.2.6(@types/node@20.14.9) + specifier: ^5.3.3 + version: 5.3.3(@types/node@20.14.9) vitest: specifier: workspace:* version: link:../../packages/vitest @@ -1559,7 +1559,7 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - /@antfu/eslint-config@2.21.2(@vue/compiler-sfc@3.4.29)(eslint@9.6.0)(typescript@5.5.2)(vitest@packages+vitest): + /@antfu/eslint-config@2.21.2(@vue/compiler-sfc@3.4.31)(eslint@9.6.0)(typescript@5.5.2)(vitest@packages+vitest): resolution: {integrity: sha512-qaKf+af5GeSNTvTzxtSmpitwLZWIwl/uURxQZhhoHCoA1PxofFHSpCNVYLSvPlj17lwT/DzWgovgL/08uXG9aQ==} hasBin: true peerDependencies: @@ -1631,7 +1631,7 @@ packages: eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@7.14.1)(eslint@9.6.0)(typescript@5.5.2)(vitest@packages+vitest) eslint-plugin-vue: 9.26.0(eslint@9.6.0) eslint-plugin-yml: 1.14.0(eslint@9.6.0) - eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.29)(eslint@9.6.0) + eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.31)(eslint@9.6.0) globals: 15.7.0 jsonc-eslint-parser: 2.4.0 local-pkg: 0.5.0 @@ -3470,21 +3470,12 @@ packages: dev: true optional: true - /@esbuild/aix-ppc64@0.20.2: - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - optional: true - /@esbuild/aix-ppc64@0.21.5: resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] requiresBuild: true - dev: true optional: true /@esbuild/aix-ppc64@0.22.0: @@ -3505,21 +3496,12 @@ packages: dev: true optional: true - /@esbuild/android-arm64@0.20.2: - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm64@0.21.5: resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/android-arm64@0.22.0: @@ -3540,21 +3522,12 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.20.2: - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm@0.21.5: resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/android-arm@0.22.0: @@ -3575,21 +3548,12 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.20.2: - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-x64@0.21.5: resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/android-x64@0.22.0: @@ -3610,21 +3574,12 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.20.2: - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.21.5: resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true - dev: true optional: true /@esbuild/darwin-arm64@0.22.0: @@ -3645,21 +3600,12 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.20.2: - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-x64@0.21.5: resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true - dev: true optional: true /@esbuild/darwin-x64@0.22.0: @@ -3680,21 +3626,12 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.20.2: - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-arm64@0.21.5: resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true - dev: true optional: true /@esbuild/freebsd-arm64@0.22.0: @@ -3715,21 +3652,12 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.20.2: - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-x64@0.21.5: resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true - dev: true optional: true /@esbuild/freebsd-x64@0.22.0: @@ -3750,21 +3678,12 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.20.2: - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm64@0.21.5: resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-arm64@0.22.0: @@ -3785,21 +3704,12 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.20.2: - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm@0.21.5: resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-arm@0.22.0: @@ -3820,21 +3730,12 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.20.2: - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ia32@0.21.5: resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-ia32@0.22.0: @@ -3855,21 +3756,12 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.20.2: - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64@0.21.5: resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-loong64@0.22.0: @@ -3890,21 +3782,12 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.20.2: - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-mips64el@0.21.5: resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-mips64el@0.22.0: @@ -3925,21 +3808,12 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.20.2: - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ppc64@0.21.5: resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-ppc64@0.22.0: @@ -3960,21 +3834,12 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.20.2: - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-riscv64@0.21.5: resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-riscv64@0.22.0: @@ -3995,21 +3860,12 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.20.2: - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-s390x@0.21.5: resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-s390x@0.22.0: @@ -4030,21 +3886,12 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.20.2: - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-x64@0.21.5: resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /@esbuild/linux-x64@0.22.0: @@ -4065,21 +3912,12 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.20.2: - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - /@esbuild/netbsd-x64@0.21.5: resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true - dev: true optional: true /@esbuild/netbsd-x64@0.22.0: @@ -4109,21 +3947,12 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.20.2: - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - /@esbuild/openbsd-x64@0.21.5: resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true - dev: true optional: true /@esbuild/openbsd-x64@0.22.0: @@ -4144,21 +3973,12 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.20.2: - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - /@esbuild/sunos-x64@0.21.5: resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true - dev: true optional: true /@esbuild/sunos-x64@0.22.0: @@ -4179,21 +3999,12 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.20.2: - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-arm64@0.21.5: resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true - dev: true optional: true /@esbuild/win32-arm64@0.22.0: @@ -4214,21 +4025,12 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.20.2: - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-ia32@0.21.5: resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true /@esbuild/win32-ia32@0.22.0: @@ -4249,21 +4051,12 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.20.2: - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-x64@0.21.5: resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true - dev: true optional: true /@esbuild/win32-x64@0.22.0: @@ -4643,16 +4436,16 @@ packages: preact: 10.21.0 dev: false - /@preact/preset-vite@2.8.2(@babel/core@7.24.7)(preact@10.21.0)(vite@5.2.10): + /@preact/preset-vite@2.8.2(@babel/core@7.24.7)(preact@10.21.0)(vite@5.3.3): resolution: {integrity: sha512-m3tl+M8IO8jgiHnk+7LSTFl8axdPXloewi7iGVLdmCwf34XOzEUur0bZVewW4DUbUipFjTS2CXu27+5f/oexBA==} peerDependencies: '@babel/core': 7.x - vite: ^5.2.6 + vite: ^5.3.3 dependencies: '@babel/core': 7.24.7 '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.24.7) '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.7) - '@prefresh/vite': 2.4.1(preact@10.21.0)(vite@5.2.10) + '@prefresh/vite': 2.4.1(preact@10.21.0)(vite@5.3.3) '@rollup/pluginutils': 4.2.1 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.24.7) debug: 4.3.4 @@ -4662,7 +4455,7 @@ packages: resolve: 1.22.8 source-map: 0.7.4 stack-trace: 1.0.0-pre2 - vite: 5.2.10(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - preact - supports-color @@ -4684,11 +4477,11 @@ packages: resolution: {integrity: sha512-KtC/fZw+oqtwOLUFM9UtiitB0JsVX0zLKNyRTA332sqREqSALIIQQxdUCS1P3xR/jT1e2e8/5rwH6gdcMLEmsQ==} dev: true - /@prefresh/vite@2.4.1(preact@10.21.0)(vite@5.2.10): + /@prefresh/vite@2.4.1(preact@10.21.0)(vite@5.3.3): resolution: {integrity: sha512-vthWmEqu8TZFeyrBNc9YE5SiC3DVSzPgsOCp/WQ7FqdHpOIJi7Z8XvCK06rBPOtG4914S52MjG9Ls22eVAiuqQ==} peerDependencies: preact: ^10.4.0 - vite: ^5.2.6 + vite: ^5.3.3 dependencies: '@babel/core': 7.24.5 '@prefresh/babel-plugin': 0.5.0 @@ -4696,7 +4489,7 @@ packages: '@prefresh/utils': 1.2.0 '@rollup/pluginutils': 4.2.1 preact: 10.21.0 - vite: 5.2.10(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - supports-color dev: true @@ -5167,20 +4960,20 @@ packages: peerDependencies: '@sveltejs/kit': ^1.0.0 dependencies: - '@sveltejs/kit': 1.20.2(svelte@3.59.1)(vite@5.2.6) + '@sveltejs/kit': 1.20.2(svelte@3.59.1)(vite@5.3.3) import-meta-resolve: 3.0.0 dev: true - /@sveltejs/kit@1.20.2(svelte@3.59.1)(vite@5.2.6): + /@sveltejs/kit@1.20.2(svelte@3.59.1)(vite@5.3.3): resolution: {integrity: sha512-MtR1i+HtmYWcRgtubw1GQqT/+CWXL/z24PegE0xYAdObbhdr7YtEfmoe705D/JZMtMmoPXrmSk4W0MfL5A3lYw==} engines: {node: ^16.14 || >=18} hasBin: true requiresBuild: true peerDependencies: svelte: ^3.54.0 || ^4.0.0-next.0 - vite: ^5.2.6 + vite: ^5.3.3 dependencies: - '@sveltejs/vite-plugin-svelte': 2.4.6(svelte@3.59.1)(vite@5.2.6) + '@sveltejs/vite-plugin-svelte': 2.4.6(svelte@3.59.1)(vite@5.3.3) '@types/cookie': 0.5.1 cookie: 0.5.0 devalue: 4.3.2 @@ -5194,43 +4987,43 @@ packages: svelte: 3.59.1 tiny-glob: 0.2.9 undici: 5.22.1 - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - supports-color dev: true - /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.4.6)(svelte@3.59.1)(vite@5.2.6): + /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.4.6)(svelte@3.59.1)(vite@5.3.3): resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==} engines: {node: ^14.18.0 || >= 16} peerDependencies: '@sveltejs/vite-plugin-svelte': ^2.2.0 svelte: ^3.54.0 || ^4.0.0 - vite: ^5.2.6 + vite: ^5.3.3 dependencies: - '@sveltejs/vite-plugin-svelte': 2.4.6(svelte@3.59.1)(vite@5.2.6) + '@sveltejs/vite-plugin-svelte': 2.4.6(svelte@3.59.1)(vite@5.3.3) debug: 4.3.5 svelte: 3.59.1 - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - supports-color dev: true - /@sveltejs/vite-plugin-svelte@2.4.6(svelte@3.59.1)(vite@5.2.6): + /@sveltejs/vite-plugin-svelte@2.4.6(svelte@3.59.1)(vite@5.3.3): resolution: {integrity: sha512-zO79p0+DZnXPnF0ltIigWDx/ux7Ni+HRaFOw720Qeivc1azFUrJxTl0OryXVibYNx1hCboGia1NRV3x8RNv4cA==} engines: {node: ^14.18.0 || >= 16} peerDependencies: svelte: ^3.54.0 || ^4.0.0 - vite: ^5.2.6 + vite: ^5.3.3 dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 1.0.4(@sveltejs/vite-plugin-svelte@2.4.6)(svelte@3.59.1)(vite@5.2.6) + '@sveltejs/vite-plugin-svelte-inspector': 1.0.4(@sveltejs/vite-plugin-svelte@2.4.6)(svelte@3.59.1)(vite@5.3.3) debug: 4.3.5 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.10 svelte: 3.59.1 svelte-hmr: 0.15.3(svelte@3.59.1) - vite: 5.2.6(@types/node@20.14.9) - vitefu: 0.2.5(vite@5.2.6) + vite: 5.3.3(@types/node@20.14.9) + vitefu: 0.2.5(vite@5.3.3) transitivePeerDependencies: - supports-color dev: true @@ -5531,7 +5324,7 @@ packages: dependencies: '@testing-library/dom': 10.2.0 - /@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.29)(vue@3.4.31): + /@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.31)(vue@3.4.31): resolution: {integrity: sha512-ls4RiHO1ta4mxqqajWRh8158uFObVrrtAPoxk7cIp4HrnQUj/ScKzqz53HxYpG3X6Zb7H2v+0eTGLSoy8HQ2nA==} engines: {node: '>=14'} peerDependencies: @@ -5543,7 +5336,7 @@ packages: dependencies: '@babel/runtime': 7.24.4 '@testing-library/dom': 9.3.4 - '@vue/compiler-sfc': 3.4.29 + '@vue/compiler-sfc': 3.4.31 '@vue/test-utils': 2.4.6 vue: 3.4.31(typescript@5.5.2) dev: true @@ -5658,7 +5451,7 @@ packages: requiresBuild: true dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 20.12.11 + '@types/node': 20.14.9 dev: true optional: true @@ -5746,7 +5539,7 @@ packages: resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} requiresBuild: true dependencies: - '@types/node': 20.12.11 + '@types/node': 20.14.9 dev: true optional: true @@ -5954,7 +5747,7 @@ packages: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} requiresBuild: true dependencies: - '@types/node': 20.12.11 + '@types/node': 20.14.9 dev: true optional: true @@ -6156,18 +5949,18 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true - /@unocss/astro@0.61.0(rollup@4.18.0)(vite@5.2.6): + /@unocss/astro@0.61.0(rollup@4.18.0)(vite@5.3.3): resolution: {integrity: sha512-cbgztX/to5rMhAtEGCcR3ClMlK9F+lPxq21A72qsbWVQjiKa7W4O7qKBmUKPYsWRzJEJtdyN11A65H2037aKQw==} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 peerDependenciesMeta: vite: optional: true dependencies: '@unocss/core': 0.61.0 '@unocss/reset': 0.61.0 - '@unocss/vite': 0.61.0(rollup@4.18.0)(vite@5.2.6) - vite: 5.2.6(@types/node@20.14.9) + '@unocss/vite': 0.61.0(rollup@4.18.0)(vite@5.3.3) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - rollup dev: true @@ -6350,10 +6143,10 @@ packages: '@unocss/core': 0.61.0 dev: true - /@unocss/vite@0.61.0(rollup@4.18.0)(vite@5.2.6): + /@unocss/vite@0.61.0(rollup@4.18.0)(vite@5.3.3): resolution: {integrity: sha512-gjxLJrja1hqDwdd8z3QvzfMCcKppGqiL2+A6aHwG/AXfEmZMydA50U7VvJK7Wx8/Enm26G6JQrtGrpu+kK3QpQ==} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 dependencies: '@ampproject/remapping': 2.3.0 '@rollup/pluginutils': 5.1.0(rollup@4.18.0) @@ -6365,7 +6158,7 @@ packages: chokidar: 3.6.0 fast-glob: 3.3.2 magic-string: 0.30.10 - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - rollup dev: true @@ -6393,84 +6186,64 @@ packages: optional: true dependencies: '@vite-pwa/assets-generator': 0.2.4 - vite-plugin-pwa: 0.20.0(@vite-pwa/assets-generator@0.2.4)(vite@5.2.6)(workbox-build@7.1.0)(workbox-window@7.1.0) + vite-plugin-pwa: 0.20.0(@vite-pwa/assets-generator@0.2.4)(vite@5.3.3)(workbox-build@7.1.0)(workbox-window@7.1.0) dev: true - /@vitejs/plugin-basic-ssl@1.0.2(vite@5.2.10): + /@vitejs/plugin-basic-ssl@1.0.2(vite@5.3.3): resolution: {integrity: sha512-DKHKVtpI+eA5fvObVgQ3QtTGU70CcCnedalzqmGSR050AzKZMdUzgC8KmlOneHWH8dF2hJ3wkC9+8FDVAaDRCw==} engines: {node: '>=14.6.0'} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 dependencies: - vite: 5.2.10(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) dev: true - /@vitejs/plugin-basic-ssl@1.0.2(vite@5.2.6): - resolution: {integrity: sha512-DKHKVtpI+eA5fvObVgQ3QtTGU70CcCnedalzqmGSR050AzKZMdUzgC8KmlOneHWH8dF2hJ3wkC9+8FDVAaDRCw==} - engines: {node: '>=14.6.0'} - peerDependencies: - vite: ^5.2.6 - dependencies: - vite: 5.2.6(@types/node@20.14.9) - dev: true - - /@vitejs/plugin-react@4.2.1(vite@5.2.10): + /@vitejs/plugin-react@4.2.1(vite@5.3.3): resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 dependencies: '@babel/core': 7.24.4 '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.24.4) '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.24.4) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 - vite: 5.2.10(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - supports-color dev: true - /@vitejs/plugin-vue@5.0.4(vite@5.2.6)(vue@3.4.21): + /@vitejs/plugin-vue@5.0.4(vite@5.3.3)(vue@3.4.21): resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 vue: ^3.2.25 dependencies: - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) vue: 3.4.21(typescript@5.5.2) dev: true - /@vitejs/plugin-vue@5.0.4(vite@5.2.6)(vue@3.4.31): + /@vitejs/plugin-vue@5.0.4(vite@5.3.3)(vue@3.4.31): resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 vue: ^3.2.25 dependencies: - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) vue: 3.4.31(typescript@5.5.2) dev: true - /@vitejs/plugin-vue@5.0.5(vite@5.2.10)(vue@3.4.31): + /@vitejs/plugin-vue@5.0.5(vite@5.3.3)(vue@3.4.31): resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 vue: ^3.2.25 dependencies: - vite: 5.2.10(@types/node@20.14.9) - vue: 3.4.31(typescript@5.5.2) - dev: true - - /@vitejs/plugin-vue@5.0.5(vite@5.2.6)(vue@3.4.31): - resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==} - engines: {node: ^18.0.0 || >=20.0.0} - peerDependencies: - vite: ^5.2.6 - vue: ^3.2.25 - dependencies: - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) vue: 3.4.31(typescript@5.5.2) dev: true @@ -6522,16 +6295,6 @@ packages: source-map-js: 1.2.0 dev: true - /@vue/compiler-core@3.4.29: - resolution: {integrity: sha512-TFKiRkKKsRCKvg/jTSSKK7mYLJEQdUiUfykbG49rubC9SfDyvT2JrzTReopWlz2MxqeLyxh9UZhvxEIBgAhtrg==} - dependencies: - '@babel/parser': 7.24.7 - '@vue/shared': 3.4.29 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.0 - dev: true - /@vue/compiler-core@3.4.31: resolution: {integrity: sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==} dependencies: @@ -6555,13 +6318,6 @@ packages: '@vue/shared': 3.4.26 dev: true - /@vue/compiler-dom@3.4.29: - resolution: {integrity: sha512-A6+iZ2fKIEGnfPJejdB7b1FlJzgiD+Y/sxxKwJWg1EbJu6ZPgzaPQQ51ESGNv0CP6jm6Z7/pO6Ia8Ze6IKrX7w==} - dependencies: - '@vue/compiler-core': 3.4.29 - '@vue/shared': 3.4.29 - dev: true - /@vue/compiler-dom@3.4.31: resolution: {integrity: sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==} dependencies: @@ -6604,20 +6360,6 @@ packages: source-map-js: 1.2.0 dev: true - /@vue/compiler-sfc@3.4.29: - resolution: {integrity: sha512-zygDcEtn8ZimDlrEQyLUovoWgKQic6aEQqRXce2WXBvSeHbEbcAsXyCk9oG33ZkyWH4sl9D3tkYc1idoOkdqZQ==} - dependencies: - '@babel/parser': 7.24.7 - '@vue/compiler-core': 3.4.29 - '@vue/compiler-dom': 3.4.29 - '@vue/compiler-ssr': 3.4.29 - '@vue/shared': 3.4.29 - estree-walker: 2.0.2 - magic-string: 0.30.10 - postcss: 8.4.38 - source-map-js: 1.2.0 - dev: true - /@vue/compiler-sfc@3.4.31: resolution: {integrity: sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==} dependencies: @@ -6645,13 +6387,6 @@ packages: '@vue/shared': 3.4.26 dev: true - /@vue/compiler-ssr@3.4.29: - resolution: {integrity: sha512-rFbwCmxJ16tDp3N8XCx5xSQzjhidYjXllvEcqX/lopkoznlNPz3jyy0WGJCyhAaVQK677WWFt3YO/WUEkMMUFQ==} - dependencies: - '@vue/compiler-dom': 3.4.29 - '@vue/shared': 3.4.29 - dev: true - /@vue/compiler-ssr@3.4.31: resolution: {integrity: sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==} dependencies: @@ -6699,7 +6434,7 @@ packages: dependencies: '@volar/language-core': 1.10.4 '@volar/source-map': 1.10.4 - '@vue/compiler-dom': 3.4.29 + '@vue/compiler-dom': 3.4.31 '@vue/shared': 3.4.29 computeds: 0.0.1 minimatch: 9.0.4 @@ -6717,7 +6452,7 @@ packages: optional: true dependencies: '@volar/language-core': 2.4.0-alpha.5 - '@vue/compiler-dom': 3.4.29 + '@vue/compiler-dom': 3.4.31 '@vue/shared': 3.4.29 computeds: 0.0.1 minimatch: 9.0.4 @@ -6808,13 +6543,13 @@ packages: vue: 3.4.26(typescript@5.5.2) dev: true - /@vue/server-renderer@3.4.29(vue@3.4.21): - resolution: {integrity: sha512-HMLCmPI2j/k8PVkSBysrA2RxcxC5DgBiCdj7n7H2QtR8bQQPqKAe8qoaxLcInzouBmzwJ+J0x20ygN/B5mYBng==} + /@vue/server-renderer@3.4.31(vue@3.4.21): + resolution: {integrity: sha512-D5BLbdvrlR9PE3by9GaUp1gQXlCNadIZytMIb8H2h3FMWJd4oUfkUTEH2wAr3qxoRz25uxbTcbqd3WKlm9EHQA==} peerDependencies: - vue: 3.4.29 + vue: 3.4.31 dependencies: - '@vue/compiler-ssr': 3.4.29 - '@vue/shared': 3.4.29 + '@vue/compiler-ssr': 3.4.31 + '@vue/shared': 3.4.31 vue: 3.4.21(typescript@5.5.2) dev: true optional: true @@ -6855,8 +6590,8 @@ packages: js-beautify: 1.14.6 vue: 3.4.21(typescript@5.5.2) optionalDependencies: - '@vue/compiler-dom': 3.4.29 - '@vue/server-renderer': 3.4.29(vue@3.4.21) + '@vue/compiler-dom': 3.4.31 + '@vue/server-renderer': 3.4.31(vue@3.4.21) dev: true /@vue/test-utils@2.4.6: @@ -9225,36 +8960,6 @@ packages: '@esbuild/win32-x64': 0.19.11 dev: true - /esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 - /esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -9284,7 +8989,6 @@ packages: '@esbuild/win32-arm64': 0.21.5 '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - dev: true /esbuild@0.22.0: resolution: {integrity: sha512-zNYA6bFZsVnsU481FnGAQjLDW0Pl/8BGG7EvAp15RzUvGC+ME7hf1q7LvIfStEQBz/iEHuBJCYcOwPmNCf1Tlw==} @@ -9699,13 +9403,13 @@ packages: - supports-color dev: true - /eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.29)(eslint@9.6.0): + /eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.31)(eslint@9.6.0): resolution: {integrity: sha512-PfpJ4uKHnqeL/fXUnzYkOax3aIenlwewXRX8jFinA1a2yCFnLgMuiH3xvCgvHHUlV2xJWQHbCTdiJWGwb3NqpQ==} peerDependencies: '@vue/compiler-sfc': ^3.3.0 eslint: ^8.50.0 || ^9.0.0 dependencies: - '@vue/compiler-sfc': 3.4.29 + '@vue/compiler-sfc': 3.4.31 eslint: 9.6.0 dev: true @@ -13523,6 +13227,14 @@ packages: picocolors: 1.0.1 source-map-js: 1.2.0 + /postcss@8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + /preact@10.21.0: resolution: {integrity: sha512-aQAIxtzWEwH8ou+OovWVSVNlFImL7xUCwJX3YMqA3U8iKCNC34999fFOnWjYNsylgfPgMexpbk7WYOLtKr/mxg==} @@ -15721,19 +15433,19 @@ packages: engines: {node: '>= 10.0.0'} dev: true - /unocss@0.61.0(postcss@8.4.38)(rollup@4.18.0)(vite@5.2.6): + /unocss@0.61.0(postcss@8.4.38)(rollup@4.18.0)(vite@5.3.3): resolution: {integrity: sha512-7642v5tHpEpHO9dl9sqYbKT/Ri4X4lmGHhj/znE4uheEfXcptPPiZ1/hVmQVciHUSI8CnQBqDwkZuxNPDG3bTQ==} engines: {node: '>=14'} peerDependencies: '@unocss/webpack': 0.61.0 - vite: ^5.2.6 + vite: ^5.3.3 peerDependenciesMeta: '@unocss/webpack': optional: true vite: optional: true dependencies: - '@unocss/astro': 0.61.0(rollup@4.18.0)(vite@5.2.6) + '@unocss/astro': 0.61.0(rollup@4.18.0)(vite@5.3.3) '@unocss/cli': 0.61.0(rollup@4.18.0) '@unocss/core': 0.61.0 '@unocss/extractor-arbitrary-variants': 0.61.0 @@ -15752,8 +15464,8 @@ packages: '@unocss/transformer-compile-class': 0.61.0 '@unocss/transformer-directives': 0.61.0 '@unocss/transformer-variant-group': 0.61.0 - '@unocss/vite': 0.61.0(rollup@4.18.0)(vite@5.2.6) - vite: 5.2.6(@types/node@20.14.9) + '@unocss/vite': 0.61.0(rollup@4.18.0)(vite@5.3.3) + vite: 5.3.3(@types/node@20.14.9) transitivePeerDependencies: - postcss - rollup @@ -15984,13 +15696,13 @@ packages: vfile-message: 4.0.2 dev: true - /vite-plugin-pages@0.32.3(@vue/compiler-sfc@3.4.29)(vite@5.2.6)(vue-router@4.4.0): + /vite-plugin-pages@0.32.3(@vue/compiler-sfc@3.4.31)(vite@5.3.3)(vue-router@4.4.0): resolution: {integrity: sha512-1vmKwc9e+lRBLkpTAMUNSVV3BglyE+DRa0iivpe6q3pbOCGkAHHSUp8f6yceXC8+lu/kFgH60vm5vK6IHyvdVw==} peerDependencies: '@solidjs/router': '*' '@vue/compiler-sfc': ^2.7.0 || ^3.0.0 react-router: '*' - vite: ^5.2.6 + vite: ^5.3.3 vue-router: '*' peerDependenciesMeta: '@solidjs/router': @@ -16003,7 +15715,7 @@ packages: optional: true dependencies: '@types/debug': 4.1.12 - '@vue/compiler-sfc': 3.4.29 + '@vue/compiler-sfc': 3.4.31 debug: 4.3.5 dequal: 2.0.3 extract-comments: 1.1.0 @@ -16011,19 +15723,19 @@ packages: json5: 2.2.3 local-pkg: 0.5.0 picocolors: 1.0.1 - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) vue-router: 4.4.0(vue@3.4.31) yaml: 2.4.5 transitivePeerDependencies: - supports-color dev: true - /vite-plugin-pwa@0.20.0(@vite-pwa/assets-generator@0.2.4)(vite@5.2.6)(workbox-build@7.1.0)(workbox-window@7.1.0): + /vite-plugin-pwa@0.20.0(@vite-pwa/assets-generator@0.2.4)(vite@5.3.3)(workbox-build@7.1.0)(workbox-window@7.1.0): resolution: {integrity: sha512-/kDZyqF8KqoXRpMUQtR5Atri/7BWayW8Gp7Kz/4bfstsV6zSFTxjREbXZYL7zSuRL40HGA+o2hvUAFRmC+bL7g==} engines: {node: '>=16.0.0'} peerDependencies: '@vite-pwa/assets-generator': ^0.2.4 - vite: ^5.2.6 + vite: ^5.3.3 workbox-build: ^7.1.0 workbox-window: ^7.1.0 peerDependenciesMeta: @@ -16034,18 +15746,18 @@ packages: debug: 4.3.4 fast-glob: 3.3.2 pretty-bytes: 6.1.1 - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) workbox-build: 7.1.0 workbox-window: 7.1.0 transitivePeerDependencies: - supports-color dev: true - /vite-plugin-solid@2.7.2(solid-js@1.8.3)(vite@5.2.6): + /vite-plugin-solid@2.7.2(solid-js@1.8.3)(vite@5.3.3): resolution: {integrity: sha512-GV2SMLAibOoXe76i02AsjAg7sbm/0lngBlERvJKVN67HOrJsHcWgkt0R6sfGLDJuFkv2aBe14Zm4vJcNME+7zw==} peerDependencies: solid-js: ^1.7.2 - vite: ^5.2.6 + vite: ^5.3.3 dependencies: '@babel/core': 7.23.3 '@babel/preset-typescript': 7.23.2(@babel/core@7.23.3) @@ -16054,50 +15766,14 @@ packages: merge-anything: 5.1.7 solid-js: 1.8.3 solid-refresh: 0.5.3(solid-js@1.8.3) - vite: 5.2.6(@types/node@20.14.9) - vitefu: 0.2.4(vite@5.2.6) + vite: 5.3.3(@types/node@20.14.9) + vitefu: 0.2.4(vite@5.3.3) transitivePeerDependencies: - supports-color dev: true - /vite@5.2.10(@types/node@20.14.9): - resolution: {integrity: sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 20.14.9 - esbuild: 0.20.2 - postcss: 8.4.38 - rollup: 4.18.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vite@5.2.6(@types/node@20.11.5): - resolution: {integrity: sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==} + /vite@5.3.3(@types/node@20.11.5): + resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -16125,15 +15801,15 @@ packages: optional: true dependencies: '@types/node': 20.11.5 - esbuild: 0.20.2 - postcss: 8.4.38 + esbuild: 0.21.5 + postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: fsevents: 2.3.3 dev: true - /vite@5.2.6(@types/node@20.14.9): - resolution: {integrity: sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==} + /vite@5.3.3(@types/node@20.14.9): + resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -16161,32 +15837,32 @@ packages: optional: true dependencies: '@types/node': 20.14.9 - esbuild: 0.20.2 - postcss: 8.4.38 + esbuild: 0.21.5 + postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: fsevents: 2.3.3 - /vitefu@0.2.4(vite@5.2.6): + /vitefu@0.2.4(vite@5.3.3): resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 peerDependenciesMeta: vite: optional: true dependencies: - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) dev: true - /vitefu@0.2.5(vite@5.2.6): + /vitefu@0.2.5(vite@5.3.3): resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} peerDependencies: - vite: ^5.2.6 + vite: ^5.3.3 peerDependenciesMeta: vite: optional: true dependencies: - vite: 5.2.6(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) dev: true /vitepress@1.2.3(@types/node@20.14.9)(postcss@8.4.38)(search-insights@2.9.0)(typescript@5.5.2): @@ -16206,7 +15882,7 @@ packages: '@shikijs/core': 1.6.4 '@shikijs/transformers': 1.6.4 '@types/markdown-it': 14.1.1 - '@vitejs/plugin-vue': 5.0.5(vite@5.2.10)(vue@3.4.31) + '@vitejs/plugin-vue': 5.0.5(vite@5.3.3)(vue@3.4.31) '@vue/devtools-api': 7.2.1(vue@3.4.31) '@vue/shared': 3.4.27 '@vueuse/core': 10.11.0(vue@3.4.31) @@ -16216,7 +15892,7 @@ packages: minisearch: 6.3.0 postcss: 8.4.38 shiki: 1.6.4 - vite: 5.2.10(@types/node@20.14.9) + vite: 5.3.3(@types/node@20.14.9) vue: 3.4.31(typescript@5.5.2) transitivePeerDependencies: - '@algolia/client-search' @@ -17166,7 +16842,7 @@ packages: hasBin: true optionalDependencies: '@types/fs-extra': 11.0.4 - '@types/node': 20.12.11 + '@types/node': 20.14.9 dev: true file:test/config/fixtures/conditions-subpackage: diff --git a/test/core/test/esnext.test.ts b/test/core/test/esnext.test.ts new file mode 100644 index 000000000..7ac73e5f5 --- /dev/null +++ b/test/core/test/esnext.test.ts @@ -0,0 +1,52 @@ +import { expect, it } from 'vitest' + +const [version] = process.version.slice(1).split('.') + +it.skipIf(Number(version) < 20)('"v" flag in regexp', () => { + const regexp = /\p{RGI_Emoji}|\P{Mark}\p{Mark}*/gv + expect('👍🏼👍🏼👍🏼'.match(regexp)).toEqual(['👍🏼', '👍🏼', '👍🏼']) +}) + +it('decorators work', () => { + expect(Sut.mocked).toBe(true) + expect(new Sut()).toBeInstanceOf(Sut) +}) + +it('new "using" feature', () => { + let getResource = (): any => { + throw new Error('don\'t call me') + } + { + using resource = resourceful('foo') + getResource = () => resource.resource + } + expect(getResource()).toBe(null) +}) + +// @ts-expect-error - readonly symbol, but might not be assigned +Symbol.dispose ??= Symbol('dispose') + +function resourceful(resourceDefault: string) { + let resource: string | null = resourceDefault + return { + get resource() { + return resource + }, + [Symbol.dispose]: () => { + resource = null + }, + } +} + +function exampleDecorator(ClassExample: any, context: ClassDecoratorContext): any { + if (context.kind !== 'class') { + throw new Error('not a class to decorate') + } + ClassExample.mocked = true + return ClassExample +} + +@exampleDecorator +class Sut { + static mocked = false +} -- 2.51.2 From 2e3c872ae4613a9aa6a06ee8a0fd920afdd4f693 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Thu, 4 Jul 2024 16:00:05 +0200 Subject: [PATCH 5/6] fix(browser): support shadow root and svg elements (#6036) --- packages/browser/src/client/tester/context.ts | 148 +++++++++-------- packages/browser/src/node/commands/clear.ts | 7 +- packages/browser/src/node/commands/click.ts | 21 ++- .../browser/src/node/commands/dragAndDrop.ts | 10 +- packages/browser/src/node/commands/fill.ts | 7 +- packages/browser/src/node/commands/hover.ts | 7 +- .../browser/src/node/commands/screenshot.ts | 13 +- packages/browser/src/node/commands/select.ts | 9 +- packages/browser/src/node/commands/type.ts | 7 +- test/browser/specs/runner.test.ts | 4 +- test/browser/test/click.test.ts | 15 -- test/browser/test/dom.test.ts | 37 +++++ test/browser/test/userEvent.test.ts | 149 +++++++++++++++++- 13 files changed, 306 insertions(+), 128 deletions(-) delete mode 100644 test/browser/test/click.test.ts diff --git a/packages/browser/src/client/tester/context.ts b/packages/browser/src/client/tester/context.ts index 2a8880d63..a4154864f 100644 --- a/packages/browser/src/client/tester/context.ts +++ b/packages/browser/src/client/tester/context.ts @@ -5,44 +5,6 @@ import type { BrowserRPC } from '../client' // this file should not import anything directly, only types -function convertElementToXPath(element: Element) { - if (!element || !(element instanceof Element)) { - throw new Error( - `Expected DOM element to be an instance of Element, received ${typeof element}`, - ) - } - - return getPathTo(element) -} - -function getPathTo(element: Element): string { - if (element.id !== '') { - return `id("${element.id}")` - } - - if (!element.parentNode || element === document.documentElement) { - return element.tagName - } - - let ix = 0 - const siblings = element.parentNode.childNodes - for (let i = 0; i < siblings.length; i++) { - const sibling = siblings[i] - if (sibling === element) { - return `${getPathTo(element.parentNode as Element)}/${element.tagName}[${ - ix + 1 - }]` - } - if ( - sibling.nodeType === 1 - && (sibling as Element).tagName === element.tagName - ) { - ix++ - } - } - return 'invalid xpath' -} - // @ts-expect-error not typed global const state = (): WorkerGlobalState => __vitest_worker__ // @ts-expect-error not typed global @@ -60,37 +22,99 @@ function triggerCommand(command: string, ...args: any[]) { const provider = runner().provider +function convertElementToCssSelector(element: Element) { + if (!element || !(element instanceof Element)) { + throw new Error( + `Expected DOM element to be an instance of Element, received ${typeof element}`, + ) + } + + return getUniqueCssSelector(element) +} + +function getUniqueCssSelector(el: Element) { + const path = [] + let parent: null | ParentNode + let hasShadowRoot = false + // eslint-disable-next-line no-cond-assign + while (parent = getParent(el)) { + if ((parent as Element).shadowRoot) { + hasShadowRoot = true + } + + const tag = el.tagName + if (el.id) { + path.push(`#${el.id}`) + } + else if (!el.nextElementSibling && !el.previousElementSibling) { + path.push(tag) + } + else { + let index = 0 + let sameTagSiblings = 0 + let elementIndex = 0 + + for (const sibling of parent.children) { + index++ + if (sibling.tagName === tag) { + sameTagSiblings++ + } + if (sibling === el) { + elementIndex = index + } + } + + if (sameTagSiblings > 1) { + path.push(`${tag}:nth-child(${elementIndex})`) + } + else { + path.push(tag) + } + } + el = parent as Element + }; + return `${provider === 'webdriverio' && hasShadowRoot ? '>>>' : ''}${path.reverse().join(' > ')}`.toLowerCase() +} + +function getParent(el: Element) { + const parent = el.parentNode + if (parent instanceof ShadowRoot) { + return parent.host + } + return parent +} + export const userEvent: UserEvent = { // TODO: actually setup userEvent with config options setup() { return userEvent }, click(element: Element, options: UserEventClickOptions = {}) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_click', xpath, options) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_click', css, options) }, dblClick(element: Element, options: UserEventClickOptions = {}) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_dblClick', xpath, options) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_dblClick', css, options) }, tripleClick(element: Element, options: UserEventClickOptions = {}) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_tripleClick', xpath, options) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_tripleClick', css, options) }, selectOptions(element, value) { const values = provider === 'webdriverio' ? getWebdriverioSelectOptions(element, value) : getSimpleSelectOptions(element, value) - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_selectOptions', xpath, values) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_selectOptions', css, values) }, type(element: Element, text: string, options: UserEventTypeOptions = {}) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_type', xpath, text, options) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_type', css, text, options) }, clear(element: Element) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_clear', xpath) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_clear', css) }, tab(options: UserEventTabOptions = {}) { return triggerCommand('__vitest_tab', options) @@ -99,23 +123,23 @@ export const userEvent: UserEvent = { return triggerCommand('__vitest_keyboard', text) }, hover(element: Element) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_hover', xpath) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_hover', css) }, unhover(element: Element) { - const xpath = convertElementToXPath(element.ownerDocument.body) - return triggerCommand('__vitest_hover', xpath) + const css = convertElementToCssSelector(element.ownerDocument.body) + return triggerCommand('__vitest_hover', css) }, // non userEvent events, but still useful fill(element: Element, text: string, options) { - const xpath = convertElementToXPath(element) - return triggerCommand('__vitest_fill', xpath, text, options) + const css = convertElementToCssSelector(element) + return triggerCommand('__vitest_fill', css, text, options) }, dragAndDrop(source: Element, target: Element, options = {}) { - const sourceXpath = convertElementToXPath(source) - const targetXpath = convertElementToXPath(target) - return triggerCommand('__vitest_dragAndDrop', sourceXpath, targetXpath, options) + const sourceCss = convertElementToCssSelector(source) + const targetCss = convertElementToCssSelector(target) + return triggerCommand('__vitest_dragAndDrop', sourceCss, targetCss, options) }, } @@ -137,7 +161,7 @@ function getWebdriverioSelectOptions(element: Element, value: string | string[] if (typeof optionValue !== 'string') { const index = options.indexOf(optionValue as HTMLOptionElement) if (index === -1) { - throw new Error(`The element ${convertElementToXPath(optionValue)} was not found in the "select" options.`) + throw new Error(`The element ${convertElementToCssSelector(optionValue)} was not found in the "select" options.`) } return [{ index }] @@ -162,7 +186,7 @@ function getWebdriverioSelectOptions(element: Element, value: string | string[] function getSimpleSelectOptions(element: Element, value: string | string[] | HTMLElement[] | HTMLElement) { return (Array.isArray(value) ? value : [value]).map((v) => { if (typeof v !== 'string') { - return { element: convertElementToXPath(v) } + return { element: convertElementToCssSelector(v) } } return v }) @@ -220,7 +244,7 @@ export const page: BrowserPage = { return triggerCommand('__vitest_screenshot', name, { ...options, element: options.element - ? convertElementToXPath(options.element) + ? convertElementToCssSelector(options.element) : undefined, }) }, diff --git a/packages/browser/src/node/commands/clear.ts b/packages/browser/src/node/commands/clear.ts index 96bfd4c65..a06f3b4a3 100644 --- a/packages/browser/src/node/commands/clear.ts +++ b/packages/browser/src/node/commands/clear.ts @@ -5,19 +5,18 @@ import type { UserEventCommand } from './utils' export const clear: UserEventCommand = async ( context, - xpath, + selector, ) => { if (context.provider instanceof PlaywrightBrowserProvider) { const { iframe } = context - const element = iframe.locator(`xpath=${xpath}`) + const element = iframe.locator(`css=${selector}`) await element.clear({ timeout: 1000, }) } else if (context.provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` - const element = await browser.$(markedXpath) + const element = await browser.$(selector) await element.clearValue() } else { diff --git a/packages/browser/src/node/commands/click.ts b/packages/browser/src/node/commands/click.ts index d01c8f276..b939513bd 100644 --- a/packages/browser/src/node/commands/click.ts +++ b/packages/browser/src/node/commands/click.ts @@ -5,21 +5,20 @@ import type { UserEventCommand } from './utils' export const click: UserEventCommand = async ( context, - xpath, + selector, options = {}, ) => { const provider = context.provider if (provider instanceof PlaywrightBrowserProvider) { const tester = context.iframe - await tester.locator(`xpath=${xpath}`).click({ + await tester.locator(`css=${selector}`).click({ timeout: 1000, ...options, }) } else if (provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` - await browser.$(markedXpath).click(options as any) + await browser.$(selector).click(options as any) } else { throw new TypeError(`Provider "${provider.name}" doesn't support click command`) @@ -28,18 +27,17 @@ export const click: UserEventCommand = async ( export const dblClick: UserEventCommand = async ( context, - xpath, + selector, options = {}, ) => { const provider = context.provider if (provider instanceof PlaywrightBrowserProvider) { const tester = context.iframe - await tester.locator(`xpath=${xpath}`).dblclick(options) + await tester.locator(`css=${selector}`).dblclick(options) } else if (provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` - await browser.$(markedXpath).doubleClick() + await browser.$(selector).doubleClick() } else { throw new TypeError(`Provider "${provider.name}" doesn't support dblClick command`) @@ -48,13 +46,13 @@ export const dblClick: UserEventCommand = async ( export const tripleClick: UserEventCommand = async ( context, - xpath, + selector, options = {}, ) => { const provider = context.provider if (provider instanceof PlaywrightBrowserProvider) { const tester = context.iframe - await tester.locator(`xpath=${xpath}`).click({ + await tester.locator(`css=${selector}`).click({ timeout: 1000, ...options, clickCount: 3, @@ -62,11 +60,10 @@ export const tripleClick: UserEventCommand = async ( } else if (provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` await browser .action('pointer', { parameters: { pointerType: 'mouse' } }) // move the pointer over the button - .move({ origin: await browser.$(markedXpath) }) + .move({ origin: await browser.$(selector) }) // simulate 3 clicks .down() .up() diff --git a/packages/browser/src/node/commands/dragAndDrop.ts b/packages/browser/src/node/commands/dragAndDrop.ts index 03d6740d5..61af689ff 100644 --- a/packages/browser/src/node/commands/dragAndDrop.ts +++ b/packages/browser/src/node/commands/dragAndDrop.ts @@ -12,8 +12,8 @@ export const dragAndDrop: UserEventCommand = async ( if (context.provider instanceof PlaywrightBrowserProvider) { const frame = await context.frame() await frame.dragAndDrop( - `xpath=${source}`, - `xpath=${target}`, + `css=${source}`, + `css=${target}`, { timeout: 1000, ...options, @@ -21,10 +21,8 @@ export const dragAndDrop: UserEventCommand = async ( ) } else if (context.provider instanceof WebdriverBrowserProvider) { - const sourceXpath = `//${source}` - const targetXpath = `//${target}` - const $source = context.browser.$(sourceXpath) - const $target = context.browser.$(targetXpath) + const $source = context.browser.$(source) + const $target = context.browser.$(target) const duration = (options as any)?.duration ?? 10 // https://github.com/webdriverio/webdriverio/issues/8022#issuecomment-1700919670 diff --git a/packages/browser/src/node/commands/fill.ts b/packages/browser/src/node/commands/fill.ts index 866c2165a..11468afdb 100644 --- a/packages/browser/src/node/commands/fill.ts +++ b/packages/browser/src/node/commands/fill.ts @@ -5,19 +5,18 @@ import type { UserEventCommand } from './utils' export const fill: UserEventCommand = async ( context, - xpath, + selector, text, options = {}, ) => { if (context.provider instanceof PlaywrightBrowserProvider) { const { iframe } = context - const element = iframe.locator(`xpath=${xpath}`) + const element = iframe.locator(`css=${selector}`) await element.fill(text, { timeout: 1000, ...options }) } else if (context.provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` - await browser.$(markedXpath).setValue(text) + await browser.$(selector).setValue(text) } else { throw new TypeError(`Provider "${context.provider.name}" does not support clearing elements`) diff --git a/packages/browser/src/node/commands/hover.ts b/packages/browser/src/node/commands/hover.ts index 043c9e21c..fa82faa43 100644 --- a/packages/browser/src/node/commands/hover.ts +++ b/packages/browser/src/node/commands/hover.ts @@ -5,19 +5,18 @@ import type { UserEventCommand } from './utils' export const hover: UserEventCommand = async ( context, - xpath, + selector, options = {}, ) => { if (context.provider instanceof PlaywrightBrowserProvider) { - await context.iframe.locator(`xpath=${xpath}`).hover({ + await context.iframe.locator(`css=${selector}`).hover({ timeout: 1000, ...options, }) } else if (context.provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` - await browser.$(markedXpath).moveTo(options) + await browser.$(selector).moveTo(options) } else { throw new TypeError(`Provider "${context.provider.name}" does not support hover`) diff --git a/packages/browser/src/node/commands/screenshot.ts b/packages/browser/src/node/commands/screenshot.ts index 211e12f13..d81b0932b 100644 --- a/packages/browser/src/node/commands/screenshot.ts +++ b/packages/browser/src/node/commands/screenshot.ts @@ -27,9 +27,13 @@ export const screenshot: BrowserCommand<[string, ScreenshotOptions]> = async ( if (context.provider instanceof PlaywrightBrowserProvider) { if (options.element) { - const { element: elementXpath, ...config } = options - const element = context.iframe.locator(`xpath=${elementXpath}`) - const buffer = await element.screenshot({ ...config, path: savePath }) + const { element: css, ...config } = options + const element = context.iframe.locator(`css=${css}`) + const buffer = await element.screenshot({ + timeout: 1000, + ...config, + path: savePath, + }) return returnResult(options, path, buffer) } @@ -48,8 +52,7 @@ export const screenshot: BrowserCommand<[string, ScreenshotOptions]> = async ( return returnResult(options, path, buffer) } - const xpath = `//${options.element}` - const element = await page.$(xpath) + const element = await page.$(`${options.element}`) const buffer = await element.saveScreenshot(savePath) return returnResult(options, path, buffer) } diff --git a/packages/browser/src/node/commands/select.ts b/packages/browser/src/node/commands/select.ts index 14adf30d9..936071979 100644 --- a/packages/browser/src/node/commands/select.ts +++ b/packages/browser/src/node/commands/select.ts @@ -6,20 +6,20 @@ import type { UserEventCommand } from './utils' export const selectOptions: UserEventCommand = async ( context, - xpath, + selector, userValues, options = {}, ) => { if (context.provider instanceof PlaywrightBrowserProvider) { const value = userValues as any as (string | { element: string })[] const { iframe } = context - const selectElement = iframe.locator(`xpath=${xpath}`) + const selectElement = iframe.locator(`css=${selector}`) const values = await Promise.all(value.map(async (v) => { if (typeof v === 'string') { return v } - const elementHandler = await iframe.locator(`xpath=${v.element}`).elementHandle() + const elementHandler = await iframe.locator(`css=${v.element}`).elementHandle() if (!elementHandler) { throw new Error(`Element not found: ${v.element}`) } @@ -38,11 +38,10 @@ export const selectOptions: UserEventCommand = async return } - const markedXpath = `//${xpath}` const browser = context.browser if (values.length === 1 && 'index' in values[0]) { - const selectElement = browser.$(markedXpath) + const selectElement = browser.$(selector) await selectElement.selectByIndex(values[0].index) } else { diff --git a/packages/browser/src/node/commands/type.ts b/packages/browser/src/node/commands/type.ts index e94850943..ff79fb7e9 100644 --- a/packages/browser/src/node/commands/type.ts +++ b/packages/browser/src/node/commands/type.ts @@ -6,7 +6,7 @@ import { keyboardImplementation } from './keyboard' export const type: UserEventCommand = async ( context, - xpath, + selector, text, options = {}, ) => { @@ -14,7 +14,7 @@ export const type: UserEventCommand = async ( if (context.provider instanceof PlaywrightBrowserProvider) { const { iframe } = context - const element = iframe.locator(`xpath=${xpath}`) + const element = iframe.locator(`css=${selector}`) if (!skipClick) { await element.focus() @@ -30,8 +30,7 @@ export const type: UserEventCommand = async ( } else if (context.provider instanceof WebdriverBrowserProvider) { const browser = context.browser - const markedXpath = `//${xpath}` - const element = browser.$(markedXpath) + const element = browser.$(selector) if (!skipClick && !await element.isFocused()) { await element.click() diff --git a/test/browser/specs/runner.test.ts b/test/browser/specs/runner.test.ts index 396841a0c..5065cc349 100644 --- a/test/browser/specs/runner.test.ts +++ b/test/browser/specs/runner.test.ts @@ -23,8 +23,8 @@ describe('running browser tests', async () => { console.error(stderr) }) - expect(browserResultJson.testResults).toHaveLength(19) - expect(passedTests).toHaveLength(17) + expect(browserResultJson.testResults).toHaveLength(18) + expect(passedTests).toHaveLength(16) expect(failedTests).toHaveLength(2) expect(stderr).not.toContain('has been externalized for browser compatibility') diff --git a/test/browser/test/click.test.ts b/test/browser/test/click.test.ts deleted file mode 100644 index 6e72ddf41..000000000 --- a/test/browser/test/click.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { userEvent } from '@vitest/browser/context' -import { expect, test, vi } from 'vitest' - -test('clicks on an element', async () => { - const button = document.createElement('button') - button.textContent = 'Hello World' - const fn = vi.fn() - button.onclick = () => { - fn() - } - document.body.appendChild(button) - - await userEvent.click(button) - expect(fn).toHaveBeenCalled() -}) diff --git a/test/browser/test/dom.test.ts b/test/browser/test/dom.test.ts index c906600ed..6014cef11 100644 --- a/test/browser/test/dom.test.ts +++ b/test/browser/test/dom.test.ts @@ -37,6 +37,43 @@ describe('dom related activity', () => { ) expect(base64).toBeTypeOf('string') }) + + test('shadow dom screenshot', async () => { + const wrapper = createWrapper() + const div = createNode() + wrapper.appendChild(div) + + const shadow = div.attachShadow({ mode: 'open' }) + const shadowDiv = createNode() + shadow.appendChild(shadowDiv) + + const screenshotPath = await page.screenshot({ + element: shadowDiv, + }) + expect(screenshotPath).toMatch( + /__screenshots__\/dom.test.ts\/dom-related-activity-shadow-dom-screenshot-1.png/, + ) + }) + + test('svg screenshot', async () => { + const wrapper = createWrapper() + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + svg.setAttribute('width', '100') + svg.setAttribute('height', '100') + const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect') + rect.setAttribute('width', '100') + rect.setAttribute('height', '100') + rect.setAttribute('fill', 'red') + svg.appendChild(rect) + wrapper.appendChild(svg) + + const screenshotPath = await page.screenshot({ + element: svg, + }) + expect(screenshotPath).toMatch( + /__screenshots__\/dom.test.ts\/dom-related-activity-svg-screenshot-1.png/, + ) + }) }) function createWrapper() { diff --git a/test/browser/test/userEvent.test.ts b/test/browser/test/userEvent.test.ts index b02b64ebf..d71fd29b7 100644 --- a/test/browser/test/userEvent.test.ts +++ b/test/browser/test/userEvent.test.ts @@ -37,6 +37,37 @@ describe('userEvent.click', () => { expect(onClick).not.toHaveBeenCalled() }) + + test('click inside shadow dom', async () => { + const shadowRoot = createShadowRoot() + const button = document.createElement('button') + button.textContent = 'Click me' + shadowRoot.appendChild(button) + + const onClick = vi.fn() + button.addEventListener('click', onClick) + + await userEvent.click(button) + + expect(onClick).toHaveBeenCalled() + }) + + test('clicks inside svg', async () => { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + circle.setAttribute('cx', '50') + circle.setAttribute('cy', '50') + circle.setAttribute('r', '40') + svg.appendChild(circle) + document.body.appendChild(svg) + + const onClick = vi.fn() + circle.addEventListener('click', onClick) + + await userEvent.click(circle) + + expect(onClick).toHaveBeenCalled() + }) }) describe('userEvent.dblClick', () => { @@ -154,6 +185,79 @@ describe('userEvent.hover, userEvent.unhover', () => { expect(pointerEntered).toBe(false) expect(mouseEntered).toBe(false) }) + + test('hover works with shadow root', async () => { + const shadowRoot = createShadowRoot() + const target = document.createElement('div') + target.style.width = '100px' + target.style.height = '100px' + + let mouseEntered = false + let pointerEntered = false + target.addEventListener('mouseover', () => { + mouseEntered = true + }) + target.addEventListener('pointerenter', () => { + pointerEntered = true + }) + target.addEventListener('pointerleave', () => { + pointerEntered = false + }) + target.addEventListener('mouseout', () => { + mouseEntered = false + }) + + shadowRoot.appendChild(target) + + await userEvent.hover(target) + + expect(pointerEntered).toBe(true) + expect(mouseEntered).toBe(true) + + await userEvent.unhover(target) + + expect(pointerEntered).toBe(false) + expect(mouseEntered).toBe(false) + }) + + test('hover works with svg', async () => { + const target = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle') + circle.setAttribute('cx', '50') + circle.setAttribute('cy', '50') + circle.setAttribute('r', '40') + target.appendChild(circle) + document.body.appendChild(target) + target.style.width = '100px' + target.style.height = '100px' + + let mouseEntered = false + let pointerEntered = false + target.addEventListener('mouseover', () => { + mouseEntered = true + }) + target.addEventListener('pointerenter', () => { + pointerEntered = true + }) + target.addEventListener('pointerleave', () => { + pointerEntered = false + }) + target.addEventListener('mouseout', () => { + mouseEntered = false + }) + + document.body.appendChild(target) + + await userEvent.hover(target) + + expect(pointerEntered).toBe(true) + expect(mouseEntered).toBe(true) + + await userEvent.unhover(target) + + expect(pointerEntered).toBe(false) + expect(mouseEntered).toBe(false) + }) }) const inputLike = [ @@ -161,19 +265,16 @@ const inputLike = [ const input = document.createElement('input') input.type = 'text' input.placeholder = 'Type here' - document.body.appendChild(input) return input }, () => { const input = document.createElement('textarea') input.placeholder = 'Type here' - document.body.appendChild(input) return input }, () => { const contentEditable = document.createElement('div') contentEditable.contentEditable = 'true' - document.body.appendChild(contentEditable) return contentEditable }, ] @@ -301,6 +402,21 @@ describe.each(inputLike)('userEvent.type', (getElement) => { ]) }) + test('types into a shadow root input', async () => { + const shadowRoot = createShadowRoot() + const { input, keydown, value } = createTextInput(shadowRoot) + + await userEvent.type(input, 'Hello') + expect(value()).toBe('Hello') + expect(keydown).toEqual([ + 'H', + 'e', + 'l', + 'l', + 'o', + ]) + }) + // strangly enough, original userEvent doesn't support this, // but we can implement it test.skipIf(server.provider === 'preview')('selectall works correctly', async () => { @@ -314,7 +430,7 @@ describe.each(inputLike)('userEvent.type', (getElement) => { expect(input.value).toBe('') }) - function createTextInput() { + function createTextInput(root: Node = document.body) { const input = getElement() const keydown: string[] = [] const keyup: string[] = [] @@ -324,7 +440,7 @@ describe.each(inputLike)('userEvent.type', (getElement) => { input.addEventListener('keyup', (event: KeyboardEvent) => { keyup.push(event.key) }) - document.body.appendChild(input) + root.appendChild(input) return { input, keydown, @@ -362,6 +478,7 @@ describe('userEvent.tab', () => { describe.each(inputLike)('userEvent.fill', async (getInput) => { test('correctly fills the input value', async () => { const input = getInput() + document.body.appendChild(input) function value() { if ('value' in input) { return input.value @@ -375,6 +492,21 @@ describe.each(inputLike)('userEvent.fill', async (getInput) => { await userEvent.fill(input, 'Another Value') expect(value()).toBe('Another Value') }) + + test('fill input in shadow root', async () => { + const input = getInput() + const shadowRoot = createShadowRoot() + shadowRoot.appendChild(input) + function value() { + if ('value' in input) { + return input.value + } + return input.textContent + } + + await userEvent.fill(input, 'Hello') + expect(value()).toBe('Hello') + }) }) describe('userEvent.keyboard', async () => { @@ -600,3 +732,10 @@ describe.each([ }) }) }) + +function createShadowRoot() { + const div = document.createElement('div') + const shadowRoot = div.attachShadow({ mode: 'open' }) + document.body.appendChild(div) + return shadowRoot +} -- 2.51.2 From 56118954e62b71ff9b53e096616511f9ecadc1ee Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Thu, 4 Jul 2024 16:01:10 +0200 Subject: [PATCH 6/6] chore: release v2.0.0-beta.13 --- package.json | 2 +- packages/browser/package.json | 2 +- packages/coverage-istanbul/package.json | 2 +- packages/coverage-v8/package.json | 2 +- packages/expect/package.json | 2 +- packages/runner/package.json | 2 +- packages/snapshot/package.json | 2 +- packages/spy/package.json | 2 +- packages/ui/package.json | 2 +- packages/utils/package.json | 2 +- packages/vite-node/package.json | 2 +- packages/vitest/package.json | 2 +- packages/web-worker/package.json | 2 +- packages/ws-client/package.json | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 53e2efa3a..edeac8ab6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/monorepo", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "private": true, "packageManager": "pnpm@8.15.8", "description": "Next generation testing framework powered by Vite", diff --git a/packages/browser/package.json b/packages/browser/package.json index 018ae7cbd..607a1a52d 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/browser", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "Browser running for Vitest", "license": "MIT", "funding": "https://opencollective.com/vitest", diff --git a/packages/coverage-istanbul/package.json b/packages/coverage-istanbul/package.json index 19470d965..b44ddb069 100644 --- a/packages/coverage-istanbul/package.json +++ b/packages/coverage-istanbul/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/coverage-istanbul", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "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 3f424951f..f4d043faf 100644 --- a/packages/coverage-v8/package.json +++ b/packages/coverage-v8/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/coverage-v8", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "V8 coverage provider for Vitest", "author": "Anthony Fu ", "license": "MIT", diff --git a/packages/expect/package.json b/packages/expect/package.json index 93095c084..f83a5eb8b 100644 --- a/packages/expect/package.json +++ b/packages/expect/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/expect", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "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 eb1cb35ef..b5003c8cd 100644 --- a/packages/runner/package.json +++ b/packages/runner/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/runner", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "Vitest test runner", "license": "MIT", "funding": "https://opencollective.com/vitest", diff --git a/packages/snapshot/package.json b/packages/snapshot/package.json index d9e2874f8..74d734138 100644 --- a/packages/snapshot/package.json +++ b/packages/snapshot/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/snapshot", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "Vitest snapshot manager", "license": "MIT", "funding": "https://opencollective.com/vitest", diff --git a/packages/spy/package.json b/packages/spy/package.json index 42219b52e..83c31dc67 100644 --- a/packages/spy/package.json +++ b/packages/spy/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/spy", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "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 d05bb305c..c1856f5f0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/ui", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "UI for Vitest", "license": "MIT", "funding": "https://opencollective.com/vitest", diff --git a/packages/utils/package.json b/packages/utils/package.json index ddeddc39d..8444565c9 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/utils", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "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 e7db66a86..187a3bcf1 100644 --- a/packages/vite-node/package.json +++ b/packages/vite-node/package.json @@ -1,7 +1,7 @@ { "name": "vite-node", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "Vite as Node.js runtime", "author": "Anthony Fu ", "license": "MIT", diff --git a/packages/vitest/package.json b/packages/vitest/package.json index 1764d156d..013609d69 100644 --- a/packages/vitest/package.json +++ b/packages/vitest/package.json @@ -1,7 +1,7 @@ { "name": "vitest", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "Next generation testing framework powered by Vite", "author": "Anthony Fu ", "license": "MIT", diff --git a/packages/web-worker/package.json b/packages/web-worker/package.json index 1fd20a072..23503574b 100644 --- a/packages/web-worker/package.json +++ b/packages/web-worker/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/web-worker", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "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 65de336bb..d1e6c5f95 100644 --- a/packages/ws-client/package.json +++ b/packages/ws-client/package.json @@ -1,7 +1,7 @@ { "name": "@vitest/ws-client", "type": "module", - "version": "2.0.0-beta.12", + "version": "2.0.0-beta.13", "description": "WebSocket client wrapper for communicating with Vitest", "author": "Anthony Fu ", "license": "MIT", -- 2.51.2