vitest 4.0.0-beta.10 → 4.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +85 -101
- package/dist/browser.d.ts +10 -6
- package/dist/browser.js +8 -5
- package/dist/chunks/{benchmark.CJUa-Hsa.js → benchmark.DHKMYAts.js} +2 -2
- package/dist/chunks/{browser.d.yFAklsD1.d.ts → browser.d.D9YV3JvA.d.ts} +1 -1
- package/dist/chunks/{cac.DCxo_nSu.js → cac.r1gel_VZ.js} +18 -11
- package/dist/chunks/{cli-api.BJJXh9BV.js → cli-api.CpywZzJV.js} +153 -176
- package/dist/chunks/{config.d.B_LthbQq.d.ts → config.d.DGazh2r6.d.ts} +3 -1
- package/dist/chunks/{console.7h5kHUIf.js → console.CTJL2nuH.js} +4 -6
- package/dist/chunks/{coverage.BCU-r2QL.js → coverage.CiB0fs_7.js} +57 -79
- package/dist/chunks/{creator.08Gi-vCA.js → creator.DfXDsUyL.js} +6 -8
- package/dist/chunks/{global.d.BK3X7FW1.d.ts → global.d.BcFPD2LN.d.ts} +0 -13
- package/dist/chunks/{globals.DG-S3xFe.js → globals.DC4ntO86.js} +8 -6
- package/dist/chunks/{index.DIWhzsUh.js → index.Bt-upxGS.js} +6 -12
- package/dist/chunks/{index.BIP7prJq.js → index.CHrBLuEH.js} +94 -103
- package/dist/chunks/{index.X0nbfr6-.js → index.Dc3xnDvT.js} +48 -289
- package/dist/chunks/{index.CMfqw92x.js → index.Dnl38iQ_.js} +2 -2
- package/dist/chunks/{index.BjKEiSn0.js → index.uLUz1RDt.js} +3 -3
- package/dist/chunks/{inspector.CvQD-Nie.js → inspector.Br76Q2Mb.js} +1 -4
- package/dist/chunks/{moduleRunner.d.D9nBoC4p.d.ts → moduleRunner.d.CeYc7nZ0.d.ts} +1 -1
- package/dist/chunks/{node.CyipiPvJ.js → node.BwAWWjHZ.js} +3 -4
- package/dist/chunks/{plugin.d.BMVSnsGV.d.ts → plugin.d.XreRXLXS.d.ts} +1 -1
- package/dist/chunks/{reporters.d.BUWjmRYq.d.ts → reporters.d.CJVTaaWb.d.ts} +54 -13
- package/dist/chunks/{resolveSnapshotEnvironment.Bkht6Yor.js → resolveSnapshotEnvironment.BsJpmVZR.js} +7 -8
- package/dist/chunks/{rpc.BKr6mtxz.js → rpc.cD77ENhU.js} +13 -14
- package/dist/chunks/{setup-common.uiMcU3cv.js → setup-common.BewgbkTd.js} +6 -6
- package/dist/chunks/{startModuleRunner.p67gbNo9.js → startModuleRunner.DPBo3mme.js} +65 -56
- package/dist/chunks/{test.BiqSKISg.js → test.CTuWuHYH.js} +7 -7
- package/dist/chunks/{typechecker.DB-fIMaH.js → typechecker.BfOQ86_a.js} +624 -14
- package/dist/chunks/{utils.D2R2NiOH.js → utils.CG9h5ccR.js} +2 -5
- package/dist/chunks/{vi.ZPgvtBao.js → vi.B2--mG9U.js} +38 -145
- package/dist/{worker.js → chunks/worker.DVTUM2IW.js} +71 -42
- package/dist/chunks/{worker.d.BDsXGkwh.d.ts → worker.d.buwuBpBt.d.ts} +2 -77
- package/dist/cli.js +7 -5
- package/dist/config.d.ts +6 -6
- package/dist/coverage.d.ts +5 -5
- package/dist/coverage.js +4 -5
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +8 -6
- package/dist/module-evaluator.d.ts +3 -3
- package/dist/module-evaluator.js +11 -13
- package/dist/module-runner.js +5 -5
- package/dist/node.d.ts +14 -11
- package/dist/node.js +18 -14
- package/dist/reporters.d.ts +5 -5
- package/dist/reporters.js +7 -5
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +9 -7
- package/dist/snapshot.js +3 -3
- package/dist/suite.js +4 -3
- package/dist/{chunks/base.Cjha6usc.js → worker-base.js} +104 -32
- package/dist/{chunks/vm.Ca0Y0W5f.js → worker-vm.js} +81 -31
- package/dist/workers/runVmTests.js +14 -11
- package/package.json +26 -26
- package/browser.d.ts +0 -1
- package/dist/chunks/moduleTransport.I-bgQy0S.js +0 -19
- package/dist/chunks/resolver.Bx6lE0iq.js +0 -119
- package/dist/chunks/utils.C2YI6McM.js +0 -52
- package/dist/chunks/worker.d.BNcX_2mH.d.ts +0 -8
- package/dist/workers/forks.js +0 -67
- package/dist/workers/threads.js +0 -55
- package/dist/workers/vmForks.js +0 -48
- package/dist/workers/vmThreads.js +0 -38
- package/dist/workers.d.ts +0 -38
- package/dist/workers.js +0 -48
- package/execute.d.ts +0 -1
- package/utils.d.ts +0 -1
- package/workers.d.ts +0 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import fs, { promises, existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import fs, { promises, existsSync, readFileSync, statSync, readdirSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { relative, resolve, dirname, extname, normalize, join, basename, isAbsolute } from 'pathe';
|
|
3
3
|
import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
|
|
4
4
|
import path, { resolve as resolve$1 } from 'node:path';
|
|
5
|
-
import { noop, createDefer, slash,
|
|
6
|
-
import {
|
|
5
|
+
import { noop, createDefer, slash, toArray, cleanUrl, deepMerge, nanoid, deepClone, isPrimitive, notNullish } from '@vitest/utils/helpers';
|
|
6
|
+
import { a as any, p as prompt } from './index.Dc3xnDvT.js';
|
|
7
7
|
import * as vite from 'vite';
|
|
8
8
|
import { parseAst, searchForWorkspaceRoot, version, mergeConfig, createServer } from 'vite';
|
|
9
9
|
import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
|
|
10
10
|
import nodeos__default, { tmpdir } from 'node:os';
|
|
11
|
-
import { generateHash as generateHash$1, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, hasFailed, getTasks,
|
|
11
|
+
import { generateHash as generateHash$1, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, hasFailed, getTasks, isTestCase } from '@vitest/runner/utils';
|
|
12
12
|
import { SnapshotManager } from '@vitest/snapshot/manager';
|
|
13
|
-
import { v as version$1 } from './cac.
|
|
13
|
+
import { v as version$1 } from './cac.r1gel_VZ.js';
|
|
14
14
|
import { c as createBirpc } from './index.Bgo3tNWt.js';
|
|
15
|
-
import { p as parse,
|
|
15
|
+
import { p as parse, d as stringify, e as printError, f as formatProjectName, w as withLabel, h as errorBanner, i as divider, j as generateCodeFrame, R as ReportersMap, B as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.CHrBLuEH.js';
|
|
16
16
|
import require$$0$3 from 'events';
|
|
17
17
|
import require$$1$1 from 'https';
|
|
18
18
|
import require$$2 from 'http';
|
|
@@ -26,14 +26,14 @@ import require$$0$1 from 'buffer';
|
|
|
26
26
|
import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
|
|
27
27
|
import crypto, { createHash } from 'node:crypto';
|
|
28
28
|
import { distDir, rootDir } from '../path.js';
|
|
29
|
-
import { h as hash, d as createFetchModuleFunction, n as normalizeResolvedIdToUrl, R as RandomSequencer, i as isPackageExists, g as getFilePoolName, e as isBrowserEnabled, r as resolveConfig, f as groupBy, j as getCoverageProvider, k as createPool, w as wildcardPatternToRegExp, a as resolveApiServerConfig, s as stdout } from './coverage.
|
|
30
|
-
import { b as
|
|
31
|
-
import { TraceMap, originalPositionFor, parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
29
|
+
import { h as hash, d as createFetchModuleFunction, n as normalizeResolvedIdToUrl, R as RandomSequencer, i as isPackageExists, g as getFilePoolName, e as isBrowserEnabled, r as resolveConfig, f as groupBy, j as getCoverageProvider, k as createPool, w as wildcardPatternToRegExp, a as resolveApiServerConfig, s as stdout } from './coverage.CiB0fs_7.js';
|
|
30
|
+
import { b as TraceMap, o as originalPositionFor, c as ancestor, d as createDefinesScript, e as convertTasksToEvents } from './typechecker.BfOQ86_a.js';
|
|
32
31
|
import createDebug from 'debug';
|
|
33
32
|
import { VitestModuleEvaluator } from '#module-evaluator';
|
|
34
33
|
import { ModuleRunner } from 'vite/module-runner';
|
|
35
34
|
import { Console } from 'node:console';
|
|
36
35
|
import c from 'tinyrainbow';
|
|
36
|
+
import { highlight } from '@vitest/utils/highlight';
|
|
37
37
|
import { createRequire, builtinModules, isBuiltin } from 'node:module';
|
|
38
38
|
import url, { pathToFileURL } from 'node:url';
|
|
39
39
|
import { i as isTTY, a as isWindows } from './env.D4Lgay0q.js';
|
|
@@ -43,11 +43,13 @@ import { glob, isDynamicPattern } from 'tinyglobby';
|
|
|
43
43
|
import MagicString from 'magic-string';
|
|
44
44
|
import { hoistMocksPlugin, automockPlugin } from '@vitest/mocker/node';
|
|
45
45
|
import { c as configDefaults } from './defaults.CXFFjsi8.js';
|
|
46
|
-
import {
|
|
46
|
+
import { KNOWN_ASSET_RE } from '@vitest/utils/constants';
|
|
47
|
+
import { findNearestPackageData } from '@vitest/utils/resolver';
|
|
47
48
|
import * as esModuleLexer from 'es-module-lexer';
|
|
48
|
-
import { a as BenchmarkReportsMap } from './index.
|
|
49
|
+
import { a as BenchmarkReportsMap } from './index.uLUz1RDt.js';
|
|
49
50
|
import assert$1 from 'node:assert';
|
|
50
|
-
import {
|
|
51
|
+
import { serializeValue } from '@vitest/utils/serialize';
|
|
52
|
+
import { parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
51
53
|
import readline from 'node:readline';
|
|
52
54
|
import { stripVTControlCharacters } from 'node:util';
|
|
53
55
|
|
|
@@ -5081,8 +5083,8 @@ catch {}
|
|
|
5081
5083
|
}
|
|
5082
5084
|
|
|
5083
5085
|
function setup(ctx, _server) {
|
|
5084
|
-
const wss = new WebSocketServer({ noServer: true }), clients = /* @__PURE__ */ new Map()
|
|
5085
|
-
|
|
5086
|
+
const wss = new WebSocketServer({ noServer: true }), clients = /* @__PURE__ */ new Map();
|
|
5087
|
+
(_server || ctx.vite).httpServer?.on("upgrade", (request, socket, head) => {
|
|
5086
5088
|
if (!request.url) return;
|
|
5087
5089
|
const { pathname } = new URL(request.url, "http://localhost");
|
|
5088
5090
|
if (pathname === API_PATH) {
|
|
@@ -5148,8 +5150,7 @@ function setup(ctx, _server) {
|
|
|
5148
5150
|
return ctx.state.getUnhandledErrors();
|
|
5149
5151
|
},
|
|
5150
5152
|
async getTestFiles() {
|
|
5151
|
-
|
|
5152
|
-
return spec.map((spec) => [
|
|
5153
|
+
return (await ctx.globTestSpecifications()).map((spec) => [
|
|
5153
5154
|
{
|
|
5154
5155
|
name: spec.project.config.name,
|
|
5155
5156
|
root: spec.project.config.root
|
|
@@ -5338,17 +5339,13 @@ function createFailedFileTask(project, filepath, error) {
|
|
|
5338
5339
|
return file.file = file, file;
|
|
5339
5340
|
}
|
|
5340
5341
|
function serializeError(ctx, error) {
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
});
|
|
5349
|
-
return errors;
|
|
5350
|
-
}
|
|
5351
|
-
return [{
|
|
5342
|
+
return "errors" in error && "pluginCode" in error ? error.errors.map((e) => {
|
|
5343
|
+
return {
|
|
5344
|
+
name: error.name,
|
|
5345
|
+
message: e.text,
|
|
5346
|
+
stack: e.location ? `${error.name}: ${e.text}\n at ${relative(ctx.config.root, e.location.file)}:${e.location.line}:${e.location.column}` : ""
|
|
5347
|
+
};
|
|
5348
|
+
}) : [{
|
|
5352
5349
|
name: error.name,
|
|
5353
5350
|
stack: error.stack,
|
|
5354
5351
|
message: error.message
|
|
@@ -5616,13 +5613,11 @@ class ServerModuleRunner extends ModuleRunner {
|
|
|
5616
5613
|
const fetchModule = createFetchModuleFunction(resolver, false);
|
|
5617
5614
|
super({
|
|
5618
5615
|
hmr: false,
|
|
5619
|
-
sourcemapInterceptor: "node",
|
|
5620
5616
|
transport: { async invoke(event) {
|
|
5621
5617
|
if (event.type !== "custom") throw new Error(`Vitest Module Runner doesn't support Vite HMR events.`);
|
|
5622
5618
|
const { data } = event.data;
|
|
5623
5619
|
try {
|
|
5624
|
-
|
|
5625
|
-
return { result };
|
|
5620
|
+
return { result: await fetchModule(data[0], data[1], environment, data[2]) };
|
|
5626
5621
|
} catch (error) {
|
|
5627
5622
|
return { error };
|
|
5628
5623
|
}
|
|
@@ -5761,8 +5756,8 @@ class Logger {
|
|
|
5761
5756
|
const projectsFilter = toArray(config.project);
|
|
5762
5757
|
if (projectsFilter.length) this.console.error(c.dim("projects: ") + c.yellow(projectsFilter.join(comma)));
|
|
5763
5758
|
this.ctx.projects.forEach((project) => {
|
|
5764
|
-
const config = project.config
|
|
5765
|
-
if (
|
|
5759
|
+
const config = project.config;
|
|
5760
|
+
if (!project.isRootProject() && project.name) this.console.error(`\n${formatProjectName(project)}\n`);
|
|
5766
5761
|
if (config.include) this.console.error(c.dim("include: ") + c.yellow(config.include.join(comma)));
|
|
5767
5762
|
if (config.exclude) this.console.error(c.dim("exclude: ") + c.yellow(config.exclude.join(comma)));
|
|
5768
5763
|
if (config.typecheck.enabled) this.console.error(c.dim("typecheck include: ") + c.yellow(config.typecheck.include.join(comma))), this.console.error(c.dim("typecheck exclude: ") + c.yellow(config.typecheck.exclude.join(comma)));
|
|
@@ -5853,7 +5848,7 @@ class VitestPackageInstaller {
|
|
|
5853
5848
|
}
|
|
5854
5849
|
if (/* @__PURE__ */ isPackageExists(dependency, { paths: [root, __dirname] })) return true;
|
|
5855
5850
|
if (process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEPENDENCY "))} Cannot find dependency '${dependency}'\n\n`)), !isTTY) return false;
|
|
5856
|
-
const
|
|
5851
|
+
const { install } = await (await import('./index.Dc3xnDvT.js').then(function (n) { return n.i; })).default({
|
|
5857
5852
|
type: "confirm",
|
|
5858
5853
|
name: "install",
|
|
5859
5854
|
message: c.reset(`Do you want to install ${c.green(dependency)}?`)
|
|
@@ -5965,7 +5960,8 @@ function serializeConfig(project) {
|
|
|
5965
5960
|
screenshotFailures: browser.screenshotFailures,
|
|
5966
5961
|
locators: { testIdAttribute: browser.locators.testIdAttribute },
|
|
5967
5962
|
providerOptions: provider?.name === "playwright" ? { actionTimeout: provider?.options?.actionTimeout } : {},
|
|
5968
|
-
trackUnhandledErrors: browser.trackUnhandledErrors ?? true
|
|
5963
|
+
trackUnhandledErrors: browser.trackUnhandledErrors ?? true,
|
|
5964
|
+
trace: browser.trace.mode
|
|
5969
5965
|
};
|
|
5970
5966
|
})(config.browser),
|
|
5971
5967
|
standalone: config.standalone,
|
|
@@ -6501,7 +6497,7 @@ function MetaEnvReplacerPlugin() {
|
|
|
6501
6497
|
transform(code, id) {
|
|
6502
6498
|
if (!/\bimport\.meta\.env\b/.test(code)) return null;
|
|
6503
6499
|
let s = null;
|
|
6504
|
-
const
|
|
6500
|
+
const envs = stripLiteral(code).matchAll(/\bimport\.meta\.env\b/g);
|
|
6505
6501
|
for (const env of envs) {
|
|
6506
6502
|
s ||= new MagicString(code);
|
|
6507
6503
|
const startIndex = env.index, endIndex = startIndex + env[0].length;
|
|
@@ -6633,9 +6629,7 @@ function isInline(id) {
|
|
|
6633
6629
|
return cssInlineRE.test(id);
|
|
6634
6630
|
}
|
|
6635
6631
|
function getCSSModuleProxyReturn(strategy, filename) {
|
|
6636
|
-
|
|
6637
|
-
const hash = generateCssFilenameHash(filename);
|
|
6638
|
-
return `\`_\${style}_${hash}\``;
|
|
6632
|
+
return strategy === "non-scoped" ? "style" : `\`_\${style}_${generateCssFilenameHash(filename)}\``;
|
|
6639
6633
|
}
|
|
6640
6634
|
function CSSEnablerPlugin(ctx) {
|
|
6641
6635
|
const shouldProcessCSS = (id) => {
|
|
@@ -6657,12 +6651,12 @@ function CSSEnablerPlugin(ctx) {
|
|
|
6657
6651
|
// return proxy for css modules, so that imported module has names:
|
|
6658
6652
|
// styles.foo returns a "foo" instead of "undefined"
|
|
6659
6653
|
// we don't use code content to generate hash for "scoped", because it's empty
|
|
6660
|
-
const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable"
|
|
6654
|
+
const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable";
|
|
6655
|
+
return { code: `export default new Proxy(Object.create(null), {
|
|
6661
6656
|
get(_, style) {
|
|
6662
|
-
return ${
|
|
6657
|
+
return ${getCSSModuleProxyReturn(scopeStrategy, relative(ctx.config.root, id))};
|
|
6663
6658
|
},
|
|
6664
|
-
})
|
|
6665
|
-
return { code };
|
|
6659
|
+
})` };
|
|
6666
6660
|
}
|
|
6667
6661
|
return { code: "export default \"\"" };
|
|
6668
6662
|
}
|
|
@@ -6777,12 +6771,7 @@ function getDefaultResolveOptions() {
|
|
|
6777
6771
|
};
|
|
6778
6772
|
}
|
|
6779
6773
|
function getDefaultServerConditions() {
|
|
6780
|
-
|
|
6781
|
-
if (viteMajor >= 6) {
|
|
6782
|
-
const conditions = vite.defaultServerConditions;
|
|
6783
|
-
return conditions.filter((c) => c !== "module");
|
|
6784
|
-
}
|
|
6785
|
-
return ["node"];
|
|
6774
|
+
return Number(version.split(".")[0]) >= 6 ? vite.defaultServerConditions.filter((c) => c !== "module") : ["node"];
|
|
6786
6775
|
}
|
|
6787
6776
|
|
|
6788
6777
|
function ModuleRunnerTransform() {
|
|
@@ -6840,15 +6829,10 @@ function VitestProjectResolver(ctx) {
|
|
|
6840
6829
|
name: "vitest:resolve-root",
|
|
6841
6830
|
enforce: "pre",
|
|
6842
6831
|
async resolveId(id, _, { ssr }) {
|
|
6843
|
-
if (id === "vitest" || id.startsWith("@vitest/") || id.startsWith("vitest/")) {
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
skip: new Set([plugin]),
|
|
6848
|
-
ssr
|
|
6849
|
-
});
|
|
6850
|
-
return resolved;
|
|
6851
|
-
}
|
|
6832
|
+
if (id === "vitest" || id.startsWith("@vitest/") || id.startsWith("vitest/")) return await ctx.vite.pluginContainer.resolveId(id, void 0, {
|
|
6833
|
+
skip: new Set([plugin]),
|
|
6834
|
+
ssr
|
|
6835
|
+
});
|
|
6852
6836
|
}
|
|
6853
6837
|
};
|
|
6854
6838
|
return plugin;
|
|
@@ -6883,22 +6867,19 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
6883
6867
|
if (existsSync(pkgJsonPath)) name = JSON.parse(readFileSync(pkgJsonPath, "utf-8")).name;
|
|
6884
6868
|
if (typeof name !== "string" || !name) name = basename(dir);
|
|
6885
6869
|
} else name = options.workspacePath.toString();
|
|
6886
|
-
const
|
|
6870
|
+
const isBrowserEnabled = viteConfig.test?.browser?.enabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled), workspaceNames = [name], browser = viteConfig.test.browser || {};
|
|
6887
6871
|
if (isBrowserEnabled && browser.name && !browser.instances?.length)
|
|
6888
6872
|
// vitest injects `instances` in this case later on
|
|
6889
6873
|
workspaceNames.push(name ? `${name} (${browser.name})` : browser.name);
|
|
6890
|
-
viteConfig.test?.browser?.instances?.forEach((instance) => {
|
|
6891
|
-
if (instance.name ??= name ? `${name} (${instance.browser})` : instance.browser, isBrowserEnabled) workspaceNames.push(instance.name);
|
|
6892
|
-
});
|
|
6893
|
-
const filters = project.vitest.config.project;
|
|
6894
6874
|
// if there is `--project=...` filter, check if any of the potential projects match
|
|
6895
6875
|
// if projects don't match, we ignore the test project altogether
|
|
6896
6876
|
// if some of them match, they will later be filtered again by `resolveWorkspace`
|
|
6897
|
-
if (
|
|
6898
|
-
|
|
6877
|
+
if (viteConfig.test?.browser?.instances?.forEach((instance) => {
|
|
6878
|
+
if (instance.name ??= name ? `${name} (${instance.browser})` : instance.browser, isBrowserEnabled) workspaceNames.push(instance.name);
|
|
6879
|
+
}), project.vitest.config.project.length) {
|
|
6880
|
+
if (!workspaceNames.some((name) => {
|
|
6899
6881
|
return project.vitest.matchesProjectFilter(name);
|
|
6900
|
-
});
|
|
6901
|
-
if (!hasProject) throw new VitestFilteredOutProjectError();
|
|
6882
|
+
})) throw new VitestFilteredOutProjectError();
|
|
6902
6883
|
}
|
|
6903
6884
|
return {
|
|
6904
6885
|
environments: { __vitest__: { dev: {} } },
|
|
@@ -7039,9 +7020,7 @@ async function isValidNodeImport(id) {
|
|
|
7039
7020
|
const extension = extname(id);
|
|
7040
7021
|
if (BUILTIN_EXTENSIONS.has(extension)) return true;
|
|
7041
7022
|
if (extension !== ".js") return false;
|
|
7042
|
-
id = id.replace("file:///", "");
|
|
7043
|
-
const package_ = findNearestPackageData(dirname(id));
|
|
7044
|
-
if (package_.type === "module") return true;
|
|
7023
|
+
if (id = id.replace("file:///", ""), findNearestPackageData(dirname(id)).type === "module") return true;
|
|
7045
7024
|
if (/\.(?:\w+-)?esm?(?:-\w+)?\.js$|\/esm?\//.test(id)) return false;
|
|
7046
7025
|
try {
|
|
7047
7026
|
await esModuleLexer.init;
|
|
@@ -7065,8 +7044,8 @@ async function _shouldExternalize(id, options) {
|
|
|
7065
7044
|
// Unless the user explicitly opted to inline them, externalize Vite deps.
|
|
7066
7045
|
// They are too big to inline by default.
|
|
7067
7046
|
if (matchExternalizePattern(id, moduleDirectories, options?.external) || options?.cacheDir && id.includes(options.cacheDir)) return id;
|
|
7068
|
-
const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir))
|
|
7069
|
-
return id =
|
|
7047
|
+
const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir));
|
|
7048
|
+
return id = isLibraryModule && options?.fallbackCJS ? guessCJSversion(id) || id : id, matchExternalizePattern(id, moduleDirectories, defaultInline) ? false : matchExternalizePattern(id, moduleDirectories, depsExternal) || isLibraryModule && await isValidNodeImport(id) ? id : false;
|
|
7070
7049
|
}
|
|
7071
7050
|
function matchExternalizePattern(id, moduleDirectories, patterns) {
|
|
7072
7051
|
if (patterns == null) return false;
|
|
@@ -7108,7 +7087,7 @@ class TestSpecification {
|
|
|
7108
7087
|
*/
|
|
7109
7088
|
get testModule() {
|
|
7110
7089
|
const task = this.project.vitest.state.idMap.get(this.taskId);
|
|
7111
|
-
|
|
7090
|
+
if (task) return this.project.vitest.state.getReportedEntity(task);
|
|
7112
7091
|
}
|
|
7113
7092
|
toJSON() {
|
|
7114
7093
|
return [
|
|
@@ -7337,16 +7316,15 @@ class TestProject {
|
|
|
7337
7316
|
}
|
|
7338
7317
|
/** @internal */
|
|
7339
7318
|
async globFiles(include, exclude, cwd) {
|
|
7340
|
-
|
|
7319
|
+
// keep the slashes consistent with Vite
|
|
7320
|
+
// we are not using the pathe here because it normalizes the drive letter on Windows
|
|
7321
|
+
// and we want to keep it the same as working dir
|
|
7322
|
+
return (await glob(include, {
|
|
7341
7323
|
dot: true,
|
|
7342
7324
|
cwd,
|
|
7343
7325
|
ignore: exclude,
|
|
7344
7326
|
expandDirectories: false
|
|
7345
|
-
}
|
|
7346
|
-
// keep the slashes consistent with Vite
|
|
7347
|
-
// we are not using the pathe here because it normalizes the drive letter on Windows
|
|
7348
|
-
// and we want to keep it the same as working dir
|
|
7349
|
-
return files.map((file) => slash(path.resolve(cwd, file)));
|
|
7327
|
+
})).map((file) => slash(path.resolve(cwd, file)));
|
|
7350
7328
|
}
|
|
7351
7329
|
/**
|
|
7352
7330
|
* Test if a file matches the test globs. This does the actual glob matching if the test is not cached, unlike `isCachedTestFile`.
|
|
@@ -7415,6 +7393,8 @@ class TestProject {
|
|
|
7415
7393
|
this.browser?.close(),
|
|
7416
7394
|
this.clearTmpDir()
|
|
7417
7395
|
].filter(Boolean)).then(() => {
|
|
7396
|
+
if (!this.runner.isClosed()) return this.runner.close();
|
|
7397
|
+
}).then(() => {
|
|
7418
7398
|
this._provided = {}, this._vite = void 0;
|
|
7419
7399
|
});
|
|
7420
7400
|
return this.closingPromise;
|
|
@@ -7511,8 +7491,13 @@ function generateHash(str) {
|
|
|
7511
7491
|
return `${hash}`;
|
|
7512
7492
|
}
|
|
7513
7493
|
|
|
7494
|
+
// vitest.config.*
|
|
7495
|
+
// vite.config.*
|
|
7496
|
+
// vitest.unit.config.*
|
|
7497
|
+
// vite.unit.config.*
|
|
7498
|
+
const CONFIG_REGEXP = /^vite(?:st)?(?:\.\w+)?\.config\./;
|
|
7514
7499
|
async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projectsDefinition, names) {
|
|
7515
|
-
const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition),
|
|
7500
|
+
const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition), cliOverrides = [
|
|
7516
7501
|
"logHeapUsage",
|
|
7517
7502
|
"allowOnly",
|
|
7518
7503
|
"sequence",
|
|
@@ -7531,7 +7516,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
|
|
|
7531
7516
|
"inspect",
|
|
7532
7517
|
"inspectBrk",
|
|
7533
7518
|
"fileParallelism"
|
|
7534
|
-
]
|
|
7519
|
+
].reduce((acc, name) => {
|
|
7535
7520
|
if (name in cliOptions) acc[name] = cliOptions[name];
|
|
7536
7521
|
return acc;
|
|
7537
7522
|
}, {}), projectPromises = [], fileProjects = [...configFiles, ...nonConfigDirectories], concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
|
|
@@ -7647,7 +7632,7 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
|
|
|
7647
7632
|
if (headedBrowserProjects.length > 1) {
|
|
7648
7633
|
const message = [`Found multiple projects that run browser tests in headed mode: "${headedBrowserProjects.map((p) => p.name).join("\", \"")}".`, ` Vitest cannot run multiple headed browsers at the same time.`].join("");
|
|
7649
7634
|
if (!isTTY) throw new Error(`${message} Please, filter projects with --browser=name or --project=name flag or run tests with "headless: true" option.`);
|
|
7650
|
-
const
|
|
7635
|
+
const { projectName } = await (await import('./index.Dc3xnDvT.js').then(function (n) { return n.i; })).default({
|
|
7651
7636
|
type: "select",
|
|
7652
7637
|
name: "projectName",
|
|
7653
7638
|
choices: headedBrowserProjects.map((project) => ({
|
|
@@ -7695,11 +7680,14 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
|
|
|
7695
7680
|
const note = "Projects definition";
|
|
7696
7681
|
throw new Error(`${note} references a non-existing file or a directory: ${file}`);
|
|
7697
7682
|
}
|
|
7698
|
-
const stats =
|
|
7683
|
+
const stats = statSync(file);
|
|
7699
7684
|
// user can specify a config file directly
|
|
7700
|
-
if (stats.isFile())
|
|
7701
|
-
|
|
7702
|
-
|
|
7685
|
+
if (stats.isFile()) {
|
|
7686
|
+
const name = basename(file);
|
|
7687
|
+
if (!CONFIG_REGEXP.test(name)) throw new Error(`The file "${relative(vitest.config.root, file)}" must start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*" to be a valid project config.`);
|
|
7688
|
+
projectsConfigFiles.push(file);
|
|
7689
|
+
} else if (stats.isDirectory()) {
|
|
7690
|
+
const configFile = resolveDirectoryConfig(file);
|
|
7703
7691
|
if (configFile) projectsConfigFiles.push(configFile);
|
|
7704
7692
|
else {
|
|
7705
7693
|
const directory = file.at(-1) === "/" ? file : `${file}/`;
|
|
@@ -7728,16 +7716,20 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
|
|
|
7728
7716
|
"**/*.timestamp-*",
|
|
7729
7717
|
"**/.DS_Store"
|
|
7730
7718
|
]
|
|
7731
|
-
}
|
|
7732
|
-
await
|
|
7719
|
+
};
|
|
7720
|
+
(await glob(projectsGlobMatches, globOptions)).forEach((path) => {
|
|
7733
7721
|
// directories are allowed with a glob like `packages/*`
|
|
7734
7722
|
// in this case every directory is treated as a project
|
|
7735
7723
|
if (path.endsWith("/")) {
|
|
7736
|
-
const configFile =
|
|
7724
|
+
const configFile = resolveDirectoryConfig(path);
|
|
7737
7725
|
if (configFile) projectsConfigFiles.push(configFile);
|
|
7738
7726
|
else nonConfigProjectDirectories.push(path);
|
|
7739
|
-
} else
|
|
7740
|
-
|
|
7727
|
+
} else {
|
|
7728
|
+
const name = basename(path);
|
|
7729
|
+
if (!CONFIG_REGEXP.test(name)) throw new Error(`The projects glob matched a file "${relative(vitest.config.root, path)}", but it should also either start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*".`);
|
|
7730
|
+
projectsConfigFiles.push(path);
|
|
7731
|
+
}
|
|
7732
|
+
});
|
|
7741
7733
|
}
|
|
7742
7734
|
const projectConfigFiles = Array.from(new Set(projectsConfigFiles));
|
|
7743
7735
|
return {
|
|
@@ -7746,16 +7738,13 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
|
|
|
7746
7738
|
configFiles: projectConfigFiles
|
|
7747
7739
|
};
|
|
7748
7740
|
}
|
|
7749
|
-
|
|
7750
|
-
const files = new Set(
|
|
7741
|
+
function resolveDirectoryConfig(directory) {
|
|
7742
|
+
const files = new Set(readdirSync(directory)), configFile = configFiles.find((file) => files.has(file));
|
|
7751
7743
|
return configFile ? resolve(directory, configFile) : null;
|
|
7752
7744
|
}
|
|
7753
7745
|
function getDefaultTestProject(vitest) {
|
|
7754
7746
|
const filter = vitest.config.project, project = vitest._ensureRootProject();
|
|
7755
|
-
|
|
7756
|
-
// check for the project name and browser names
|
|
7757
|
-
const hasProjects = getPotentialProjectNames(project).some((p) => vitest.matchesProjectFilter(p));
|
|
7758
|
-
return hasProjects ? project : null;
|
|
7747
|
+
return !filter.length || getPotentialProjectNames(project).some((p) => vitest.matchesProjectFilter(p)) ? project : null;
|
|
7759
7748
|
}
|
|
7760
7749
|
function getPotentialProjectNames(project) {
|
|
7761
7750
|
const names = [project.name];
|
|
@@ -7778,17 +7767,11 @@ function createReporters(reporterReferences, ctx) {
|
|
|
7778
7767
|
const runner = ctx.runner, promisedReporters = reporterReferences.map(async (referenceOrInstance) => {
|
|
7779
7768
|
if (Array.isArray(referenceOrInstance)) {
|
|
7780
7769
|
const [reporterName, reporterOptions] = referenceOrInstance;
|
|
7781
|
-
if (reporterName === "html")
|
|
7782
|
-
|
|
7783
|
-
const CustomReporter = await loadCustomReporterModule("@vitest/ui/reporter", runner);
|
|
7784
|
-
return new CustomReporter(reporterOptions);
|
|
7785
|
-
} else if (reporterName in ReportersMap) {
|
|
7770
|
+
if (reporterName === "html") return await ctx.packageInstaller.ensureInstalled("@vitest/ui", ctx.config.root, ctx.version), new (await (loadCustomReporterModule("@vitest/ui/reporter", runner)))(reporterOptions);
|
|
7771
|
+
if (reporterName in ReportersMap) {
|
|
7786
7772
|
const BuiltinReporter = ReportersMap[reporterName];
|
|
7787
7773
|
return new BuiltinReporter(reporterOptions);
|
|
7788
|
-
} else
|
|
7789
|
-
const CustomReporter = await loadCustomReporterModule(reporterName, runner);
|
|
7790
|
-
return new CustomReporter(reporterOptions);
|
|
7791
|
-
}
|
|
7774
|
+
} else return new (await (loadCustomReporterModule(reporterName, runner)))(reporterOptions);
|
|
7792
7775
|
}
|
|
7793
7776
|
return referenceOrInstance;
|
|
7794
7777
|
});
|
|
@@ -7799,10 +7782,7 @@ function createBenchmarkReporters(reporterReferences, runner) {
|
|
|
7799
7782
|
if (typeof referenceOrInstance === "string") if (referenceOrInstance in BenchmarkReportsMap) {
|
|
7800
7783
|
const BuiltinReporter = BenchmarkReportsMap[referenceOrInstance];
|
|
7801
7784
|
return new BuiltinReporter();
|
|
7802
|
-
} else
|
|
7803
|
-
const CustomReporter = await loadCustomReporterModule(referenceOrInstance, runner);
|
|
7804
|
-
return new CustomReporter();
|
|
7805
|
-
}
|
|
7785
|
+
} else return new (await (loadCustomReporterModule(referenceOrInstance, runner)))();
|
|
7806
7786
|
return referenceOrInstance;
|
|
7807
7787
|
});
|
|
7808
7788
|
return Promise.all(promisedReporters);
|
|
@@ -7820,11 +7800,11 @@ function parseFilter(filter) {
|
|
|
7820
7800
|
return { filename: filter };
|
|
7821
7801
|
}
|
|
7822
7802
|
function groupFilters(filters) {
|
|
7823
|
-
const groupedFilters_ = groupBy(filters, (f) => f.filename)
|
|
7803
|
+
const groupedFilters_ = groupBy(filters, (f) => f.filename);
|
|
7804
|
+
return Object.fromEntries(Object.entries(groupedFilters_).map((entry) => {
|
|
7824
7805
|
const [filename, filters] = entry, testLocations = filters.map((f) => f.lineNumber);
|
|
7825
7806
|
return [filename, testLocations.filter((l) => l !== void 0)];
|
|
7826
7807
|
}));
|
|
7827
|
-
return groupedFilters;
|
|
7828
7808
|
}
|
|
7829
7809
|
|
|
7830
7810
|
class VitestSpecifications {
|
|
@@ -7885,7 +7865,7 @@ class VitestSpecifications {
|
|
|
7885
7865
|
}
|
|
7886
7866
|
async filterTestsBySource(specs) {
|
|
7887
7867
|
if (this.vitest.config.changed && !this.vitest.config.related) {
|
|
7888
|
-
const { VitestGit } = await import('./git.BFNcloKD.js'),
|
|
7868
|
+
const { VitestGit } = await import('./git.BFNcloKD.js'), related = await new VitestGit(this.vitest.config.root).findChangedFiles({ changedSince: this.vitest.config.changed });
|
|
7889
7869
|
if (!related) throw process.exitCode = 1, new GitNotFoundError();
|
|
7890
7870
|
this.vitest.config.related = Array.from(new Set(related));
|
|
7891
7871
|
}
|
|
@@ -7909,7 +7889,7 @@ class VitestSpecifications {
|
|
|
7909
7889
|
const addImports = async (project, filepath) => {
|
|
7910
7890
|
if (deps.has(filepath)) return;
|
|
7911
7891
|
deps.add(filepath);
|
|
7912
|
-
const
|
|
7892
|
+
const transformed = project.vite.environments.ssr.moduleGraph.getModuleById(filepath)?.transformResult || await project.vite.environments.ssr.transformRequest(filepath);
|
|
7913
7893
|
if (!transformed) return;
|
|
7914
7894
|
const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
|
|
7915
7895
|
await Promise.all(dependencies.map(async (dep) => {
|
|
@@ -8047,10 +8027,10 @@ class TestCase extends ReportedTaskImplementation {
|
|
|
8047
8027
|
diagnostic() {
|
|
8048
8028
|
const result = this.task.result;
|
|
8049
8029
|
// startTime should always be available if the test has properly finished
|
|
8050
|
-
if (!result || !result.startTime) return
|
|
8051
|
-
const duration = result.duration || 0
|
|
8030
|
+
if (!result || !result.startTime) return;
|
|
8031
|
+
const duration = result.duration || 0;
|
|
8052
8032
|
return {
|
|
8053
|
-
slow,
|
|
8033
|
+
slow: duration > this.project.globalConfig.slowTestThreshold,
|
|
8054
8034
|
heap: result.heap,
|
|
8055
8035
|
duration,
|
|
8056
8036
|
startTime: result.startTime,
|
|
@@ -8201,8 +8181,7 @@ class TestModule extends SuiteImplementation {
|
|
|
8201
8181
|
* Checks the running state of the test file.
|
|
8202
8182
|
*/
|
|
8203
8183
|
state() {
|
|
8204
|
-
|
|
8205
|
-
return state === "queued" ? "queued" : getSuiteState(this.task);
|
|
8184
|
+
return this.task.result?.state === "queued" ? "queued" : getSuiteState(this.task);
|
|
8206
8185
|
}
|
|
8207
8186
|
/**
|
|
8208
8187
|
* Useful information about the module like duration, memory usage, etc.
|
|
@@ -8361,6 +8340,10 @@ class StateManager {
|
|
|
8361
8340
|
getReportedEntity(task) {
|
|
8362
8341
|
return this.reportedTasksMap.get(task);
|
|
8363
8342
|
}
|
|
8343
|
+
getReportedEntityById(taskId) {
|
|
8344
|
+
const task = this.idMap.get(taskId);
|
|
8345
|
+
return task ? this.reportedTasksMap.get(task) : void 0;
|
|
8346
|
+
}
|
|
8364
8347
|
updateTasks(packs) {
|
|
8365
8348
|
for (const [id, result, meta] of packs) {
|
|
8366
8349
|
const task = this.idMap.get(id);
|
|
@@ -8866,7 +8849,7 @@ class TestRun {
|
|
|
8866
8849
|
async updated(update, events) {
|
|
8867
8850
|
this.syncUpdateStacks(update), this.vitest.state.updateTasks(update);
|
|
8868
8851
|
for (const [id, event, data] of events) await this.reportEvent(id, event, data).catch((error) => {
|
|
8869
|
-
this.vitest.state.catchError(
|
|
8852
|
+
this.vitest.state.catchError(serializeValue(error), "Unhandled Reporter Error");
|
|
8870
8853
|
});
|
|
8871
8854
|
// TODO: what is the order or reports here?
|
|
8872
8855
|
// "onTaskUpdate" in parallel with others or before all or after all?
|
|
@@ -8933,9 +8916,8 @@ class TestRun {
|
|
|
8933
8916
|
const path = attachment.path;
|
|
8934
8917
|
if (path && !path.startsWith("http://") && !path.startsWith("https://")) {
|
|
8935
8918
|
const currentPath = resolve(project.config.root, path), hash = createHash("sha1").update(currentPath).digest("hex"), newPath = resolve(project.config.attachmentsDir, `${sanitizeFilePath(annotation.message)}-${hash}${extname(currentPath)}`);
|
|
8936
|
-
await mkdir(
|
|
8937
|
-
|
|
8938
|
-
attachment.contentType = contentType || void 0;
|
|
8919
|
+
if (!existsSync(project.config.attachmentsDir)) await mkdir(project.config.attachmentsDir, { recursive: true });
|
|
8920
|
+
await copyFile(currentPath, newPath), attachment.path = newPath, attachment.contentType = (attachment.contentType ?? mime.getType(basename(currentPath))) || void 0;
|
|
8939
8921
|
}
|
|
8940
8922
|
return attachment;
|
|
8941
8923
|
}
|
|
@@ -8995,21 +8977,14 @@ class VitestWatcher {
|
|
|
8995
8977
|
}), triggered;
|
|
8996
8978
|
}
|
|
8997
8979
|
onFileChange = (id) => {
|
|
8998
|
-
id = slash(id), this.vitest.logger.clearHighlightCache(id), this.vitest.invalidateFile(id);
|
|
8999
|
-
|
|
9000
|
-
if (testFiles) this.scheduleRerun(id);
|
|
9001
|
-
else {
|
|
9002
|
-
const needsRerun = this.handleFileChanged(id);
|
|
9003
|
-
if (needsRerun) this.scheduleRerun(id);
|
|
9004
|
-
}
|
|
8980
|
+
if (id = slash(id), this.vitest.logger.clearHighlightCache(id), this.vitest.invalidateFile(id), this.getTestFilesFromWatcherTrigger(id)) this.scheduleRerun(id);
|
|
8981
|
+
else if (this.handleFileChanged(id)) this.scheduleRerun(id);
|
|
9005
8982
|
};
|
|
9006
8983
|
onFileDelete = (id) => {
|
|
9007
8984
|
if (id = slash(id), this.vitest.logger.clearHighlightCache(id), this.invalidates.add(id), this.vitest.state.filesMap.has(id)) this.vitest.projects.forEach((project) => project._removeCachedTestFile(id)), this.vitest.state.filesMap.delete(id), this.vitest.cache.results.removeFromCache(id), this.vitest.cache.stats.removeStats(id), this.changedTests.delete(id), this.vitest.report("onTestRemoved", id);
|
|
9008
8985
|
};
|
|
9009
8986
|
onFileCreate = (id) => {
|
|
9010
|
-
id = slash(id), this.vitest.invalidateFile(id)
|
|
9011
|
-
const testFiles = this.getTestFilesFromWatcherTrigger(id);
|
|
9012
|
-
if (testFiles) {
|
|
8987
|
+
if (id = slash(id), this.vitest.invalidateFile(id), this.getTestFilesFromWatcherTrigger(id)) {
|
|
9013
8988
|
this.scheduleRerun(id);
|
|
9014
8989
|
return;
|
|
9015
8990
|
}
|
|
@@ -9018,11 +8993,7 @@ class VitestWatcher {
|
|
|
9018
8993
|
if (this.vitest.projects.forEach((project) => {
|
|
9019
8994
|
if (project.matchesTestGlob(id, () => fileContent ??= readFileSync(id, "utf-8"))) matchingProjects.push(project);
|
|
9020
8995
|
}), matchingProjects.length > 0) this.changedTests.add(id), this.scheduleRerun(id);
|
|
9021
|
-
else
|
|
9022
|
-
// it's possible that file was already there but watcher triggered "add" event instead
|
|
9023
|
-
const needsRerun = this.handleFileChanged(id);
|
|
9024
|
-
if (needsRerun) this.scheduleRerun(id);
|
|
9025
|
-
}
|
|
8996
|
+
else if (this.handleFileChanged(id)) this.scheduleRerun(id);
|
|
9026
8997
|
};
|
|
9027
8998
|
handleSetupFile(filepath) {
|
|
9028
8999
|
let isSetupFile = false;
|
|
@@ -9042,8 +9013,7 @@ class VitestWatcher {
|
|
|
9042
9013
|
if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) return this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file)), true;
|
|
9043
9014
|
if (this.handleSetupFile(filepath)) return true;
|
|
9044
9015
|
const projects = this.vitest.projects.filter((project) => {
|
|
9045
|
-
|
|
9046
|
-
return moduleGraph.getModulesByFile(filepath)?.size;
|
|
9016
|
+
return (project.browser?.vite.moduleGraph || project.vite.moduleGraph).getModulesByFile(filepath)?.size;
|
|
9047
9017
|
});
|
|
9048
9018
|
if (!projects.length) return this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath)) ? (this.changedTests.add(filepath), true) : false;
|
|
9049
9019
|
const files = [];
|
|
@@ -9057,9 +9027,7 @@ class VitestWatcher {
|
|
|
9057
9027
|
}
|
|
9058
9028
|
let rerun = false;
|
|
9059
9029
|
for (const mod of mods) mod.importers.forEach((i) => {
|
|
9060
|
-
if (
|
|
9061
|
-
const needsRerun = this.handleFileChanged(i.file);
|
|
9062
|
-
if (needsRerun) rerun = true;
|
|
9030
|
+
if (i.file && this.handleFileChanged(i.file)) rerun = true;
|
|
9063
9031
|
});
|
|
9064
9032
|
if (rerun) files.push(filepath);
|
|
9065
9033
|
}
|
|
@@ -9183,9 +9151,7 @@ class Vitest {
|
|
|
9183
9151
|
server.restart = async (...args) => {
|
|
9184
9152
|
await Promise.all(this._onRestartListeners.map((fn) => fn())), this.report("onServerRestart"), await this.close(), await serverRestart(...args);
|
|
9185
9153
|
}, server.watcher.on("change", async (file) => {
|
|
9186
|
-
file = normalize(file);
|
|
9187
|
-
const isConfig = file === server.config.configFile || this.projects.some((p) => p.vite.config.configFile === file);
|
|
9188
|
-
if (isConfig) await Promise.all(this._onRestartListeners.map((fn) => fn("config"))), this.report("onServerRestart", "config"), await this.close(), await serverRestart();
|
|
9154
|
+
if (file = normalize(file), file === server.config.configFile || this.projects.some((p) => p.vite.config.configFile === file)) await Promise.all(this._onRestartListeners.map((fn) => fn("config"))), this.report("onServerRestart", "config"), await this.close(), await serverRestart();
|
|
9189
9155
|
});
|
|
9190
9156
|
}
|
|
9191
9157
|
this.cache.results.setConfig(resolved.root, resolved.cache);
|
|
@@ -9194,15 +9160,13 @@ class Vitest {
|
|
|
9194
9160
|
} catch {}
|
|
9195
9161
|
const projects = await this.resolveProjects(this._cliOptions);
|
|
9196
9162
|
if (this.projects = projects, await Promise.all(projects.flatMap((project) => {
|
|
9197
|
-
|
|
9198
|
-
return hooks.map((hook) => hook({
|
|
9163
|
+
return project.vite.config.getSortedPluginHooks("configureVitest").map((hook) => hook({
|
|
9199
9164
|
project,
|
|
9200
9165
|
vitest: this,
|
|
9201
9166
|
injectTestProjects: this.injectTestProject
|
|
9202
9167
|
}));
|
|
9203
9168
|
})), this._cliOptions.browser?.enabled) {
|
|
9204
|
-
|
|
9205
|
-
if (!browserProjects.length) throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`);
|
|
9169
|
+
if (!this.projects.filter((p) => p.config.browser.enabled).length) throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`);
|
|
9206
9170
|
}
|
|
9207
9171
|
if (!this.projects.length) {
|
|
9208
9172
|
const filter = toArray(resolved.project).join("\", \"");
|
|
@@ -9321,7 +9285,7 @@ class Vitest {
|
|
|
9321
9285
|
}, await this.report("onInit", this);
|
|
9322
9286
|
const specifications = [];
|
|
9323
9287
|
for (const file of files) {
|
|
9324
|
-
const
|
|
9288
|
+
const specification = this.getProjectByName(file.projectName || "").createSpecification(file.filepath, void 0, file.pool);
|
|
9325
9289
|
specifications.push(specification);
|
|
9326
9290
|
}
|
|
9327
9291
|
await this._testRun.start(specifications).catch(noop);
|
|
@@ -9331,6 +9295,12 @@ class Vitest {
|
|
|
9331
9295
|
unhandledErrors: this.state.getUnhandledErrors()
|
|
9332
9296
|
};
|
|
9333
9297
|
}
|
|
9298
|
+
/**
|
|
9299
|
+
* Returns the seed, if tests are running in a random order.
|
|
9300
|
+
*/
|
|
9301
|
+
getSeed() {
|
|
9302
|
+
return this.config.sequence.seed ?? null;
|
|
9303
|
+
}
|
|
9334
9304
|
/** @internal */
|
|
9335
9305
|
async _reportFileTask(file) {
|
|
9336
9306
|
const project = this.getProjectByName(file.projectName || "");
|
|
@@ -9654,10 +9624,8 @@ class Vitest {
|
|
|
9654
9624
|
*/
|
|
9655
9625
|
invalidateFile(filepath) {
|
|
9656
9626
|
this.projects.forEach(({ vite, browser }) => {
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
const modules = moduleGraph.getModulesByFile(filepath);
|
|
9660
|
-
modules?.forEach((module) => moduleGraph.invalidateModule(module));
|
|
9627
|
+
[...Object.values(vite.environments), ...Object.values(browser?.vite.environments || {})].forEach(({ moduleGraph }) => {
|
|
9628
|
+
moduleGraph.getModulesByFile(filepath)?.forEach((module) => moduleGraph.invalidateModule(module));
|
|
9661
9629
|
});
|
|
9662
9630
|
});
|
|
9663
9631
|
}
|
|
@@ -9780,8 +9748,7 @@ class Vitest {
|
|
|
9780
9748
|
matchesProjectFilter(name) {
|
|
9781
9749
|
const projects = this._config?.project || this._cliOptions?.project;
|
|
9782
9750
|
return !projects || !projects.length ? true : toArray(projects).some((project) => {
|
|
9783
|
-
|
|
9784
|
-
return regexp.test(name);
|
|
9751
|
+
return wildcardPatternToRegExp(project).test(name);
|
|
9785
9752
|
});
|
|
9786
9753
|
}
|
|
9787
9754
|
}
|
|
@@ -9810,11 +9777,7 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
9810
9777
|
// however to allow vitest plugins to modify vitest config values
|
|
9811
9778
|
// this is repeated in configResolved where the config is final
|
|
9812
9779
|
const testConfig = deepMerge({}, configDefaults, removeUndefinedValues(viteConfig.test ?? {}), options);
|
|
9813
|
-
testConfig.api = resolveApiServerConfig(testConfig, defaultPort);
|
|
9814
|
-
// store defines for globalThis to make them
|
|
9815
|
-
// reassignable when running in worker in src/runtime/setup.ts
|
|
9816
|
-
const defines = deleteDefineConfig(viteConfig);
|
|
9817
|
-
options.defines = defines;
|
|
9780
|
+
testConfig.api = resolveApiServerConfig(testConfig, defaultPort), options.defines = deleteDefineConfig(viteConfig);
|
|
9818
9781
|
let open = false;
|
|
9819
9782
|
if (testConfig.ui && testConfig.open) open = testConfig.uiBase ?? "/__vitest__/";
|
|
9820
9783
|
const resolveOptions = getDefaultResolveOptions();
|
|
@@ -9929,7 +9892,7 @@ function removeUndefinedValues(obj) {
|
|
|
9929
9892
|
}
|
|
9930
9893
|
|
|
9931
9894
|
async function createVitest(mode, options, viteOverrides = {}, vitestOptions = {}) {
|
|
9932
|
-
const ctx = new Vitest(mode, deepClone(options), vitestOptions), root = slash(resolve$1(options.root || process.cwd())), configPath = options.config === false ? false : options.config ? resolve$1(root, options.config) :
|
|
9895
|
+
const ctx = new Vitest(mode, deepClone(options), vitestOptions), root = slash(resolve$1(options.root || process.cwd())), configPath = options.config === false ? false : options.config ? resolve$1(root, options.config) : any(configFiles, { cwd: root });
|
|
9933
9896
|
options.config = configPath;
|
|
9934
9897
|
const { browser: _removeBrowser,...restOptions } = options, config = {
|
|
9935
9898
|
configFile: configPath,
|
|
@@ -9981,9 +9944,11 @@ class WatchFilter {
|
|
|
9981
9944
|
this.write(`${ESC}1G${ESC}0J`), onSubmit(void 0);
|
|
9982
9945
|
return;
|
|
9983
9946
|
case key?.name === "enter":
|
|
9984
|
-
case key?.name === "return":
|
|
9985
|
-
|
|
9947
|
+
case key?.name === "return": {
|
|
9948
|
+
const selection = this.results[this.selectionIndex], result = typeof selection === "string" ? selection : selection?.key;
|
|
9949
|
+
onSubmit(result || this.currentKeyword || ""), this.currentKeyword = void 0;
|
|
9986
9950
|
break;
|
|
9951
|
+
}
|
|
9987
9952
|
case key?.name === "up":
|
|
9988
9953
|
if (this.selectionIndex && this.selectionIndex > 0) this.selectionIndex--;
|
|
9989
9954
|
else this.selectionIndex = -1;
|
|
@@ -10045,7 +10010,7 @@ ${c.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "
|
|
|
10045
10010
|
this.stdout.write(data);
|
|
10046
10011
|
}
|
|
10047
10012
|
getLastResults() {
|
|
10048
|
-
return this.results;
|
|
10013
|
+
return this.results.map((r) => typeof r === "string" ? r : r.toString());
|
|
10049
10014
|
}
|
|
10050
10015
|
}
|
|
10051
10016
|
|
|
@@ -10071,6 +10036,26 @@ ${c.bold(" Watch Usage")}
|
|
|
10071
10036
|
${keys.map((i) => c.dim(" press ") + c.reset([i[0]].flat().map(c.bold).join(", ")) + c.dim(` to ${i[1]}`)).join("\n")}
|
|
10072
10037
|
`);
|
|
10073
10038
|
}
|
|
10039
|
+
function* traverseFilteredTestNames(parentName, filter, t) {
|
|
10040
|
+
if (isTestCase(t)) {
|
|
10041
|
+
if (t.name.match(filter)) {
|
|
10042
|
+
const displayName = `${parentName} > ${t.name}`;
|
|
10043
|
+
yield {
|
|
10044
|
+
key: t.name,
|
|
10045
|
+
toString: () => displayName
|
|
10046
|
+
};
|
|
10047
|
+
}
|
|
10048
|
+
} else {
|
|
10049
|
+
parentName = parentName.length ? `${parentName} > ${t.name}` : t.name;
|
|
10050
|
+
for (const task of t.tasks) yield* traverseFilteredTestNames(parentName, filter, task);
|
|
10051
|
+
}
|
|
10052
|
+
}
|
|
10053
|
+
function* getFilteredTestNames(pattern, suite) {
|
|
10054
|
+
try {
|
|
10055
|
+
const reg = new RegExp(pattern), files = /* @__PURE__ */ new Set();
|
|
10056
|
+
for (const file of suite) if (!files.has(file.name)) files.add(file.name), yield* traverseFilteredTestNames("", reg, file);
|
|
10057
|
+
} catch {}
|
|
10058
|
+
}
|
|
10074
10059
|
function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
10075
10060
|
let latestFilename = "";
|
|
10076
10061
|
async function _keypressHandler(str, key) {
|
|
@@ -10120,15 +10105,8 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10120
10105
|
}
|
|
10121
10106
|
async function inputNamePattern() {
|
|
10122
10107
|
off();
|
|
10123
|
-
const
|
|
10124
|
-
|
|
10125
|
-
try {
|
|
10126
|
-
const reg = new RegExp(str);
|
|
10127
|
-
return tests.map((test) => test.name).filter((testName) => testName.match(reg));
|
|
10128
|
-
} catch {
|
|
10129
|
-
// `new RegExp` may throw error when input is invalid regexp
|
|
10130
|
-
return [];
|
|
10131
|
-
}
|
|
10108
|
+
const filter = await new WatchFilter("Input test name pattern (RegExp)", stdin, stdout).filter((str) => {
|
|
10109
|
+
return [...getFilteredTestNames(str, ctx.state.getFiles())];
|
|
10132
10110
|
});
|
|
10133
10111
|
if (on(), typeof filter === "undefined") return;
|
|
10134
10112
|
const files = ctx.state.getFilepaths(), cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
|
|
@@ -10147,8 +10125,7 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10147
10125
|
async function inputFilePattern() {
|
|
10148
10126
|
off();
|
|
10149
10127
|
const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout), filter = await watchFilter.filter(async (str) => {
|
|
10150
|
-
|
|
10151
|
-
return specifications.map((specification) => relative(ctx.config.root, specification.moduleId)).filter((file, index, all) => all.indexOf(file) === index);
|
|
10128
|
+
return (await ctx.globTestSpecifications([str])).map((specification) => relative(ctx.config.root, specification.moduleId)).filter((file, index, all) => all.indexOf(file) === index);
|
|
10152
10129
|
});
|
|
10153
10130
|
if (on(), typeof filter === "undefined") return;
|
|
10154
10131
|
latestFilename = filter?.trim() || "";
|