vitest 4.0.0-beta.4 → 4.0.0-beta.6
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 +1 -1
- package/dist/browser.d.ts +8 -9
- package/dist/browser.js +3 -2
- package/dist/chunks/base.BXI97p6t.js +39 -0
- package/dist/chunks/{benchmark.CYdenmiT.js → benchmark.UW6Ezvxy.js} +6 -8
- package/dist/chunks/{browser.d.BRP8scJf.d.ts → browser.d.Cawq_X_N.d.ts} +1 -1
- package/dist/chunks/{cac.CY0IAxC4.js → cac.WE-urWw5.js} +38 -115
- package/dist/chunks/{cli-api.B8xRY9Zt.js → cli-api.CZz3evYC.js} +931 -1439
- package/dist/chunks/{config.d.DZo8c7fw.d.ts → config.d.CKNVOKm0.d.ts} +3 -8
- package/dist/chunks/{console.DoJHFxmj.js → console.B0quX7yH.js} +32 -68
- package/dist/chunks/{constants.CXzqaLmq.js → constants.D_Q9UYh-.js} +1 -6
- package/dist/chunks/{coverage.C84l9G-M.js → coverage.BPRS6xgn.js} +395 -665
- package/dist/chunks/{coverage.DVF1vEu8.js → coverage.D_JHT54q.js} +2 -2
- package/dist/chunks/{coverage.d.CNYjU4GF.d.ts → coverage.d.BZtK59WP.d.ts} +7 -5
- package/dist/chunks/{creator.yfA2ExGt.js → creator.KEg6n5IC.js} +29 -75
- package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
- package/dist/chunks/{environment.d.Bhm9oc0v.d.ts → environment.d.2fYMoz3o.d.ts} +26 -4
- package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
- package/dist/chunks/{global.d.DAhT2emn.d.ts → global.d.K6uBQHzY.d.ts} +1 -1
- package/dist/chunks/{globals.Dgo-vS5G.js → globals.lgsmH00r.js} +7 -6
- package/dist/chunks/{index.D3SKT3tv.js → index.7w0eqmYM.js} +14 -24
- package/dist/chunks/{index.D1_MsKEt.js → index.AR8aAkCC.js} +4 -2
- package/dist/chunks/{index.CmSc2RE5.js → index.BG0gqZH-.js} +43 -106
- package/dist/chunks/{index.CtUvr1c8.js → index.CsFXYRkW.js} +27 -46
- package/dist/chunks/{index.Bz6b0Ib7.js → index.VNI-1z5c.js} +276 -604
- package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
- package/dist/chunks/moduleRunner.d.8kKUsuDg.d.ts +202 -0
- package/dist/chunks/moduleTransport.I-bgQy0S.js +19 -0
- package/dist/chunks/{node.fjCdwEIl.js → node.BOqcT2jW.js} +1 -1
- package/dist/chunks/{plugin.d.CLhMcYdD.d.ts → plugin.d.DuiQJfUL.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DWg40D2B.d.ts → reporters.d.CqR9-CDJ.d.ts} +52 -101
- package/dist/chunks/resolver.Bx6lE0iq.js +119 -0
- package/dist/chunks/{rpc.jnQO9F8a.js → rpc.RpPylpp0.js} +7 -21
- package/dist/chunks/runBaseTests.D6sfuWBM.js +99 -0
- package/dist/chunks/{setup-common.Ebx5x0eP.js → setup-common.hLGRxhC8.js} +15 -27
- package/dist/chunks/startModuleRunner.C8TW8zTN.js +655 -0
- package/dist/chunks/{typechecker.CMNPqJOo.js → typechecker.Cd1wvxUM.js} +97 -209
- package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
- package/dist/chunks/{utils.XdZDrNZV.js → utils.C7__0Iv5.js} +7 -17
- package/dist/chunks/{vi.CA0EPI9Y.js → vi.BfdOiD4j.js} +116 -269
- package/dist/chunks/{vm.BUnLJt_P.js → vm.BHBje7cC.js} +101 -225
- package/dist/chunks/{worker.d.zjyR34Pb.d.ts → worker.d.D9QWnzAe.d.ts} +16 -13
- package/dist/chunks/{worker.d.C-1AbnVe.d.ts → worker.d.Db-UVmXc.d.ts} +1 -1
- package/dist/cli.js +4 -4
- package/dist/config.cjs +3 -9
- package/dist/config.d.ts +10 -12
- package/dist/config.js +1 -1
- package/dist/coverage.d.ts +10 -11
- package/dist/coverage.js +5 -6
- package/dist/environments.d.ts +2 -2
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +10 -9
- package/dist/index.js +6 -5
- package/dist/module-evaluator.d.ts +12 -0
- package/dist/module-evaluator.js +276 -0
- package/dist/module-runner.js +15 -0
- package/dist/node.d.ts +12 -13
- package/dist/node.js +19 -24
- package/dist/reporters.d.ts +7 -8
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +3 -3
- package/dist/runners.js +35 -57
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +82 -45
- package/dist/workers/forks.js +11 -10
- package/dist/workers/runVmTests.js +27 -46
- package/dist/workers/threads.js +11 -10
- package/dist/workers/vmForks.js +11 -10
- package/dist/workers/vmThreads.js +11 -10
- package/dist/workers.d.ts +5 -4
- package/dist/workers.js +17 -16
- package/package.json +22 -17
- package/dist/chunks/base.BaCDDRPG.js +0 -38
- package/dist/chunks/execute.Dt-pCVcL.js +0 -708
- package/dist/chunks/runBaseTests.DBVVLMSb.js +0 -129
- package/dist/execute.d.ts +0 -148
- package/dist/execute.js +0 -13
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import fs, { promises, existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { relative, resolve, dirname, extname, normalize, join, basename, isAbsolute } from 'pathe';
|
|
3
|
-
import { C as CoverageProviderMap } from './coverage.
|
|
3
|
+
import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
|
|
4
4
|
import path, { resolve as resolve$1 } from 'node:path';
|
|
5
|
-
import { noop, isPrimitive, createDefer, slash, highlight, toArray, deepMerge, nanoid, deepClone, notNullish } from '@vitest/utils';
|
|
5
|
+
import { noop, isPrimitive, createDefer, slash, highlight, toArray, cleanUrl, deepMerge, KNOWN_ASSET_RE, nanoid, deepClone, notNullish } from '@vitest/utils';
|
|
6
6
|
import { f as findUp, p as prompt } from './index.X0nbfr6-.js';
|
|
7
7
|
import * as vite from 'vite';
|
|
8
|
-
import { searchForWorkspaceRoot, version,
|
|
9
|
-
import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.
|
|
8
|
+
import { searchForWorkspaceRoot, version, mergeConfig, createServer } from 'vite';
|
|
9
|
+
import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
|
|
10
10
|
import { generateFileHash, limitConcurrency, createFileTask, hasFailed, getTasks, getTests } from '@vitest/runner/utils';
|
|
11
11
|
import { SnapshotManager } from '@vitest/snapshot/manager';
|
|
12
|
-
import {
|
|
13
|
-
import { ViteNodeServer } from 'vite-node/server';
|
|
14
|
-
import { v as version$1 } from './cac.CY0IAxC4.js';
|
|
12
|
+
import { v as version$1 } from './cac.WE-urWw5.js';
|
|
15
13
|
import { c as createBirpc } from './index.Bgo3tNWt.js';
|
|
16
|
-
import { p as parse, s as stringify, d as printError, f as formatProjectName, w as withLabel, e as errorBanner, h as divider, i as generateCodeFrame, R as ReportersMap, B as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.
|
|
14
|
+
import { p as parse, s as stringify, d as printError, f as formatProjectName, w as withLabel, e as errorBanner, h as divider, i as generateCodeFrame, R as ReportersMap, B as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.VNI-1z5c.js';
|
|
17
15
|
import require$$0$3 from 'events';
|
|
18
16
|
import require$$1$1 from 'https';
|
|
19
17
|
import require$$2 from 'http';
|
|
@@ -28,22 +26,25 @@ import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
|
|
|
28
26
|
import { parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
29
27
|
import crypto, { createHash } from 'node:crypto';
|
|
30
28
|
import { distDir, rootDir } from '../path.js';
|
|
31
|
-
import { h as hash, R as RandomSequencer, i as isPackageExists, g as getFilePoolName,
|
|
32
|
-
import { c as convertTasksToEvents } from './typechecker.
|
|
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.BPRS6xgn.js';
|
|
30
|
+
import { c as convertTasksToEvents } from './typechecker.Cd1wvxUM.js';
|
|
31
|
+
import { VitestModuleEvaluator } from '#module-evaluator';
|
|
32
|
+
import { ModuleRunner } from 'vite/module-runner';
|
|
33
33
|
import { Console } from 'node:console';
|
|
34
34
|
import c from 'tinyrainbow';
|
|
35
|
-
import { createRequire } from 'node:module';
|
|
36
|
-
import url from 'node:url';
|
|
35
|
+
import { createRequire, builtinModules, isBuiltin } from 'node:module';
|
|
36
|
+
import url, { pathToFileURL } from 'node:url';
|
|
37
37
|
import { i as isTTY, a as isWindows } from './env.D4Lgay0q.js';
|
|
38
38
|
import { rm, mkdir, copyFile } from 'node:fs/promises';
|
|
39
39
|
import nodeos__default, { tmpdir } from 'node:os';
|
|
40
40
|
import pm from 'picomatch';
|
|
41
41
|
import { glob, isDynamicPattern } from 'tinyglobby';
|
|
42
|
-
import
|
|
42
|
+
import MagicString from 'magic-string';
|
|
43
43
|
import { hoistMocksPlugin, automockPlugin } from '@vitest/mocker/node';
|
|
44
44
|
import { c as configDefaults } from './defaults.CXFFjsi8.js';
|
|
45
|
-
import
|
|
46
|
-
import
|
|
45
|
+
import { f as findNearestPackageData } from './resolver.Bx6lE0iq.js';
|
|
46
|
+
import * as esModuleLexer from 'es-module-lexer';
|
|
47
|
+
import { a as BenchmarkReportsMap } from './index.7w0eqmYM.js';
|
|
47
48
|
import assert$1 from 'node:assert';
|
|
48
49
|
import { serializeError } from '@vitest/utils/error';
|
|
49
50
|
import readline from 'node:readline';
|
|
@@ -5016,25 +5017,18 @@ var websocketServerExports = requireWebsocketServer();
|
|
|
5016
5017
|
var WebSocketServer = /*@__PURE__*/getDefaultExportFromCjs(websocketServerExports);
|
|
5017
5018
|
|
|
5018
5019
|
async function getModuleGraph(ctx, projectName, id, browser = false) {
|
|
5019
|
-
const graph = {};
|
|
5020
|
-
const externalized = /* @__PURE__ */ new Set();
|
|
5021
|
-
const inlined = /* @__PURE__ */ new Set();
|
|
5022
|
-
const project = ctx.getProjectByName(projectName);
|
|
5020
|
+
const graph = {}, externalized = /* @__PURE__ */ new Set(), inlined = /* @__PURE__ */ new Set(), project = ctx.getProjectByName(projectName);
|
|
5023
5021
|
async function get(mod, seen = /* @__PURE__ */ new Map()) {
|
|
5024
|
-
if (!mod || !mod.id) return;
|
|
5025
|
-
if (mod.id === "\0@vitest/browser/context") return;
|
|
5022
|
+
if (!mod || !mod.id || mod.id === "\0@vitest/browser/context") return;
|
|
5026
5023
|
if (seen.has(mod)) return seen.get(mod);
|
|
5027
5024
|
let id = clearId(mod.id);
|
|
5028
5025
|
seen.set(mod, id);
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
seen.set(mod, id);
|
|
5034
|
-
} else inlined.add(id);
|
|
5026
|
+
// TODO: how to know if it was rewritten(?) - what is rewritten?
|
|
5027
|
+
const rewrote = browser ? mod.file?.includes(project.browser.vite.config.cacheDir) ? mod.id : false : false;
|
|
5028
|
+
if (rewrote) id = rewrote, externalized.add(id), seen.set(mod, id);
|
|
5029
|
+
else inlined.add(id);
|
|
5035
5030
|
const mods = Array.from(mod.importedModules).filter((i) => i.id && !i.id.includes("/vitest/dist/"));
|
|
5036
|
-
graph[id] = (await Promise.all(mods.map((m) => get(m, seen)))).filter(Boolean);
|
|
5037
|
-
return id;
|
|
5031
|
+
return graph[id] = (await Promise.all(mods.map((m) => get(m, seen)))).filter(Boolean), id;
|
|
5038
5032
|
}
|
|
5039
5033
|
if (browser && project.browser) await get(project.browser.vite.moduleGraph.getModuleById(id));
|
|
5040
5034
|
else await get(project.vite.moduleGraph.getModuleById(id));
|
|
@@ -5086,21 +5080,19 @@ catch {}
|
|
|
5086
5080
|
}
|
|
5087
5081
|
|
|
5088
5082
|
function setup(ctx, _server) {
|
|
5089
|
-
const wss = new WebSocketServer({ noServer: true });
|
|
5090
|
-
const clients = /* @__PURE__ */ new Map();
|
|
5091
|
-
const server = _server || ctx.server;
|
|
5083
|
+
const wss = new WebSocketServer({ noServer: true }), clients = /* @__PURE__ */ new Map(), server = _server || ctx.server;
|
|
5092
5084
|
server.httpServer?.on("upgrade", (request, socket, head) => {
|
|
5093
5085
|
if (!request.url) return;
|
|
5094
5086
|
const { pathname } = new URL(request.url, "http://localhost");
|
|
5095
|
-
if (pathname
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5087
|
+
if (pathname === API_PATH) {
|
|
5088
|
+
if (!isValidApiRequest(ctx.config, request)) {
|
|
5089
|
+
socket.destroy();
|
|
5090
|
+
return;
|
|
5091
|
+
}
|
|
5092
|
+
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
5093
|
+
wss.emit("connection", ws, request), setupClient(ws);
|
|
5094
|
+
});
|
|
5099
5095
|
}
|
|
5100
|
-
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
5101
|
-
wss.emit("connection", ws, request);
|
|
5102
|
-
setupClient(ws);
|
|
5103
|
-
});
|
|
5104
5096
|
});
|
|
5105
5097
|
function setupClient(ws) {
|
|
5106
5098
|
const rpc = createBirpc({
|
|
@@ -5114,8 +5106,7 @@ function setup(ctx, _server) {
|
|
|
5114
5106
|
return ctx.state.getPaths();
|
|
5115
5107
|
},
|
|
5116
5108
|
async readTestFile(id) {
|
|
5117
|
-
|
|
5118
|
-
return promises.readFile(id, "utf-8");
|
|
5109
|
+
return !ctx.state.filesMap.has(id) || !existsSync(id) ? null : promises.readFile(id, "utf-8");
|
|
5119
5110
|
},
|
|
5120
5111
|
async saveTestFile(id, content) {
|
|
5121
5112
|
if (!ctx.state.filesMap.has(id) || !existsSync(id)) throw new Error(`Test file "${id}" was not registered, so it cannot be updated using the API.`);
|
|
@@ -5137,8 +5128,7 @@ function setup(ctx, _server) {
|
|
|
5137
5128
|
}));
|
|
5138
5129
|
},
|
|
5139
5130
|
async getTransformResult(projectName, id, browser = false) {
|
|
5140
|
-
const project = ctx.getProjectByName(projectName);
|
|
5141
|
-
const result = browser ? await project.browser.vite.transformRequest(id) : await project.vitenode.transformRequest(id);
|
|
5131
|
+
const project = ctx.getProjectByName(projectName), result = browser ? await project.browser.vite.transformRequest(id) : await project.vite.transformRequest(id);
|
|
5142
5132
|
if (result) {
|
|
5143
5133
|
try {
|
|
5144
5134
|
result.source = result.source || await promises.readFile(id, "utf-8");
|
|
@@ -5181,56 +5171,49 @@ function setup(ctx, _server) {
|
|
|
5181
5171
|
deserialize: parse,
|
|
5182
5172
|
timeout: -1
|
|
5183
5173
|
});
|
|
5184
|
-
clients.set(ws, rpc)
|
|
5185
|
-
|
|
5186
|
-
clients.delete(ws);
|
|
5187
|
-
rpc.$close(/* @__PURE__ */ new Error("[vitest-api]: Pending methods while closing rpc"));
|
|
5174
|
+
clients.set(ws, rpc), ws.on("close", () => {
|
|
5175
|
+
clients.delete(ws), rpc.$close(/* @__PURE__ */ new Error("[vitest-api]: Pending methods while closing rpc"));
|
|
5188
5176
|
});
|
|
5189
5177
|
}
|
|
5190
5178
|
ctx.reporters.push(new WebSocketReporter(ctx, wss, clients));
|
|
5191
5179
|
}
|
|
5192
5180
|
class WebSocketReporter {
|
|
5193
5181
|
constructor(ctx, wss, clients) {
|
|
5194
|
-
this.ctx = ctx;
|
|
5195
|
-
this.wss = wss;
|
|
5196
|
-
this.clients = clients;
|
|
5182
|
+
this.ctx = ctx, this.wss = wss, this.clients = clients;
|
|
5197
5183
|
}
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
client.onCollected?.(files)?.catch?.(noop);
|
|
5184
|
+
onTestModuleCollected(testModule) {
|
|
5185
|
+
this.clients.size !== 0 && this.clients.forEach((client) => {
|
|
5186
|
+
client.onCollected?.([testModule.task])?.catch?.(noop);
|
|
5202
5187
|
});
|
|
5203
5188
|
}
|
|
5204
|
-
|
|
5189
|
+
onTestRunStart(specifications) {
|
|
5205
5190
|
if (this.clients.size === 0) return;
|
|
5191
|
+
const serializedSpecs = specifications.map((spec) => spec.toJSON());
|
|
5206
5192
|
this.clients.forEach((client) => {
|
|
5207
|
-
client.onSpecsCollected?.(
|
|
5193
|
+
client.onSpecsCollected?.(serializedSpecs)?.catch?.(noop);
|
|
5208
5194
|
});
|
|
5209
5195
|
}
|
|
5210
5196
|
async onTestCaseAnnotate(testCase, annotation) {
|
|
5211
|
-
|
|
5212
|
-
this.clients.forEach((client) => {
|
|
5197
|
+
this.clients.size !== 0 && this.clients.forEach((client) => {
|
|
5213
5198
|
client.onTestAnnotate?.(testCase.id, annotation)?.catch?.(noop);
|
|
5214
5199
|
});
|
|
5215
5200
|
}
|
|
5216
5201
|
async onTaskUpdate(packs, events) {
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
const task = this.ctx.state.idMap.get(taskId);
|
|
5220
|
-
const isBrowser = task && task.file.pool === "browser";
|
|
5202
|
+
this.clients.size !== 0 && (packs.forEach(([taskId, result]) => {
|
|
5203
|
+
const task = this.ctx.state.idMap.get(taskId), isBrowser = task && task.file.pool === "browser";
|
|
5221
5204
|
result?.errors?.forEach((error) => {
|
|
5222
|
-
if (isPrimitive(error))
|
|
5223
|
-
if (isBrowser) {
|
|
5205
|
+
if (!isPrimitive(error)) if (isBrowser) {
|
|
5224
5206
|
const project = this.ctx.getProjectByName(task.file.projectName || "");
|
|
5225
5207
|
error.stacks = project.browser?.parseErrorStacktrace(error);
|
|
5226
5208
|
} else error.stacks = parseErrorStacktrace(error);
|
|
5227
5209
|
});
|
|
5228
|
-
})
|
|
5229
|
-
this.clients.forEach((client) => {
|
|
5210
|
+
}), this.clients.forEach((client) => {
|
|
5230
5211
|
client.onTaskUpdate?.(packs, events)?.catch?.(noop);
|
|
5231
|
-
});
|
|
5212
|
+
}));
|
|
5232
5213
|
}
|
|
5233
|
-
|
|
5214
|
+
onTestRunEnd(testModules, unhandledErrors) {
|
|
5215
|
+
if (!this.clients.size) return;
|
|
5216
|
+
const files = testModules.map((testModule) => testModule.task), errors = [...unhandledErrors];
|
|
5234
5217
|
this.clients.forEach((client) => {
|
|
5235
5218
|
client.onFinished?.(files, errors)?.catch?.(noop);
|
|
5236
5219
|
});
|
|
@@ -5264,23 +5247,18 @@ class BrowserSessions {
|
|
|
5264
5247
|
}
|
|
5265
5248
|
createSession(sessionId, project, pool) {
|
|
5266
5249
|
// this promise only waits for the WS connection with the orhcestrator to be established
|
|
5267
|
-
const defer = createDefer()
|
|
5268
|
-
const timeout = setTimeout(() => {
|
|
5250
|
+
const defer = createDefer(), timeout = setTimeout(() => {
|
|
5269
5251
|
defer.reject(/* @__PURE__ */ new Error(`Failed to connect to the browser session "${sessionId}" [${project.name}] within the timeout.`));
|
|
5270
5252
|
}, project.vitest.config.browser.connectTimeout ?? 6e4).unref();
|
|
5271
|
-
this.sessions.set(sessionId, {
|
|
5253
|
+
return this.sessions.set(sessionId, {
|
|
5272
5254
|
project,
|
|
5273
5255
|
connected: () => {
|
|
5274
|
-
defer.resolve();
|
|
5275
|
-
clearTimeout(timeout);
|
|
5256
|
+
defer.resolve(), clearTimeout(timeout);
|
|
5276
5257
|
},
|
|
5277
5258
|
fail: (error) => {
|
|
5278
|
-
defer.resolve();
|
|
5279
|
-
clearTimeout(timeout);
|
|
5280
|
-
pool.reject(error);
|
|
5259
|
+
defer.resolve(), clearTimeout(timeout), pool.reject(error);
|
|
5281
5260
|
}
|
|
5282
|
-
});
|
|
5283
|
-
return defer;
|
|
5261
|
+
}), defer;
|
|
5284
5262
|
}
|
|
5285
5263
|
}
|
|
5286
5264
|
|
|
@@ -5321,37 +5299,25 @@ class ResultsCache {
|
|
|
5321
5299
|
return this.cachePath;
|
|
5322
5300
|
}
|
|
5323
5301
|
setConfig(root, config) {
|
|
5324
|
-
this.root = root;
|
|
5325
|
-
if (config) this.cachePath = resolve(config.dir, "results.json");
|
|
5302
|
+
if (this.root = root, config) this.cachePath = resolve(config.dir, "results.json");
|
|
5326
5303
|
}
|
|
5327
5304
|
getResults(key) {
|
|
5328
5305
|
return this.cache.get(key);
|
|
5329
5306
|
}
|
|
5330
5307
|
async readFromCache() {
|
|
5331
|
-
if (!this.cachePath) return;
|
|
5332
|
-
|
|
5333
|
-
const resultsCache = await fs.promises.readFile(this.cachePath, "utf8");
|
|
5334
|
-
const { results, version } = JSON.parse(resultsCache || "[]");
|
|
5335
|
-
const [major, minor] = version.split(".");
|
|
5308
|
+
if (!this.cachePath || !fs.existsSync(this.cachePath)) return;
|
|
5309
|
+
const resultsCache = await fs.promises.readFile(this.cachePath, "utf8"), { results, version } = JSON.parse(resultsCache || "[]"), [major, minor] = version.split(".");
|
|
5336
5310
|
// handling changed in 0.30.0
|
|
5337
|
-
if (major > 0 || Number(minor) >= 30) {
|
|
5338
|
-
|
|
5339
|
-
this.
|
|
5340
|
-
|
|
5341
|
-
const [projectName, relativePath] = spec.split(":");
|
|
5342
|
-
const keyMap = this.workspacesKeyMap.get(relativePath) || [];
|
|
5343
|
-
keyMap.push(projectName);
|
|
5344
|
-
this.workspacesKeyMap.set(relativePath, keyMap);
|
|
5345
|
-
});
|
|
5346
|
-
}
|
|
5311
|
+
if (major > 0 || Number(minor) >= 30) this.cache = new Map(results), this.version = version, results.forEach(([spec]) => {
|
|
5312
|
+
const [projectName, relativePath] = spec.split(":"), keyMap = this.workspacesKeyMap.get(relativePath) || [];
|
|
5313
|
+
keyMap.push(projectName), this.workspacesKeyMap.set(relativePath, keyMap);
|
|
5314
|
+
});
|
|
5347
5315
|
}
|
|
5348
5316
|
updateResults(files) {
|
|
5349
5317
|
files.forEach((file) => {
|
|
5350
5318
|
const result = file.result;
|
|
5351
5319
|
if (!result) return;
|
|
5352
|
-
const duration = result.duration || 0;
|
|
5353
|
-
// store as relative, so cache would be the same in CI and locally
|
|
5354
|
-
const relativePath = relative(this.root, file.filepath);
|
|
5320
|
+
const duration = result.duration || 0, relativePath = relative(this.root, file.filepath);
|
|
5355
5321
|
this.cache.set(`${file.projectName || ""}:${relativePath}`, {
|
|
5356
5322
|
duration: duration >= 0 ? duration : 0,
|
|
5357
5323
|
failed: result.state === "fail"
|
|
@@ -5365,8 +5331,7 @@ class ResultsCache {
|
|
|
5365
5331
|
}
|
|
5366
5332
|
async writeToCache() {
|
|
5367
5333
|
if (!this.cachePath) return;
|
|
5368
|
-
const results = Array.from(this.cache.entries());
|
|
5369
|
-
const cacheDirname = dirname(this.cachePath);
|
|
5334
|
+
const results = Array.from(this.cache.entries()), cacheDirname = dirname(this.cachePath);
|
|
5370
5335
|
if (!fs.existsSync(cacheDirname)) await fs.promises.mkdir(cacheDirname, { recursive: true });
|
|
5371
5336
|
const cache = JSON.stringify({
|
|
5372
5337
|
version: this.version,
|
|
@@ -5394,6 +5359,34 @@ class VitestCache {
|
|
|
5394
5359
|
}
|
|
5395
5360
|
}
|
|
5396
5361
|
|
|
5362
|
+
class ServerModuleRunner extends ModuleRunner {
|
|
5363
|
+
constructor(environment, resolver, config) {
|
|
5364
|
+
const fetchModule = createFetchModuleFunction(resolver, false);
|
|
5365
|
+
super({
|
|
5366
|
+
hmr: false,
|
|
5367
|
+
sourcemapInterceptor: "node",
|
|
5368
|
+
transport: { async invoke(event) {
|
|
5369
|
+
if (event.type !== "custom") throw new Error(`Vitest Module Runner doesn't support Vite HMR events.`);
|
|
5370
|
+
const { data } = event.data;
|
|
5371
|
+
try {
|
|
5372
|
+
const result = await fetchModule(data[0], data[1], environment, data[2]);
|
|
5373
|
+
return { result };
|
|
5374
|
+
} catch (error) {
|
|
5375
|
+
return { error };
|
|
5376
|
+
}
|
|
5377
|
+
} }
|
|
5378
|
+
}, new VitestModuleEvaluator()), this.environment = environment, this.config = config;
|
|
5379
|
+
}
|
|
5380
|
+
async import(rawId) {
|
|
5381
|
+
const resolved = await this.environment.pluginContainer.resolveId(rawId, this.config.root);
|
|
5382
|
+
if (!resolved) return super.import(rawId);
|
|
5383
|
+
// Vite will make "@vitest/coverage-v8" into "@vitest/coverage-v8.js" url
|
|
5384
|
+
// instead of using an actual file path-like URL, so we resolve it here first
|
|
5385
|
+
const url = normalizeResolvedIdToUrl(this.environment, resolved.id);
|
|
5386
|
+
return super.import(url);
|
|
5387
|
+
}
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5397
5390
|
class FilesNotFoundError extends Error {
|
|
5398
5391
|
code = "VITEST_FILES_NOT_FOUND";
|
|
5399
5392
|
constructor(mode) {
|
|
@@ -5449,43 +5442,26 @@ function highlightCode(id, source, colors) {
|
|
|
5449
5442
|
});
|
|
5450
5443
|
}
|
|
5451
5444
|
|
|
5452
|
-
const PAD = " ";
|
|
5453
|
-
const ESC$1 = "\x1B[";
|
|
5454
|
-
const ERASE_DOWN = `${ESC$1}J`;
|
|
5455
|
-
const ERASE_SCROLLBACK = `${ESC$1}3J`;
|
|
5456
|
-
const CURSOR_TO_START = `${ESC$1}1;1H`;
|
|
5457
|
-
const HIDE_CURSOR = `${ESC$1}?25l`;
|
|
5458
|
-
const SHOW_CURSOR = `${ESC$1}?25h`;
|
|
5459
|
-
const CLEAR_SCREEN = "\x1Bc";
|
|
5445
|
+
const PAD = " ", ESC$1 = "\x1B[", ERASE_DOWN = `${ESC$1}J`, ERASE_SCROLLBACK = `${ESC$1}3J`, CURSOR_TO_START = `${ESC$1}1;1H`, HIDE_CURSOR = `${ESC$1}?25l`, SHOW_CURSOR = `${ESC$1}?25h`, CLEAR_SCREEN = "\x1Bc";
|
|
5460
5446
|
class Logger {
|
|
5461
5447
|
_clearScreenPending;
|
|
5462
5448
|
_highlights = /* @__PURE__ */ new Map();
|
|
5463
5449
|
cleanupListeners = [];
|
|
5464
5450
|
console;
|
|
5465
5451
|
constructor(ctx, outputStream = process.stdout, errorStream = process.stderr) {
|
|
5466
|
-
this.ctx = ctx
|
|
5467
|
-
this.outputStream = outputStream;
|
|
5468
|
-
this.errorStream = errorStream;
|
|
5469
|
-
this.console = new Console({
|
|
5452
|
+
if (this.ctx = ctx, this.outputStream = outputStream, this.errorStream = errorStream, this.console = new Console({
|
|
5470
5453
|
stdout: outputStream,
|
|
5471
5454
|
stderr: errorStream
|
|
5472
|
-
});
|
|
5473
|
-
this._highlights.clear();
|
|
5474
|
-
this.addCleanupListeners();
|
|
5475
|
-
this.registerUnhandledRejection();
|
|
5476
|
-
if (this.outputStream.isTTY) this.outputStream.write(HIDE_CURSOR);
|
|
5455
|
+
}), this._highlights.clear(), this.addCleanupListeners(), this.registerUnhandledRejection(), this.outputStream.isTTY) this.outputStream.write(HIDE_CURSOR);
|
|
5477
5456
|
}
|
|
5478
5457
|
log(...args) {
|
|
5479
|
-
this._clearScreen();
|
|
5480
|
-
this.console.log(...args);
|
|
5458
|
+
this._clearScreen(), this.console.log(...args);
|
|
5481
5459
|
}
|
|
5482
5460
|
error(...args) {
|
|
5483
|
-
this._clearScreen();
|
|
5484
|
-
this.console.error(...args);
|
|
5461
|
+
this._clearScreen(), this.console.error(...args);
|
|
5485
5462
|
}
|
|
5486
5463
|
warn(...args) {
|
|
5487
|
-
this._clearScreen();
|
|
5488
|
-
this.console.warn(...args);
|
|
5464
|
+
this._clearScreen(), this.console.warn(...args);
|
|
5489
5465
|
}
|
|
5490
5466
|
clearFullScreen(message = "") {
|
|
5491
5467
|
if (!this.ctx.config.clearScreen) {
|
|
@@ -5500,14 +5476,12 @@ class Logger {
|
|
|
5500
5476
|
this.console.log(message);
|
|
5501
5477
|
return;
|
|
5502
5478
|
}
|
|
5503
|
-
this._clearScreenPending = message;
|
|
5504
|
-
if (force) this._clearScreen();
|
|
5479
|
+
if (this._clearScreenPending = message, force) this._clearScreen();
|
|
5505
5480
|
}
|
|
5506
5481
|
_clearScreen() {
|
|
5507
5482
|
if (this._clearScreenPending == null) return;
|
|
5508
5483
|
const log = this._clearScreenPending;
|
|
5509
|
-
this._clearScreenPending = void 0;
|
|
5510
|
-
this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
|
|
5484
|
+
this._clearScreenPending = void 0, this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
|
|
5511
5485
|
}
|
|
5512
5486
|
printError(err, options = {}) {
|
|
5513
5487
|
printError(err, this.ctx, this, options);
|
|
@@ -5522,8 +5496,7 @@ class Logger {
|
|
|
5522
5496
|
highlight(filename, source) {
|
|
5523
5497
|
if (this._highlights.has(filename)) return this._highlights.get(filename);
|
|
5524
5498
|
const code = highlightCode(filename, source);
|
|
5525
|
-
this._highlights.set(filename, code);
|
|
5526
|
-
return code;
|
|
5499
|
+
return this._highlights.set(filename, code), code;
|
|
5527
5500
|
}
|
|
5528
5501
|
printNoTestFound(filters) {
|
|
5529
5502
|
const config = this.ctx.config;
|
|
@@ -5536,34 +5509,22 @@ class Logger {
|
|
|
5536
5509
|
const projectsFilter = toArray(config.project);
|
|
5537
5510
|
if (projectsFilter.length) this.console.error(c.dim("projects: ") + c.yellow(projectsFilter.join(comma)));
|
|
5538
5511
|
this.ctx.projects.forEach((project) => {
|
|
5539
|
-
const config = project.config;
|
|
5540
|
-
const printConfig = !project.isRootProject() && project.name;
|
|
5512
|
+
const config = project.config, printConfig = !project.isRootProject() && project.name;
|
|
5541
5513
|
if (printConfig) this.console.error(`\n${formatProjectName(project)}\n`);
|
|
5542
5514
|
if (config.include) this.console.error(c.dim("include: ") + c.yellow(config.include.join(comma)));
|
|
5543
5515
|
if (config.exclude) this.console.error(c.dim("exclude: ") + c.yellow(config.exclude.join(comma)));
|
|
5544
|
-
if (config.typecheck.enabled)
|
|
5545
|
-
|
|
5546
|
-
this.console.error(c.dim("typecheck exclude: ") + c.yellow(config.typecheck.exclude.join(comma)));
|
|
5547
|
-
}
|
|
5548
|
-
});
|
|
5549
|
-
this.console.error();
|
|
5516
|
+
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)));
|
|
5517
|
+
}), this.console.error();
|
|
5550
5518
|
}
|
|
5551
5519
|
printBanner() {
|
|
5552
5520
|
this.log();
|
|
5553
|
-
const color = this.ctx.config.watch ? "blue" : "cyan";
|
|
5554
|
-
|
|
5555
|
-
this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
|
|
5556
|
-
if (this.ctx.config.sequence.sequencer === RandomSequencer) this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
|
|
5521
|
+
const color = this.ctx.config.watch ? "blue" : "cyan", mode = this.ctx.config.watch ? "DEV" : "RUN";
|
|
5522
|
+
if (this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root)), this.ctx.config.sequence.sequencer === RandomSequencer) this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
|
|
5557
5523
|
if (this.ctx.config.ui) {
|
|
5558
|
-
const host = this.ctx.config.api?.host || "localhost";
|
|
5559
|
-
const port = this.ctx.server.config.server.port;
|
|
5560
|
-
const base = this.ctx.config.uiBase;
|
|
5524
|
+
const host = this.ctx.config.api?.host || "localhost", port = this.ctx.server.config.server.port, base = this.ctx.config.uiBase;
|
|
5561
5525
|
this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
|
|
5562
5526
|
} else if (this.ctx.config.api?.port) {
|
|
5563
|
-
const resolvedUrls = this.ctx.server.resolvedUrls;
|
|
5564
|
-
// workaround for https://github.com/vitejs/vite/issues/15438, it was fixed in vite 5.1
|
|
5565
|
-
const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
|
|
5566
|
-
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
|
|
5527
|
+
const resolvedUrls = this.ctx.server.resolvedUrls, fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`, origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
|
|
5567
5528
|
this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
|
|
5568
5529
|
}
|
|
5569
5530
|
if (this.ctx.coverageProvider) this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
|
|
@@ -5572,35 +5533,26 @@ class Logger {
|
|
|
5572
5533
|
}
|
|
5573
5534
|
printBrowserBanner(project) {
|
|
5574
5535
|
if (!project.browser) return;
|
|
5575
|
-
const resolvedUrls = project.browser.vite.resolvedUrls;
|
|
5576
|
-
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
5536
|
+
const resolvedUrls = project.browser.vite.resolvedUrls, origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
5577
5537
|
if (!origin) return;
|
|
5578
|
-
const output = project.isRootProject() ? "" : formatProjectName(project)
|
|
5579
|
-
const provider = project.browser.provider.name;
|
|
5580
|
-
const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
|
|
5538
|
+
const output = project.isRootProject() ? "" : formatProjectName(project), provider = project.browser.provider.name, providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
|
|
5581
5539
|
this.log(c.dim(`${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/__vitest_test__/", origin))}\n`));
|
|
5582
5540
|
}
|
|
5583
5541
|
printUnhandledErrors(errors) {
|
|
5584
5542
|
const errorMessage = c.red(c.bold(`\nVitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run.
|
|
5585
5543
|
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.`));
|
|
5586
|
-
this.error(errorBanner("Unhandled Errors"))
|
|
5587
|
-
this.error(errorMessage);
|
|
5588
|
-
errors.forEach((err) => {
|
|
5544
|
+
this.error(errorBanner("Unhandled Errors")), this.error(errorMessage), errors.forEach((err) => {
|
|
5589
5545
|
this.printError(err, {
|
|
5590
5546
|
fullStack: true,
|
|
5591
5547
|
type: err.type || "Unhandled Error"
|
|
5592
5548
|
});
|
|
5593
|
-
});
|
|
5594
|
-
this.error(c.red(divider()));
|
|
5549
|
+
}), this.error(c.red(divider()));
|
|
5595
5550
|
}
|
|
5596
5551
|
printSourceTypeErrors(errors) {
|
|
5597
5552
|
const errorMessage = c.red(c.bold(`\nVitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related to your test files.`));
|
|
5598
|
-
this.log(errorBanner("Source Errors"))
|
|
5599
|
-
this.log(errorMessage);
|
|
5600
|
-
errors.forEach((err) => {
|
|
5553
|
+
this.log(errorBanner("Source Errors")), this.log(errorMessage), errors.forEach((err) => {
|
|
5601
5554
|
this.printError(err, { fullStack: true });
|
|
5602
|
-
});
|
|
5603
|
-
this.log(c.red(divider()));
|
|
5555
|
+
}), this.log(c.red(divider()));
|
|
5604
5556
|
}
|
|
5605
5557
|
getColumns() {
|
|
5606
5558
|
return "columns" in this.outputStream ? this.outputStream.columns : 80;
|
|
@@ -5610,38 +5562,25 @@ This might cause false positive tests. Resolve unhandled errors to make sure you
|
|
|
5610
5562
|
}
|
|
5611
5563
|
addCleanupListeners() {
|
|
5612
5564
|
const cleanup = () => {
|
|
5613
|
-
this.cleanupListeners.forEach((fn) => fn());
|
|
5614
|
-
|
|
5615
|
-
};
|
|
5616
|
-
const onExit = (signal, exitCode) => {
|
|
5617
|
-
cleanup();
|
|
5565
|
+
if (this.cleanupListeners.forEach((fn) => fn()), this.outputStream.isTTY) this.outputStream.write(SHOW_CURSOR);
|
|
5566
|
+
}, onExit = (signal, exitCode) => {
|
|
5618
5567
|
// Interrupted signals don't set exit code automatically.
|
|
5619
5568
|
// Use same exit code as node: https://nodejs.org/api/process.html#signal-events
|
|
5620
|
-
if (process.exitCode === void 0) process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
|
|
5569
|
+
if (cleanup(), process.exitCode === void 0) process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
|
|
5621
5570
|
process.exit();
|
|
5622
5571
|
};
|
|
5623
|
-
process.once("SIGINT", onExit)
|
|
5624
|
-
|
|
5625
|
-
process.once("exit", onExit);
|
|
5626
|
-
this.ctx.onClose(() => {
|
|
5627
|
-
process.off("SIGINT", onExit);
|
|
5628
|
-
process.off("SIGTERM", onExit);
|
|
5629
|
-
process.off("exit", onExit);
|
|
5630
|
-
cleanup();
|
|
5572
|
+
process.once("SIGINT", onExit), process.once("SIGTERM", onExit), process.once("exit", onExit), this.ctx.onClose(() => {
|
|
5573
|
+
process.off("SIGINT", onExit), process.off("SIGTERM", onExit), process.off("exit", onExit), cleanup();
|
|
5631
5574
|
});
|
|
5632
5575
|
}
|
|
5633
5576
|
registerUnhandledRejection() {
|
|
5634
5577
|
const onUnhandledRejection = (err) => {
|
|
5635
|
-
process.exitCode = 1
|
|
5636
|
-
this.printError(err, {
|
|
5578
|
+
process.exitCode = 1, this.printError(err, {
|
|
5637
5579
|
fullStack: true,
|
|
5638
5580
|
type: "Unhandled Rejection"
|
|
5639
|
-
});
|
|
5640
|
-
this.error("\n\n");
|
|
5641
|
-
process.exit();
|
|
5581
|
+
}), this.error("\n\n"), process.exit();
|
|
5642
5582
|
};
|
|
5643
|
-
process.on("unhandledRejection", onUnhandledRejection)
|
|
5644
|
-
this.ctx.onClose(() => {
|
|
5583
|
+
process.on("unhandledRejection", onUnhandledRejection), this.ctx.onClose(() => {
|
|
5645
5584
|
process.off("unhandledRejection", onUnhandledRejection);
|
|
5646
5585
|
});
|
|
5647
5586
|
}
|
|
@@ -5657,36 +5596,26 @@ class VitestPackageInstaller {
|
|
|
5657
5596
|
if (process.versions.pnp) {
|
|
5658
5597
|
const targetRequire = createRequire(__dirname);
|
|
5659
5598
|
try {
|
|
5660
|
-
targetRequire.resolve(dependency, { paths: [root, __dirname] });
|
|
5661
|
-
return true;
|
|
5599
|
+
return targetRequire.resolve(dependency, { paths: [root, __dirname] }), true;
|
|
5662
5600
|
} catch {}
|
|
5663
5601
|
}
|
|
5664
5602
|
if (/* @__PURE__ */ isPackageExists(dependency, { paths: [root, __dirname] })) return true;
|
|
5665
|
-
process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEPENDENCY "))} Cannot find dependency '${dependency}'\n\n`));
|
|
5666
|
-
|
|
5667
|
-
const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; });
|
|
5668
|
-
const { install } = await prompts.default({
|
|
5603
|
+
if (process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEPENDENCY "))} Cannot find dependency '${dependency}'\n\n`)), !isTTY) return false;
|
|
5604
|
+
const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; }), { install } = await prompts.default({
|
|
5669
5605
|
type: "confirm",
|
|
5670
5606
|
name: "install",
|
|
5671
5607
|
message: c.reset(`Do you want to install ${c.green(dependency)}?`)
|
|
5672
5608
|
});
|
|
5673
5609
|
if (install) {
|
|
5674
5610
|
const packageName = version ? `${dependency}@${version}` : dependency;
|
|
5675
|
-
await (await import('./index.D3XRDfWc.js')).installPackage(packageName, { dev: true });
|
|
5676
|
-
// TODO: somehow it fails to load the package after installation, remove this when it's fixed
|
|
5677
|
-
process.stderr.write(c.yellow(`\nPackage ${packageName} installed, re-run the command to start.\n`));
|
|
5678
|
-
process.exit();
|
|
5679
|
-
return true;
|
|
5611
|
+
return await (await import('./index.D3XRDfWc.js')).installPackage(packageName, { dev: true }), process.stderr.write(c.yellow(`\nPackage ${packageName} installed, re-run the command to start.\n`)), process.exit(), true;
|
|
5680
5612
|
}
|
|
5681
5613
|
return false;
|
|
5682
5614
|
}
|
|
5683
5615
|
}
|
|
5684
5616
|
|
|
5685
5617
|
function serializeConfig(config, coreConfig, viteConfig) {
|
|
5686
|
-
const optimizer = config.deps?.optimizer;
|
|
5687
|
-
const poolOptions = config.poolOptions;
|
|
5688
|
-
// Resolve from server.config to avoid comparing against default value
|
|
5689
|
-
const isolate = viteConfig?.test?.isolate;
|
|
5618
|
+
const optimizer = config.deps?.optimizer || {}, poolOptions = config.poolOptions, isolate = viteConfig?.test?.isolate;
|
|
5690
5619
|
return {
|
|
5691
5620
|
environmentOptions: config.environmentOptions,
|
|
5692
5621
|
mode: config.mode,
|
|
@@ -5720,8 +5649,7 @@ function serializeConfig(config, coreConfig, viteConfig) {
|
|
|
5720
5649
|
snapshotEnvironment: config.snapshotEnvironment,
|
|
5721
5650
|
passWithNoTests: config.passWithNoTests,
|
|
5722
5651
|
coverage: ((coverage) => {
|
|
5723
|
-
const htmlReporter = coverage.reporter.find(([reporterName]) => reporterName === "html");
|
|
5724
|
-
const subdir = htmlReporter && htmlReporter[1]?.subdir;
|
|
5652
|
+
const htmlReporter = coverage.reporter.find(([reporterName]) => reporterName === "html"), subdir = htmlReporter && htmlReporter[1]?.subdir;
|
|
5725
5653
|
return {
|
|
5726
5654
|
reportsDirectory: coverage.reportsDirectory,
|
|
5727
5655
|
provider: coverage.provider,
|
|
@@ -5745,10 +5673,9 @@ function serializeConfig(config, coreConfig, viteConfig) {
|
|
|
5745
5673
|
},
|
|
5746
5674
|
deps: {
|
|
5747
5675
|
web: config.deps.web || {},
|
|
5748
|
-
optimizer: {
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
},
|
|
5676
|
+
optimizer: Object.entries(optimizer).reduce((acc, [name, option]) => {
|
|
5677
|
+
return acc[name] = { enabled: option?.enabled ?? false }, acc;
|
|
5678
|
+
}, {}),
|
|
5752
5679
|
interopDefault: config.deps.interopDefault,
|
|
5753
5680
|
moduleDirectories: config.deps.moduleDirectories
|
|
5754
5681
|
},
|
|
@@ -5798,7 +5725,7 @@ async function loadGlobalSetupFiles(runner, globalSetup) {
|
|
|
5798
5725
|
return Promise.all(globalSetupFiles.map((file) => loadGlobalSetupFile(file, runner)));
|
|
5799
5726
|
}
|
|
5800
5727
|
async function loadGlobalSetupFile(file, runner) {
|
|
5801
|
-
const m = await runner.
|
|
5728
|
+
const m = await runner.import(file);
|
|
5802
5729
|
for (const exp of [
|
|
5803
5730
|
"default",
|
|
5804
5731
|
"setup",
|
|
@@ -5808,211 +5735,23 @@ async function loadGlobalSetupFile(file, runner) {
|
|
|
5808
5735
|
file,
|
|
5809
5736
|
setup: m.default
|
|
5810
5737
|
};
|
|
5811
|
-
|
|
5738
|
+
if (m.setup || m.teardown) return {
|
|
5812
5739
|
file,
|
|
5813
5740
|
setup: m.setup,
|
|
5814
5741
|
teardown: m.teardown
|
|
5815
5742
|
};
|
|
5816
|
-
|
|
5743
|
+
throw new Error(`invalid globalSetup file ${file}. Must export setup, teardown or have a default export`);
|
|
5817
5744
|
}
|
|
5818
5745
|
|
|
5819
5746
|
function CoverageTransform(ctx) {
|
|
5820
5747
|
return {
|
|
5821
5748
|
name: "vitest:coverage-transform",
|
|
5822
5749
|
transform(srcCode, id) {
|
|
5823
|
-
return ctx.coverageProvider?.onFileTransform?.(srcCode,
|
|
5824
|
-
}
|
|
5825
|
-
};
|
|
5826
|
-
}
|
|
5827
|
-
|
|
5828
|
-
function MocksPlugins(options = {}) {
|
|
5829
|
-
const normalizedDistDir = normalize(distDir);
|
|
5830
|
-
return [hoistMocksPlugin({
|
|
5831
|
-
filter(id) {
|
|
5832
|
-
if (id.includes(normalizedDistDir)) return false;
|
|
5833
|
-
if (options.filter) return options.filter(id);
|
|
5834
|
-
return true;
|
|
5835
|
-
},
|
|
5836
|
-
codeFrameGenerator(node, id, code) {
|
|
5837
|
-
return generateCodeFrame(code, 4, node.start + 1);
|
|
5838
|
-
}
|
|
5839
|
-
}), automockPlugin()];
|
|
5840
|
-
}
|
|
5841
|
-
|
|
5842
|
-
function generateCssFilenameHash(filepath) {
|
|
5843
|
-
return hash("sha1", filepath, "hex").slice(0, 6);
|
|
5844
|
-
}
|
|
5845
|
-
function generateScopedClassName(strategy, name, filename) {
|
|
5846
|
-
// should be configured by Vite defaults
|
|
5847
|
-
if (strategy === "scoped") return null;
|
|
5848
|
-
if (strategy === "non-scoped") return name;
|
|
5849
|
-
const hash = generateCssFilenameHash(filename);
|
|
5850
|
-
return `_${name}_${hash}`;
|
|
5851
|
-
}
|
|
5852
|
-
|
|
5853
|
-
const LogLevels = {
|
|
5854
|
-
silent: 0,
|
|
5855
|
-
error: 1,
|
|
5856
|
-
warn: 2,
|
|
5857
|
-
info: 3
|
|
5858
|
-
};
|
|
5859
|
-
function clearScreen(logger) {
|
|
5860
|
-
const repeatCount = process.stdout.rows - 2;
|
|
5861
|
-
const blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
|
|
5862
|
-
logger.clearScreen(blank);
|
|
5863
|
-
}
|
|
5864
|
-
let lastType;
|
|
5865
|
-
let lastMsg;
|
|
5866
|
-
let sameCount = 0;
|
|
5867
|
-
// Only initialize the timeFormatter when the timestamp option is used, and
|
|
5868
|
-
// reuse it across all loggers
|
|
5869
|
-
let timeFormatter;
|
|
5870
|
-
function getTimeFormatter() {
|
|
5871
|
-
timeFormatter ??= new Intl.DateTimeFormat(void 0, {
|
|
5872
|
-
hour: "numeric",
|
|
5873
|
-
minute: "numeric",
|
|
5874
|
-
second: "numeric"
|
|
5875
|
-
});
|
|
5876
|
-
return timeFormatter;
|
|
5877
|
-
}
|
|
5878
|
-
// This is copy-pasted and needs to be synced from time to time. Ideally, Vite's `createLogger` should accept a custom `console`
|
|
5879
|
-
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/logger.ts?rgh-link-date=2024-10-16T23%3A29%3A19Z
|
|
5880
|
-
// When Vitest supports only Vite 6 and above, we can use Vite's `createLogger({ console })`
|
|
5881
|
-
// https://github.com/vitejs/vite/pull/18379
|
|
5882
|
-
function createViteLogger(console, level = "info", options = {}) {
|
|
5883
|
-
const loggedErrors = /* @__PURE__ */ new WeakSet();
|
|
5884
|
-
const { prefix = "[vite]", allowClearScreen = true } = options;
|
|
5885
|
-
const thresh = LogLevels[level];
|
|
5886
|
-
const canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI;
|
|
5887
|
-
const clear = canClearScreen ? clearScreen : () => {};
|
|
5888
|
-
function format(type, msg, options = {}) {
|
|
5889
|
-
if (options.timestamp) {
|
|
5890
|
-
let tag = "";
|
|
5891
|
-
if (type === "info") tag = c.cyan(c.bold(prefix));
|
|
5892
|
-
else if (type === "warn") tag = c.yellow(c.bold(prefix));
|
|
5893
|
-
else tag = c.red(c.bold(prefix));
|
|
5894
|
-
const environment = options.environment ? `${options.environment} ` : "";
|
|
5895
|
-
return `${c.dim(getTimeFormatter().format(/* @__PURE__ */ new Date()))} ${tag} ${environment}${msg}`;
|
|
5896
|
-
} else return msg;
|
|
5897
|
-
}
|
|
5898
|
-
function output(type, msg, options = {}) {
|
|
5899
|
-
if (thresh >= LogLevels[type]) {
|
|
5900
|
-
const method = type === "info" ? "log" : type;
|
|
5901
|
-
if (options.error) loggedErrors.add(options.error);
|
|
5902
|
-
if (canClearScreen) if (type === lastType && msg === lastMsg) {
|
|
5903
|
-
sameCount++;
|
|
5904
|
-
clear(console);
|
|
5905
|
-
console[method](format(type, msg, options), c.yellow(`(x${sameCount + 1})`));
|
|
5906
|
-
} else {
|
|
5907
|
-
sameCount = 0;
|
|
5908
|
-
lastMsg = msg;
|
|
5909
|
-
lastType = type;
|
|
5910
|
-
if (options.clear) clear(console);
|
|
5911
|
-
console[method](format(type, msg, options));
|
|
5912
|
-
}
|
|
5913
|
-
else console[method](format(type, msg, options));
|
|
5914
|
-
}
|
|
5915
|
-
}
|
|
5916
|
-
const warnedMessages = /* @__PURE__ */ new Set();
|
|
5917
|
-
const logger = {
|
|
5918
|
-
hasWarned: false,
|
|
5919
|
-
info(msg, opts) {
|
|
5920
|
-
output("info", msg, opts);
|
|
5921
|
-
},
|
|
5922
|
-
warn(msg, opts) {
|
|
5923
|
-
logger.hasWarned = true;
|
|
5924
|
-
output("warn", msg, opts);
|
|
5925
|
-
},
|
|
5926
|
-
warnOnce(msg, opts) {
|
|
5927
|
-
if (warnedMessages.has(msg)) return;
|
|
5928
|
-
logger.hasWarned = true;
|
|
5929
|
-
output("warn", msg, opts);
|
|
5930
|
-
warnedMessages.add(msg);
|
|
5931
|
-
},
|
|
5932
|
-
error(msg, opts) {
|
|
5933
|
-
logger.hasWarned = true;
|
|
5934
|
-
output("error", msg, opts);
|
|
5935
|
-
},
|
|
5936
|
-
clearScreen(type) {
|
|
5937
|
-
if (thresh >= LogLevels[type]) clear(console);
|
|
5938
|
-
},
|
|
5939
|
-
hasErrorLogged(error) {
|
|
5940
|
-
return loggedErrors.has(error);
|
|
5941
|
-
}
|
|
5942
|
-
};
|
|
5943
|
-
return logger;
|
|
5944
|
-
}
|
|
5945
|
-
// silence warning by Vite for statically not analyzable dynamic import
|
|
5946
|
-
function silenceImportViteIgnoreWarning(logger) {
|
|
5947
|
-
return {
|
|
5948
|
-
...logger,
|
|
5949
|
-
warn(msg, options) {
|
|
5950
|
-
if (msg.includes("The above dynamic import cannot be analyzed by Vite")) return;
|
|
5951
|
-
logger.warn(msg, options);
|
|
5750
|
+
return ctx.coverageProvider?.onFileTransform?.(srcCode, id, this);
|
|
5952
5751
|
}
|
|
5953
5752
|
};
|
|
5954
5753
|
}
|
|
5955
5754
|
|
|
5956
|
-
const cssLangs = "\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)";
|
|
5957
|
-
const cssLangRE = new RegExp(cssLangs);
|
|
5958
|
-
const cssModuleRE = /* @__PURE__ */ new RegExp(`\\.module${cssLangs}`);
|
|
5959
|
-
const cssInlineRE = /[?&]inline(?:&|$)/;
|
|
5960
|
-
function isCSS(id) {
|
|
5961
|
-
return cssLangRE.test(id);
|
|
5962
|
-
}
|
|
5963
|
-
function isCSSModule(id) {
|
|
5964
|
-
return cssModuleRE.test(id);
|
|
5965
|
-
}
|
|
5966
|
-
// inline css requests are expected to just return the
|
|
5967
|
-
// string content directly and not the proxy module
|
|
5968
|
-
function isInline(id) {
|
|
5969
|
-
return cssInlineRE.test(id);
|
|
5970
|
-
}
|
|
5971
|
-
function getCSSModuleProxyReturn(strategy, filename) {
|
|
5972
|
-
if (strategy === "non-scoped") return "style";
|
|
5973
|
-
const hash = generateCssFilenameHash(filename);
|
|
5974
|
-
return `\`_\${style}_${hash}\``;
|
|
5975
|
-
}
|
|
5976
|
-
function CSSEnablerPlugin(ctx) {
|
|
5977
|
-
const shouldProcessCSS = (id) => {
|
|
5978
|
-
const { css } = ctx.config;
|
|
5979
|
-
if (typeof css === "boolean") return css;
|
|
5980
|
-
if (toArray(css.exclude).some((re) => re.test(id))) return false;
|
|
5981
|
-
if (toArray(css.include).some((re) => re.test(id))) return true;
|
|
5982
|
-
return false;
|
|
5983
|
-
};
|
|
5984
|
-
return [{
|
|
5985
|
-
name: "vitest:css-disable",
|
|
5986
|
-
enforce: "pre",
|
|
5987
|
-
transform(code, id) {
|
|
5988
|
-
if (!isCSS(id)) return;
|
|
5989
|
-
// css plugin inside Vite won't do anything if the code is empty
|
|
5990
|
-
// but it will put __vite__updateStyle anyway
|
|
5991
|
-
if (!shouldProcessCSS(id)) return { code: "" };
|
|
5992
|
-
}
|
|
5993
|
-
}, {
|
|
5994
|
-
name: "vitest:css-empty-post",
|
|
5995
|
-
enforce: "post",
|
|
5996
|
-
transform(_, id) {
|
|
5997
|
-
if (!isCSS(id) || shouldProcessCSS(id)) return;
|
|
5998
|
-
if (isCSSModule(id) && !isInline(id)) {
|
|
5999
|
-
// return proxy for css modules, so that imported module has names:
|
|
6000
|
-
// styles.foo returns a "foo" instead of "undefined"
|
|
6001
|
-
// we don't use code content to generate hash for "scoped", because it's empty
|
|
6002
|
-
const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable";
|
|
6003
|
-
const proxyReturn = getCSSModuleProxyReturn(scopeStrategy, relative(ctx.config.root, id));
|
|
6004
|
-
const code = `export default new Proxy(Object.create(null), {
|
|
6005
|
-
get(_, style) {
|
|
6006
|
-
return ${proxyReturn};
|
|
6007
|
-
},
|
|
6008
|
-
})`;
|
|
6009
|
-
return { code };
|
|
6010
|
-
}
|
|
6011
|
-
return { code: "export default \"\"" };
|
|
6012
|
-
}
|
|
6013
|
-
}];
|
|
6014
|
-
}
|
|
6015
|
-
|
|
6016
5755
|
var jsTokens_1;
|
|
6017
5756
|
var hasRequiredJsTokens;
|
|
6018
5757
|
|
|
@@ -6497,136 +6236,208 @@ function stripLiteralDetailed(code, options) {
|
|
|
6497
6236
|
return stripLiteralJsTokens(code);
|
|
6498
6237
|
}
|
|
6499
6238
|
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
// This makes "href" equal to "http://localhost:3000/path.js" in the browser, but if we keep it like this,
|
|
6504
|
-
// then in tests the URL will become "file:///path.js".
|
|
6505
|
-
// To battle this, we replace "import.meta.url" with "self.location" in the code to keep the browser behavior.
|
|
6506
|
-
function NormalizeURLPlugin() {
|
|
6239
|
+
// so people can reassign envs at runtime
|
|
6240
|
+
// import.meta.env.VITE_NAME = 'app' -> process.env.VITE_NAME = 'app'
|
|
6241
|
+
function MetaEnvReplacerPlugin() {
|
|
6507
6242
|
return {
|
|
6508
|
-
name: "vitest:
|
|
6509
|
-
enforce: "
|
|
6510
|
-
transform(code, id
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
const
|
|
6514
|
-
const
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
while (match = assetImportMetaUrlRE.exec(cleanString)) {
|
|
6519
|
-
const { 0: exp, index } = match;
|
|
6520
|
-
const metaUrlIndex = index + exp.indexOf("import.meta.url");
|
|
6521
|
-
updatedCode = updatedCode.slice(0, metaUrlIndex) + locationString + updatedCode.slice(metaUrlIndex + metaUrlLength);
|
|
6243
|
+
name: "vitest:meta-env-replacer",
|
|
6244
|
+
enforce: "pre",
|
|
6245
|
+
transform(code, id) {
|
|
6246
|
+
if (!/\bimport\.meta\.env\b/.test(code)) return null;
|
|
6247
|
+
let s = null;
|
|
6248
|
+
const cleanCode = stripLiteral(code), envs = cleanCode.matchAll(/\bimport\.meta\.env\b/g);
|
|
6249
|
+
for (const env of envs) {
|
|
6250
|
+
s ||= new MagicString(code);
|
|
6251
|
+
const startIndex = env.index, endIndex = startIndex + env[0].length;
|
|
6252
|
+
s.overwrite(startIndex, endIndex, `Object.assign(/* istanbul ignore next */ globalThis.__vitest_worker__?.metaEnv ?? import.meta.env)`);
|
|
6522
6253
|
}
|
|
6523
|
-
return {
|
|
6524
|
-
code:
|
|
6525
|
-
map:
|
|
6254
|
+
if (s) return {
|
|
6255
|
+
code: s.toString(),
|
|
6256
|
+
map: s.generateMap({
|
|
6257
|
+
hires: "boundary",
|
|
6258
|
+
source: cleanUrl(id)
|
|
6259
|
+
})
|
|
6526
6260
|
};
|
|
6527
6261
|
}
|
|
6528
6262
|
};
|
|
6529
6263
|
}
|
|
6530
6264
|
|
|
6531
|
-
function
|
|
6532
|
-
const
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
newConfig.cacheDir = void 0;
|
|
6540
|
-
newConfig.optimizeDeps = {
|
|
6541
|
-
disabled: true,
|
|
6542
|
-
entries: []
|
|
6543
|
-
};
|
|
6544
|
-
} else {
|
|
6545
|
-
const currentInclude = testOptions.include || viteOptions?.include || [];
|
|
6546
|
-
const exclude = [
|
|
6547
|
-
"vitest",
|
|
6548
|
-
"react",
|
|
6549
|
-
"vue",
|
|
6550
|
-
...testOptions.exclude || viteOptions?.exclude || []
|
|
6551
|
-
];
|
|
6552
|
-
const runtime = currentInclude.filter((n) => n.endsWith("jsx-dev-runtime") || n.endsWith("jsx-runtime"));
|
|
6553
|
-
exclude.push(...runtime);
|
|
6554
|
-
const include = (testOptions.include || viteOptions?.include || []).filter((n) => !exclude.includes(n));
|
|
6555
|
-
newConfig.optimizeDeps = {
|
|
6556
|
-
...viteOptions,
|
|
6557
|
-
...testOptions,
|
|
6558
|
-
noDiscovery: true,
|
|
6559
|
-
disabled: false,
|
|
6560
|
-
entries: [],
|
|
6561
|
-
exclude,
|
|
6562
|
-
include
|
|
6563
|
-
};
|
|
6564
|
-
}
|
|
6565
|
-
// `optimizeDeps.disabled` is deprecated since v5.1.0-beta.1
|
|
6566
|
-
// https://github.com/vitejs/vite/pull/15184
|
|
6567
|
-
if (major >= 5 && minor >= 1 || major >= 6) {
|
|
6568
|
-
if (newConfig.optimizeDeps.disabled) {
|
|
6569
|
-
newConfig.optimizeDeps.noDiscovery = true;
|
|
6570
|
-
newConfig.optimizeDeps.include = [];
|
|
6571
|
-
}
|
|
6572
|
-
delete newConfig.optimizeDeps.disabled;
|
|
6573
|
-
}
|
|
6574
|
-
return newConfig;
|
|
6575
|
-
}
|
|
6576
|
-
function deleteDefineConfig(viteConfig) {
|
|
6577
|
-
const defines = {};
|
|
6578
|
-
if (viteConfig.define) {
|
|
6579
|
-
delete viteConfig.define["import.meta.vitest"];
|
|
6580
|
-
delete viteConfig.define["process.env"];
|
|
6581
|
-
delete viteConfig.define.process;
|
|
6582
|
-
delete viteConfig.define.global;
|
|
6583
|
-
}
|
|
6584
|
-
for (const key in viteConfig.define) {
|
|
6585
|
-
const val = viteConfig.define[key];
|
|
6586
|
-
let replacement;
|
|
6587
|
-
try {
|
|
6588
|
-
replacement = typeof val === "string" ? JSON.parse(val) : val;
|
|
6589
|
-
} catch {
|
|
6590
|
-
// probably means it contains reference to some variable,
|
|
6591
|
-
// like this: "__VAR__": "process.env.VAR"
|
|
6592
|
-
continue;
|
|
6593
|
-
}
|
|
6594
|
-
if (key.startsWith("import.meta.env.")) {
|
|
6595
|
-
const envKey = key.slice(16);
|
|
6596
|
-
process.env[envKey] = replacement;
|
|
6597
|
-
delete viteConfig.define[key];
|
|
6598
|
-
} else if (key.startsWith("process.env.")) {
|
|
6599
|
-
const envKey = key.slice(12);
|
|
6600
|
-
process.env[envKey] = replacement;
|
|
6601
|
-
delete viteConfig.define[key];
|
|
6602
|
-
} else if (!key.includes(".")) {
|
|
6603
|
-
defines[key] = replacement;
|
|
6604
|
-
delete viteConfig.define[key];
|
|
6265
|
+
function MocksPlugins(options = {}) {
|
|
6266
|
+
const normalizedDistDir = normalize(distDir);
|
|
6267
|
+
return [hoistMocksPlugin({
|
|
6268
|
+
filter(id) {
|
|
6269
|
+
return id.includes(normalizedDistDir) ? false : options.filter ? options.filter(id) : true;
|
|
6270
|
+
},
|
|
6271
|
+
codeFrameGenerator(node, id, code) {
|
|
6272
|
+
return generateCodeFrame(code, 4, node.start + 1);
|
|
6605
6273
|
}
|
|
6606
|
-
}
|
|
6607
|
-
return defines;
|
|
6274
|
+
}), automockPlugin()];
|
|
6608
6275
|
}
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
return
|
|
6612
|
-
dirname(rootConfigFile),
|
|
6613
|
-
searchForWorkspaceRoot(projectRoot),
|
|
6614
|
-
rootDir
|
|
6615
|
-
];
|
|
6276
|
+
|
|
6277
|
+
function generateCssFilenameHash(filepath) {
|
|
6278
|
+
return hash("sha1", filepath, "hex").slice(0, 6);
|
|
6616
6279
|
}
|
|
6617
|
-
function
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6280
|
+
function generateScopedClassName(strategy, name, filename) {
|
|
6281
|
+
// should be configured by Vite defaults
|
|
6282
|
+
if (strategy === "scoped") return null;
|
|
6283
|
+
if (strategy === "non-scoped") return name;
|
|
6284
|
+
const hash = generateCssFilenameHash(filename);
|
|
6285
|
+
return `_${name}_${hash}`;
|
|
6622
6286
|
}
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6287
|
+
|
|
6288
|
+
const LogLevels = {
|
|
6289
|
+
silent: 0,
|
|
6290
|
+
error: 1,
|
|
6291
|
+
warn: 2,
|
|
6292
|
+
info: 3
|
|
6293
|
+
};
|
|
6294
|
+
function clearScreen(logger) {
|
|
6295
|
+
const repeatCount = process.stdout.rows - 2, blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
|
|
6296
|
+
logger.clearScreen(blank);
|
|
6297
|
+
}
|
|
6298
|
+
let lastType, lastMsg, sameCount = 0, timeFormatter;
|
|
6299
|
+
function getTimeFormatter() {
|
|
6300
|
+
return timeFormatter ??= new Intl.DateTimeFormat(void 0, {
|
|
6301
|
+
hour: "numeric",
|
|
6302
|
+
minute: "numeric",
|
|
6303
|
+
second: "numeric"
|
|
6304
|
+
}), timeFormatter;
|
|
6305
|
+
}
|
|
6306
|
+
// This is copy-pasted and needs to be synced from time to time. Ideally, Vite's `createLogger` should accept a custom `console`
|
|
6307
|
+
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/logger.ts?rgh-link-date=2024-10-16T23%3A29%3A19Z
|
|
6308
|
+
// When Vitest supports only Vite 6 and above, we can use Vite's `createLogger({ console })`
|
|
6309
|
+
// https://github.com/vitejs/vite/pull/18379
|
|
6310
|
+
function createViteLogger(console, level = "info", options = {}) {
|
|
6311
|
+
const loggedErrors = /* @__PURE__ */ new WeakSet(), { prefix = "[vite]", allowClearScreen = true } = options, thresh = LogLevels[level], canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI, clear = canClearScreen ? clearScreen : () => {};
|
|
6312
|
+
function format(type, msg, options = {}) {
|
|
6313
|
+
if (options.timestamp) {
|
|
6314
|
+
let tag = "";
|
|
6315
|
+
if (type === "info") tag = c.cyan(c.bold(prefix));
|
|
6316
|
+
else if (type === "warn") tag = c.yellow(c.bold(prefix));
|
|
6317
|
+
else tag = c.red(c.bold(prefix));
|
|
6318
|
+
const environment = options.environment ? `${options.environment} ` : "";
|
|
6319
|
+
return `${c.dim(getTimeFormatter().format(/* @__PURE__ */ new Date()))} ${tag} ${environment}${msg}`;
|
|
6320
|
+
} else return msg;
|
|
6628
6321
|
}
|
|
6629
|
-
|
|
6322
|
+
function output(type, msg, options = {}) {
|
|
6323
|
+
if (thresh >= LogLevels[type]) {
|
|
6324
|
+
const method = type === "info" ? "log" : type;
|
|
6325
|
+
if (options.error) loggedErrors.add(options.error);
|
|
6326
|
+
if (canClearScreen) if (type === lastType && msg === lastMsg) sameCount++, clear(console), console[method](format(type, msg, options), c.yellow(`(x${sameCount + 1})`));
|
|
6327
|
+
else {
|
|
6328
|
+
if (sameCount = 0, lastMsg = msg, lastType = type, options.clear) clear(console);
|
|
6329
|
+
console[method](format(type, msg, options));
|
|
6330
|
+
}
|
|
6331
|
+
else console[method](format(type, msg, options));
|
|
6332
|
+
}
|
|
6333
|
+
}
|
|
6334
|
+
const warnedMessages = /* @__PURE__ */ new Set(), logger = {
|
|
6335
|
+
hasWarned: false,
|
|
6336
|
+
info(msg, opts) {
|
|
6337
|
+
output("info", msg, opts);
|
|
6338
|
+
},
|
|
6339
|
+
warn(msg, opts) {
|
|
6340
|
+
logger.hasWarned = true, output("warn", msg, opts);
|
|
6341
|
+
},
|
|
6342
|
+
warnOnce(msg, opts) {
|
|
6343
|
+
warnedMessages.has(msg) || (logger.hasWarned = true, output("warn", msg, opts), warnedMessages.add(msg));
|
|
6344
|
+
},
|
|
6345
|
+
error(msg, opts) {
|
|
6346
|
+
logger.hasWarned = true, output("error", msg, opts);
|
|
6347
|
+
},
|
|
6348
|
+
clearScreen(type) {
|
|
6349
|
+
if (thresh >= LogLevels[type]) clear(console);
|
|
6350
|
+
},
|
|
6351
|
+
hasErrorLogged(error) {
|
|
6352
|
+
return loggedErrors.has(error);
|
|
6353
|
+
}
|
|
6354
|
+
};
|
|
6355
|
+
return logger;
|
|
6356
|
+
}
|
|
6357
|
+
// silence warning by Vite for statically not analyzable dynamic import
|
|
6358
|
+
function silenceImportViteIgnoreWarning(logger) {
|
|
6359
|
+
return {
|
|
6360
|
+
...logger,
|
|
6361
|
+
warn(msg, options) {
|
|
6362
|
+
msg.includes("The above dynamic import cannot be analyzed by Vite") || logger.warn(msg, options);
|
|
6363
|
+
}
|
|
6364
|
+
};
|
|
6365
|
+
}
|
|
6366
|
+
|
|
6367
|
+
const cssLangs = "\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)", cssLangRE = new RegExp(cssLangs), cssModuleRE = /* @__PURE__ */ new RegExp(`\\.module${cssLangs}`), cssInlineRE = /[?&]inline(?:&|$)/;
|
|
6368
|
+
function isCSS(id) {
|
|
6369
|
+
return cssLangRE.test(id);
|
|
6370
|
+
}
|
|
6371
|
+
function isCSSModule(id) {
|
|
6372
|
+
return cssModuleRE.test(id);
|
|
6373
|
+
}
|
|
6374
|
+
// inline css requests are expected to just return the
|
|
6375
|
+
// string content directly and not the proxy module
|
|
6376
|
+
function isInline(id) {
|
|
6377
|
+
return cssInlineRE.test(id);
|
|
6378
|
+
}
|
|
6379
|
+
function getCSSModuleProxyReturn(strategy, filename) {
|
|
6380
|
+
if (strategy === "non-scoped") return "style";
|
|
6381
|
+
const hash = generateCssFilenameHash(filename);
|
|
6382
|
+
return `\`_\${style}_${hash}\``;
|
|
6383
|
+
}
|
|
6384
|
+
function CSSEnablerPlugin(ctx) {
|
|
6385
|
+
const shouldProcessCSS = (id) => {
|
|
6386
|
+
const { css } = ctx.config;
|
|
6387
|
+
return typeof css === "boolean" ? css : toArray(css.exclude).some((re) => re.test(id)) ? false : !!toArray(css.include).some((re) => re.test(id));
|
|
6388
|
+
};
|
|
6389
|
+
return [{
|
|
6390
|
+
name: "vitest:css-disable",
|
|
6391
|
+
enforce: "pre",
|
|
6392
|
+
transform(code, id) {
|
|
6393
|
+
if (isCSS(id) && !shouldProcessCSS(id)) return { code: "" };
|
|
6394
|
+
}
|
|
6395
|
+
}, {
|
|
6396
|
+
name: "vitest:css-empty-post",
|
|
6397
|
+
enforce: "post",
|
|
6398
|
+
transform(_, id) {
|
|
6399
|
+
if (!(!isCSS(id) || shouldProcessCSS(id))) {
|
|
6400
|
+
if (isCSSModule(id) && !isInline(id)) {
|
|
6401
|
+
// return proxy for css modules, so that imported module has names:
|
|
6402
|
+
// styles.foo returns a "foo" instead of "undefined"
|
|
6403
|
+
// we don't use code content to generate hash for "scoped", because it's empty
|
|
6404
|
+
const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable", proxyReturn = getCSSModuleProxyReturn(scopeStrategy, relative(ctx.config.root, id)), code = `export default new Proxy(Object.create(null), {
|
|
6405
|
+
get(_, style) {
|
|
6406
|
+
return ${proxyReturn};
|
|
6407
|
+
},
|
|
6408
|
+
})`;
|
|
6409
|
+
return { code };
|
|
6410
|
+
}
|
|
6411
|
+
return { code: "export default \"\"" };
|
|
6412
|
+
}
|
|
6413
|
+
}
|
|
6414
|
+
}];
|
|
6415
|
+
}
|
|
6416
|
+
|
|
6417
|
+
const metaUrlLength = 15, locationString = "self.location".padEnd(metaUrlLength, " ");
|
|
6418
|
+
// Vite transforms new URL('./path', import.meta.url) to new URL('/path.js', import.meta.url)
|
|
6419
|
+
// This makes "href" equal to "http://localhost:3000/path.js" in the browser, but if we keep it like this,
|
|
6420
|
+
// then in tests the URL will become "file:///path.js".
|
|
6421
|
+
// To battle this, we replace "import.meta.url" with "self.location" in the code to keep the browser behavior.
|
|
6422
|
+
function NormalizeURLPlugin() {
|
|
6423
|
+
return {
|
|
6424
|
+
name: "vitest:normalize-url",
|
|
6425
|
+
enforce: "post",
|
|
6426
|
+
transform(code) {
|
|
6427
|
+
if (this.environment.name !== "client" || !code.includes("new URL") || !code.includes("import.meta.url")) return;
|
|
6428
|
+
const cleanString = stripLiteral(code), assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*(?:'[^']+'|"[^"]+"|`[^`]+`)\s*,\s*(?:'' \+ )?import\.meta\.url\s*(?:,\s*)?\)/g;
|
|
6429
|
+
let updatedCode = code, match;
|
|
6430
|
+
// eslint-disable-next-line no-cond-assign
|
|
6431
|
+
while (match = assetImportMetaUrlRE.exec(cleanString)) {
|
|
6432
|
+
const { 0: exp, index } = match, metaUrlIndex = index + exp.indexOf("import.meta.url");
|
|
6433
|
+
updatedCode = updatedCode.slice(0, metaUrlIndex) + locationString + updatedCode.slice(metaUrlIndex + metaUrlLength);
|
|
6434
|
+
}
|
|
6435
|
+
return {
|
|
6436
|
+
code: updatedCode,
|
|
6437
|
+
map: null
|
|
6438
|
+
};
|
|
6439
|
+
}
|
|
6440
|
+
};
|
|
6630
6441
|
}
|
|
6631
6442
|
|
|
6632
6443
|
function VitestOptimizer() {
|
|
@@ -6635,48 +6446,138 @@ function VitestOptimizer() {
|
|
|
6635
6446
|
config: {
|
|
6636
6447
|
order: "post",
|
|
6637
6448
|
handler(viteConfig) {
|
|
6638
|
-
const testConfig = viteConfig.test || {};
|
|
6639
|
-
const webOptimizer = resolveOptimizerConfig(testConfig.deps?.optimizer?.web, viteConfig.optimizeDeps);
|
|
6640
|
-
const ssrOptimizer = resolveOptimizerConfig(testConfig.deps?.optimizer?.ssr, viteConfig.ssr?.optimizeDeps);
|
|
6641
|
-
const root = resolve(viteConfig.root || process.cwd());
|
|
6642
|
-
const name = viteConfig.test?.name;
|
|
6643
|
-
const label = typeof name === "string" ? name : name?.label || "";
|
|
6449
|
+
const testConfig = viteConfig.test || {}, root = resolve(viteConfig.root || process.cwd()), name = viteConfig.test?.name, label = typeof name === "string" ? name : name?.label || "";
|
|
6644
6450
|
viteConfig.cacheDir = VitestCache.resolveCacheDir(resolve(root || process.cwd()), testConfig.cache != null && testConfig.cache !== false ? testConfig.cache.dir : viteConfig.cacheDir, label);
|
|
6645
|
-
viteConfig.optimizeDeps = webOptimizer.optimizeDeps;
|
|
6646
|
-
viteConfig.ssr ??= {};
|
|
6647
|
-
viteConfig.ssr.optimizeDeps = ssrOptimizer.optimizeDeps;
|
|
6648
6451
|
}
|
|
6649
6452
|
}
|
|
6650
6453
|
};
|
|
6651
6454
|
}
|
|
6652
6455
|
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6456
|
+
function resolveOptimizerConfig(_testOptions, viteOptions) {
|
|
6457
|
+
const testOptions = _testOptions || {};
|
|
6458
|
+
let optimizeDeps;
|
|
6459
|
+
if (testOptions.enabled !== true) testOptions.enabled ??= false, optimizeDeps = {
|
|
6460
|
+
disabled: true,
|
|
6461
|
+
entries: []
|
|
6462
|
+
};
|
|
6463
|
+
else {
|
|
6464
|
+
const currentInclude = testOptions.include || viteOptions?.include || [], exclude = [
|
|
6465
|
+
"vitest",
|
|
6466
|
+
"react",
|
|
6467
|
+
"vue",
|
|
6468
|
+
...testOptions.exclude || viteOptions?.exclude || []
|
|
6469
|
+
], runtime = currentInclude.filter((n) => n.endsWith("jsx-dev-runtime") || n.endsWith("jsx-runtime"));
|
|
6470
|
+
exclude.push(...runtime);
|
|
6471
|
+
const include = (testOptions.include || viteOptions?.include || []).filter((n) => !exclude.includes(n));
|
|
6472
|
+
optimizeDeps = {
|
|
6473
|
+
...viteOptions,
|
|
6474
|
+
...testOptions,
|
|
6475
|
+
noDiscovery: true,
|
|
6476
|
+
disabled: false,
|
|
6477
|
+
entries: [],
|
|
6478
|
+
exclude,
|
|
6479
|
+
include
|
|
6480
|
+
};
|
|
6481
|
+
}
|
|
6482
|
+
// `optimizeDeps.disabled` is deprecated since v5.1.0-beta.1
|
|
6483
|
+
// https://github.com/vitejs/vite/pull/15184
|
|
6484
|
+
if (optimizeDeps.disabled) optimizeDeps.noDiscovery = true, optimizeDeps.include = [];
|
|
6485
|
+
return delete optimizeDeps.disabled, optimizeDeps;
|
|
6486
|
+
}
|
|
6487
|
+
function deleteDefineConfig(viteConfig) {
|
|
6488
|
+
const defines = {};
|
|
6489
|
+
if (viteConfig.define) delete viteConfig.define["import.meta.vitest"], delete viteConfig.define["process.env"], delete viteConfig.define.process, delete viteConfig.define.global;
|
|
6490
|
+
for (const key in viteConfig.define) {
|
|
6491
|
+
const val = viteConfig.define[key];
|
|
6492
|
+
let replacement;
|
|
6493
|
+
try {
|
|
6494
|
+
replacement = typeof val === "string" ? JSON.parse(val) : val;
|
|
6495
|
+
} catch {
|
|
6496
|
+
// probably means it contains reference to some variable,
|
|
6497
|
+
// like this: "__VAR__": "process.env.VAR"
|
|
6498
|
+
continue;
|
|
6499
|
+
}
|
|
6500
|
+
if (key.startsWith("import.meta.env.")) {
|
|
6501
|
+
const envKey = key.slice(16);
|
|
6502
|
+
process.env[envKey] = replacement, delete viteConfig.define[key];
|
|
6503
|
+
} else if (key.startsWith("process.env.")) {
|
|
6504
|
+
const envKey = key.slice(12);
|
|
6505
|
+
process.env[envKey] = replacement, delete viteConfig.define[key];
|
|
6506
|
+
} else if (!key.includes(".")) defines[key] = replacement, delete viteConfig.define[key];
|
|
6507
|
+
}
|
|
6508
|
+
return defines;
|
|
6509
|
+
}
|
|
6510
|
+
function resolveFsAllow(projectRoot, rootConfigFile) {
|
|
6511
|
+
return rootConfigFile ? [
|
|
6512
|
+
dirname(rootConfigFile),
|
|
6513
|
+
searchForWorkspaceRoot(projectRoot),
|
|
6514
|
+
rootDir
|
|
6515
|
+
] : [searchForWorkspaceRoot(projectRoot), rootDir];
|
|
6516
|
+
}
|
|
6517
|
+
function getDefaultResolveOptions() {
|
|
6656
6518
|
return {
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6519
|
+
mainFields: [],
|
|
6520
|
+
conditions: getDefaultServerConditions()
|
|
6521
|
+
};
|
|
6522
|
+
}
|
|
6523
|
+
function getDefaultServerConditions() {
|
|
6524
|
+
const viteMajor = Number(version.split(".")[0]);
|
|
6525
|
+
if (viteMajor >= 6) {
|
|
6526
|
+
const conditions = vite.defaultServerConditions;
|
|
6527
|
+
return conditions.filter((c) => c !== "module");
|
|
6528
|
+
}
|
|
6529
|
+
return ["node"];
|
|
6530
|
+
}
|
|
6531
|
+
|
|
6532
|
+
function ModuleRunnerTransform() {
|
|
6533
|
+
// make sure Vite always applies the module runner transform
|
|
6534
|
+
return {
|
|
6535
|
+
name: "vitest:environments-module-runner",
|
|
6536
|
+
config: {
|
|
6537
|
+
order: "post",
|
|
6538
|
+
handler(config) {
|
|
6539
|
+
const testConfig = config.test || {};
|
|
6540
|
+
config.environments ??= {};
|
|
6541
|
+
const names = new Set(Object.keys(config.environments));
|
|
6542
|
+
names.add("client"), names.add("ssr");
|
|
6543
|
+
const pool = config.test?.pool;
|
|
6544
|
+
if (pool === "vmForks" || pool === "vmThreads") names.add("__vitest_vm__");
|
|
6545
|
+
const external = [], noExternal = [];
|
|
6546
|
+
let noExternalAll;
|
|
6547
|
+
for (const name of names) {
|
|
6548
|
+
config.environments[name] ??= {};
|
|
6549
|
+
const environment = config.environments[name];
|
|
6550
|
+
// vm tests run using the native import mechanism
|
|
6551
|
+
if (environment.dev ??= {}, name === "__vitest_vm__") environment.dev.moduleRunnerTransform = false, environment.consumer = "client";
|
|
6552
|
+
else environment.dev.moduleRunnerTransform = true;
|
|
6553
|
+
environment.dev.preTransformRequests = false, environment.keepProcessEnv = true;
|
|
6554
|
+
const resolveExternal = name === "client" ? config.resolve?.external : [], resolveNoExternal = name === "client" ? config.resolve?.noExternal : [], topLevelResolveOptions = {};
|
|
6555
|
+
if (resolveExternal != null) topLevelResolveOptions.external = resolveExternal;
|
|
6556
|
+
if (resolveNoExternal != null) topLevelResolveOptions.noExternal = resolveNoExternal;
|
|
6557
|
+
const currentResolveOptions = mergeConfig(topLevelResolveOptions, environment.resolve || {}), envNoExternal = resolveViteResolveOptions("noExternal", currentResolveOptions);
|
|
6558
|
+
if (envNoExternal === true) noExternalAll = true;
|
|
6559
|
+
else noExternal.push(...envNoExternal);
|
|
6560
|
+
const envExternal = resolveViteResolveOptions("external", currentResolveOptions);
|
|
6561
|
+
if (envExternal !== true) external.push(...envExternal);
|
|
6562
|
+
if (environment.resolve ??= {}, environment.resolve.external = [...builtinModules, ...builtinModules.map((m) => `node:${m}`)], environment.resolve.noExternal = true, name === "__vitest_vm__" || name === "__vitest__") continue;
|
|
6563
|
+
const currentOptimizeDeps = environment.optimizeDeps || (name === "client" ? config.optimizeDeps : name === "ssr" ? config.ssr?.optimizeDeps : void 0), optimizeDeps = resolveOptimizerConfig(testConfig.deps?.optimizer?.[name], currentOptimizeDeps);
|
|
6564
|
+
// Vite respects the root level optimize deps, so we override it instead
|
|
6565
|
+
if (name === "client") config.optimizeDeps = optimizeDeps, environment.optimizeDeps = void 0;
|
|
6566
|
+
else if (name === "ssr") config.ssr ??= {}, config.ssr.optimizeDeps = optimizeDeps, environment.optimizeDeps = void 0;
|
|
6567
|
+
else environment.optimizeDeps = optimizeDeps;
|
|
6568
|
+
}
|
|
6569
|
+
if (testConfig.server ??= {}, testConfig.server.deps ??= {}, testConfig.server.deps.inline !== true) {
|
|
6570
|
+
if (noExternalAll) testConfig.server.deps.inline = true;
|
|
6571
|
+
else if (noExternal.length) testConfig.server.deps.inline ??= [], testConfig.server.deps.inline.push(...noExternal);
|
|
6572
|
+
}
|
|
6573
|
+
if (external.length) testConfig.server.deps.external ??= [], testConfig.server.deps.external.push(...external);
|
|
6669
6574
|
}
|
|
6670
|
-
if (s) return {
|
|
6671
|
-
code: s.toString(),
|
|
6672
|
-
map: s.generateMap({
|
|
6673
|
-
hires: "boundary",
|
|
6674
|
-
source: cleanUrl(id)
|
|
6675
|
-
})
|
|
6676
|
-
};
|
|
6677
6575
|
}
|
|
6678
6576
|
};
|
|
6679
6577
|
}
|
|
6578
|
+
function resolveViteResolveOptions(key, options) {
|
|
6579
|
+
return Array.isArray(options[key]) ? options[key] : typeof options[key] === "string" || options[key] instanceof RegExp ? [options[key]] : typeof options[key] === "boolean" ? true : [];
|
|
6580
|
+
}
|
|
6680
6581
|
|
|
6681
6582
|
function VitestProjectResolver(ctx) {
|
|
6682
6583
|
const plugin = {
|
|
@@ -6722,23 +6623,16 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
6722
6623
|
};
|
|
6723
6624
|
if (!name) if (typeof options.workspacePath === "string") {
|
|
6724
6625
|
// if there is a package.json, read the name from it
|
|
6725
|
-
const dir = options.workspacePath.endsWith("/") ? options.workspacePath.slice(0, -1) : dirname(options.workspacePath);
|
|
6726
|
-
const pkgJsonPath = resolve(dir, "package.json");
|
|
6626
|
+
const dir = options.workspacePath.endsWith("/") ? options.workspacePath.slice(0, -1) : dirname(options.workspacePath), pkgJsonPath = resolve(dir, "package.json");
|
|
6727
6627
|
if (existsSync(pkgJsonPath)) name = JSON.parse(readFileSync(pkgJsonPath, "utf-8")).name;
|
|
6728
6628
|
if (typeof name !== "string" || !name) name = basename(dir);
|
|
6729
6629
|
} else name = options.workspacePath.toString();
|
|
6730
|
-
const isUserBrowserEnabled = viteConfig.test?.browser?.enabled;
|
|
6731
|
-
const isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled);
|
|
6732
|
-
// keep project names to potentially filter it out
|
|
6733
|
-
const workspaceNames = [name];
|
|
6734
|
-
const browser = viteConfig.test.browser || {};
|
|
6630
|
+
const isUserBrowserEnabled = viteConfig.test?.browser?.enabled, isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled), workspaceNames = [name], browser = viteConfig.test.browser || {};
|
|
6735
6631
|
if (isBrowserEnabled && browser.name && !browser.instances?.length)
|
|
6736
6632
|
// vitest injects `instances` in this case later on
|
|
6737
6633
|
workspaceNames.push(name ? `${name} (${browser.name})` : browser.name);
|
|
6738
6634
|
viteConfig.test?.browser?.instances?.forEach((instance) => {
|
|
6739
|
-
|
|
6740
|
-
instance.name ??= name ? `${name} (${instance.browser})` : instance.browser;
|
|
6741
|
-
if (isBrowserEnabled) workspaceNames.push(instance.name);
|
|
6635
|
+
if (instance.name ??= name ? `${name} (${instance.browser})` : instance.browser, isBrowserEnabled) workspaceNames.push(instance.name);
|
|
6742
6636
|
});
|
|
6743
6637
|
const filters = project.vitest.config.project;
|
|
6744
6638
|
// if there is `--project=...` filter, check if any of the potential projects match
|
|
@@ -6750,10 +6644,13 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
6750
6644
|
});
|
|
6751
6645
|
if (!hasProject) throw new VitestFilteredOutProjectError();
|
|
6752
6646
|
}
|
|
6753
|
-
return {
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6647
|
+
return {
|
|
6648
|
+
environments: { __vitest__: { dev: {} } },
|
|
6649
|
+
test: { name: {
|
|
6650
|
+
label: name,
|
|
6651
|
+
color
|
|
6652
|
+
} }
|
|
6653
|
+
};
|
|
6757
6654
|
}
|
|
6758
6655
|
},
|
|
6759
6656
|
{
|
|
@@ -6763,22 +6660,14 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
6763
6660
|
this.meta.watchMode = false;
|
|
6764
6661
|
},
|
|
6765
6662
|
config(viteConfig) {
|
|
6766
|
-
const defines = deleteDefineConfig(viteConfig);
|
|
6767
|
-
|
|
6768
|
-
const root = testConfig.root || viteConfig.root || options.root;
|
|
6769
|
-
const resolveOptions = getDefaultResolveOptions();
|
|
6770
|
-
const config = {
|
|
6663
|
+
const defines = deleteDefineConfig(viteConfig), testConfig = viteConfig.test || {}, root = testConfig.root || viteConfig.root || options.root, resolveOptions = getDefaultResolveOptions();
|
|
6664
|
+
let config = {
|
|
6771
6665
|
root,
|
|
6772
6666
|
define: { "process.env.NODE_ENV": "process.env.NODE_ENV" },
|
|
6773
6667
|
resolve: {
|
|
6774
6668
|
...resolveOptions,
|
|
6775
6669
|
alias: testConfig.alias
|
|
6776
6670
|
},
|
|
6777
|
-
esbuild: viteConfig.esbuild === false ? false : {
|
|
6778
|
-
target: viteConfig.esbuild?.target || "node18",
|
|
6779
|
-
sourcemap: "external",
|
|
6780
|
-
legalComments: "inline"
|
|
6781
|
-
},
|
|
6782
6671
|
server: {
|
|
6783
6672
|
watch: null,
|
|
6784
6673
|
open: false,
|
|
@@ -6791,19 +6680,27 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
6791
6680
|
environments: { ssr: { resolve: resolveOptions } },
|
|
6792
6681
|
test: {}
|
|
6793
6682
|
};
|
|
6683
|
+
if ("rolldownVersion" in vite) config = {
|
|
6684
|
+
...config,
|
|
6685
|
+
oxc: viteConfig.oxc === false ? false : { target: viteConfig.oxc?.target || "node18" }
|
|
6686
|
+
};
|
|
6687
|
+
else config = {
|
|
6688
|
+
...config,
|
|
6689
|
+
esbuild: viteConfig.esbuild === false ? false : {
|
|
6690
|
+
target: viteConfig.esbuild?.target || "node18",
|
|
6691
|
+
sourcemap: "external",
|
|
6692
|
+
legalComments: "inline"
|
|
6693
|
+
}
|
|
6694
|
+
};
|
|
6794
6695
|
config.test.defines = defines;
|
|
6795
6696
|
const classNameStrategy = typeof testConfig.css !== "boolean" && testConfig.css?.modules?.classNameStrategy || "stable";
|
|
6796
6697
|
if (classNameStrategy !== "scoped") {
|
|
6797
|
-
config.css ??= {}
|
|
6798
|
-
config.css.modules ??= {};
|
|
6799
|
-
if (config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
|
|
6698
|
+
if (config.css ??= {}, config.css.modules ??= {}, config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
|
|
6800
6699
|
const root = project.config.root;
|
|
6801
6700
|
return generateScopedClassName(classNameStrategy, name, relative(root, filename));
|
|
6802
6701
|
};
|
|
6803
6702
|
}
|
|
6804
|
-
config.customLogger = createViteLogger(project.vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false });
|
|
6805
|
-
config.customLogger = silenceImportViteIgnoreWarning(config.customLogger);
|
|
6806
|
-
return config;
|
|
6703
|
+
return config.customLogger = createViteLogger(project.vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false }), config.customLogger = silenceImportViteIgnoreWarning(config.customLogger), config;
|
|
6807
6704
|
}
|
|
6808
6705
|
},
|
|
6809
6706
|
{
|
|
@@ -6811,20 +6708,119 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
6811
6708
|
enforce: "post",
|
|
6812
6709
|
async configureServer(server) {
|
|
6813
6710
|
const options = deepMerge({}, configDefaults, server.config.test || {});
|
|
6814
|
-
await project._configureServer(options, server);
|
|
6815
|
-
await server.watcher.close();
|
|
6711
|
+
await project._configureServer(options, server), await server.watcher.close();
|
|
6816
6712
|
}
|
|
6817
6713
|
},
|
|
6818
|
-
|
|
6714
|
+
MetaEnvReplacerPlugin(),
|
|
6819
6715
|
...CSSEnablerPlugin(project),
|
|
6820
6716
|
CoverageTransform(project.vitest),
|
|
6821
6717
|
...MocksPlugins(),
|
|
6822
6718
|
VitestProjectResolver(project.vitest),
|
|
6823
6719
|
VitestOptimizer(),
|
|
6824
|
-
NormalizeURLPlugin()
|
|
6720
|
+
NormalizeURLPlugin(),
|
|
6721
|
+
ModuleRunnerTransform()
|
|
6825
6722
|
];
|
|
6826
6723
|
}
|
|
6827
6724
|
|
|
6725
|
+
class VitestResolver {
|
|
6726
|
+
options;
|
|
6727
|
+
externalizeCache = /* @__PURE__ */ new Map();
|
|
6728
|
+
constructor(cacheDir, config) {
|
|
6729
|
+
this.options = {
|
|
6730
|
+
moduleDirectories: config.deps.moduleDirectories,
|
|
6731
|
+
inlineFiles: config.setupFiles.flatMap((file) => {
|
|
6732
|
+
if (file.startsWith("file://")) return file;
|
|
6733
|
+
const resolvedId = resolve(file);
|
|
6734
|
+
return [resolvedId, pathToFileURL(resolvedId).href];
|
|
6735
|
+
}),
|
|
6736
|
+
cacheDir,
|
|
6737
|
+
inline: config.server.deps?.inline,
|
|
6738
|
+
external: config.server.deps?.external
|
|
6739
|
+
};
|
|
6740
|
+
}
|
|
6741
|
+
shouldExternalize(file) {
|
|
6742
|
+
return shouldExternalize(normalizeId(file), this.options, this.externalizeCache);
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6745
|
+
function normalizeId(id) {
|
|
6746
|
+
if (id.startsWith("/@fs/")) id = id.slice(isWindows ? 5 : 4);
|
|
6747
|
+
return id;
|
|
6748
|
+
}
|
|
6749
|
+
const BUILTIN_EXTENSIONS = new Set([
|
|
6750
|
+
".mjs",
|
|
6751
|
+
".cjs",
|
|
6752
|
+
".node",
|
|
6753
|
+
".wasm"
|
|
6754
|
+
]), ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/, ESM_FOLDER_RE = /\/(es|esm)\/(.*\.js)$/, defaultInline = [
|
|
6755
|
+
/virtual:/,
|
|
6756
|
+
/\.[mc]?ts$/,
|
|
6757
|
+
/[?&](init|raw|url|inline)\b/,
|
|
6758
|
+
KNOWN_ASSET_RE,
|
|
6759
|
+
/^(?!.*node_modules).*\.mjs$/,
|
|
6760
|
+
/^(?!.*node_modules).*\.cjs\.js$/,
|
|
6761
|
+
/vite\w*\/dist\/client\/env.mjs/
|
|
6762
|
+
], depsExternal = [/\/node_modules\/.*\.cjs\.js$/, /\/node_modules\/.*\.mjs$/];
|
|
6763
|
+
function guessCJSversion(id) {
|
|
6764
|
+
if (id.match(ESM_EXT_RE)) {
|
|
6765
|
+
for (const i of [
|
|
6766
|
+
id.replace(ESM_EXT_RE, ".mjs"),
|
|
6767
|
+
id.replace(ESM_EXT_RE, ".umd.js"),
|
|
6768
|
+
id.replace(ESM_EXT_RE, ".cjs.js"),
|
|
6769
|
+
id.replace(ESM_EXT_RE, ".js")
|
|
6770
|
+
]) if (existsSync(i)) return i;
|
|
6771
|
+
}
|
|
6772
|
+
if (id.match(ESM_FOLDER_RE)) {
|
|
6773
|
+
for (const i of [
|
|
6774
|
+
id.replace(ESM_FOLDER_RE, "/umd/$1"),
|
|
6775
|
+
id.replace(ESM_FOLDER_RE, "/cjs/$1"),
|
|
6776
|
+
id.replace(ESM_FOLDER_RE, "/lib/$1"),
|
|
6777
|
+
id.replace(ESM_FOLDER_RE, "/$1")
|
|
6778
|
+
]) if (existsSync(i)) return i;
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
// The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98
|
|
6782
|
+
async function isValidNodeImport(id) {
|
|
6783
|
+
const extension = extname(id);
|
|
6784
|
+
if (BUILTIN_EXTENSIONS.has(extension)) return true;
|
|
6785
|
+
if (extension !== ".js") return false;
|
|
6786
|
+
id = id.replace("file:///", "");
|
|
6787
|
+
const package_ = findNearestPackageData(dirname(id));
|
|
6788
|
+
if (package_.type === "module") return true;
|
|
6789
|
+
if (/\.(?:\w+-)?esm?(?:-\w+)?\.js$|\/esm?\//.test(id)) return false;
|
|
6790
|
+
try {
|
|
6791
|
+
await esModuleLexer.init;
|
|
6792
|
+
const code = await promises.readFile(id, "utf8"), [, , , hasModuleSyntax] = esModuleLexer.parse(code);
|
|
6793
|
+
return !hasModuleSyntax;
|
|
6794
|
+
} catch {
|
|
6795
|
+
return false;
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
async function shouldExternalize(id, options, cache) {
|
|
6799
|
+
if (!cache.has(id)) cache.set(id, _shouldExternalize(id, options));
|
|
6800
|
+
return cache.get(id);
|
|
6801
|
+
}
|
|
6802
|
+
async function _shouldExternalize(id, options) {
|
|
6803
|
+
// data: should be processed by native import,
|
|
6804
|
+
// since it is a feature of ESM.
|
|
6805
|
+
// also externalize network imports since nodejs allows it when --experimental-network-imports
|
|
6806
|
+
if (isBuiltin(id) || id.startsWith("data:") || /^(?:https?:)?\/\//.test(id)) return id;
|
|
6807
|
+
const moduleDirectories = options?.moduleDirectories || ["/node_modules/"];
|
|
6808
|
+
if (matchExternalizePattern(id, moduleDirectories, options?.inline) || options?.inlineFiles && options?.inlineFiles.includes(id)) return false;
|
|
6809
|
+
// Unless the user explicitly opted to inline them, externalize Vite deps.
|
|
6810
|
+
// They are too big to inline by default.
|
|
6811
|
+
if (matchExternalizePattern(id, moduleDirectories, options?.external) || options?.cacheDir && id.includes(options.cacheDir)) return id;
|
|
6812
|
+
const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir)), guessCJS = isLibraryModule && options?.fallbackCJS;
|
|
6813
|
+
return id = guessCJS ? guessCJSversion(id) || id : id, matchExternalizePattern(id, moduleDirectories, defaultInline) ? false : matchExternalizePattern(id, moduleDirectories, depsExternal) || isLibraryModule && await isValidNodeImport(id) ? id : false;
|
|
6814
|
+
}
|
|
6815
|
+
function matchExternalizePattern(id, moduleDirectories, patterns) {
|
|
6816
|
+
if (patterns == null) return false;
|
|
6817
|
+
if (patterns === true) return true;
|
|
6818
|
+
for (const ex of patterns) if (typeof ex === "string") {
|
|
6819
|
+
if (moduleDirectories.some((dir) => id.includes(join(dir, ex)))) return true;
|
|
6820
|
+
} else if (ex.test(id)) return true;
|
|
6821
|
+
return false;
|
|
6822
|
+
}
|
|
6823
|
+
|
|
6828
6824
|
class TestSpecification {
|
|
6829
6825
|
/**
|
|
6830
6826
|
* @deprecated use `project` instead
|
|
@@ -6860,24 +6856,16 @@ class TestSpecification {
|
|
|
6860
6856
|
*/
|
|
6861
6857
|
testLines;
|
|
6862
6858
|
constructor(project, moduleId, pool, testLines) {
|
|
6863
|
-
this[0] = project;
|
|
6864
|
-
|
|
6865
|
-
this
|
|
6866
|
-
const name = project.config.name;
|
|
6867
|
-
const hashName = pool !== "typescript" ? name : name ? `${name}:__typecheck__` : "__typecheck__";
|
|
6868
|
-
this.taskId = generateFileHash(relative(project.config.root, moduleId), hashName);
|
|
6869
|
-
this.project = project;
|
|
6870
|
-
this.moduleId = moduleId;
|
|
6871
|
-
this.pool = pool;
|
|
6872
|
-
this.testLines = testLines;
|
|
6859
|
+
this[0] = project, this[1] = moduleId, this[2] = { pool };
|
|
6860
|
+
const name = project.config.name, hashName = pool !== "typescript" ? name : name ? `${name}:__typecheck__` : "__typecheck__";
|
|
6861
|
+
this.taskId = generateFileHash(relative(project.config.root, moduleId), hashName), this.project = project, this.moduleId = moduleId, this.pool = pool, this.testLines = testLines;
|
|
6873
6862
|
}
|
|
6874
6863
|
/**
|
|
6875
6864
|
* Test module associated with the specification.
|
|
6876
6865
|
*/
|
|
6877
6866
|
get testModule() {
|
|
6878
6867
|
const task = this.project.vitest.state.idMap.get(this.taskId);
|
|
6879
|
-
|
|
6880
|
-
return this.project.vitest.state.getReportedEntity(task);
|
|
6868
|
+
return task ? this.project.vitest.state.getReportedEntity(task) : void 0;
|
|
6881
6869
|
}
|
|
6882
6870
|
toJSON() {
|
|
6883
6871
|
return [
|
|
@@ -6897,9 +6885,7 @@ class TestSpecification {
|
|
|
6897
6885
|
* @deprecated
|
|
6898
6886
|
*/
|
|
6899
6887
|
*[Symbol.iterator]() {
|
|
6900
|
-
yield this.project;
|
|
6901
|
-
yield this.moduleId;
|
|
6902
|
-
yield this.pool;
|
|
6888
|
+
yield this.project, yield this.moduleId, yield this.pool;
|
|
6903
6889
|
}
|
|
6904
6890
|
}
|
|
6905
6891
|
|
|
@@ -6908,12 +6894,10 @@ async function createViteServer(inlineConfig) {
|
|
|
6908
6894
|
// But Vitest works correctly either way
|
|
6909
6895
|
const error = console.error;
|
|
6910
6896
|
console.error = (...args) => {
|
|
6911
|
-
|
|
6912
|
-
error(...args);
|
|
6897
|
+
typeof args[0] === "string" && args[0].includes("WebSocket server error:") || error(...args);
|
|
6913
6898
|
};
|
|
6914
6899
|
const server = await createServer(inlineConfig);
|
|
6915
|
-
console.error = error;
|
|
6916
|
-
return server;
|
|
6900
|
+
return console.error = error, server;
|
|
6917
6901
|
}
|
|
6918
6902
|
|
|
6919
6903
|
class TestProject {
|
|
@@ -6936,11 +6920,11 @@ class TestProject {
|
|
|
6936
6920
|
* Temporary directory for the project. This is unique for each project. Vitest stores transformed content here.
|
|
6937
6921
|
*/
|
|
6938
6922
|
tmpDir = join(tmpdir(), nanoid());
|
|
6939
|
-
/** @internal */ vitenode;
|
|
6940
6923
|
/** @internal */ typechecker;
|
|
6941
6924
|
/** @internal */ _config;
|
|
6942
6925
|
/** @internal */ _vite;
|
|
6943
6926
|
/** @internal */ _hash;
|
|
6927
|
+
/** @internal */ _resolver;
|
|
6944
6928
|
runner;
|
|
6945
6929
|
closingPromise;
|
|
6946
6930
|
testFilesList = null;
|
|
@@ -6948,11 +6932,7 @@ class TestProject {
|
|
|
6948
6932
|
_globalSetups;
|
|
6949
6933
|
_provided = {};
|
|
6950
6934
|
constructor(path, vitest, options) {
|
|
6951
|
-
this.path = path;
|
|
6952
|
-
this.options = options;
|
|
6953
|
-
this.vitest = vitest;
|
|
6954
|
-
this.ctx = vitest;
|
|
6955
|
-
this.globalConfig = vitest.config;
|
|
6935
|
+
this.path = path, this.options = options, this.vitest = vitest, this.ctx = vitest, this.globalConfig = vitest.config;
|
|
6956
6936
|
}
|
|
6957
6937
|
/**
|
|
6958
6938
|
* The unique hash of this project. This value is consistent between the reruns.
|
|
@@ -6981,10 +6961,9 @@ class TestProject {
|
|
|
6981
6961
|
* Get the provided context. The project context is merged with the global context.
|
|
6982
6962
|
*/
|
|
6983
6963
|
getProvidedContext() {
|
|
6984
|
-
if (this.isRootProject()) return this._provided;
|
|
6985
6964
|
// globalSetup can run even if core workspace is not part of the test run
|
|
6986
6965
|
// so we need to inherit its provided context
|
|
6987
|
-
return {
|
|
6966
|
+
return this.isRootProject() ? this._provided : {
|
|
6988
6967
|
...this.vitest.getRootProject().getProvidedContext(),
|
|
6989
6968
|
...this._provided
|
|
6990
6969
|
};
|
|
@@ -7008,13 +6987,11 @@ class TestProject {
|
|
|
7008
6987
|
*/
|
|
7009
6988
|
get vite() {
|
|
7010
6989
|
if (!this._vite) throw new Error("The server was not set. It means that `project.vite` was called before the Vite server was established.");
|
|
7011
|
-
|
|
7012
|
-
Object.defineProperty(this, "vite", {
|
|
6990
|
+
return Object.defineProperty(this, "vite", {
|
|
7013
6991
|
configurable: true,
|
|
7014
6992
|
writable: true,
|
|
7015
6993
|
value: this._vite
|
|
7016
|
-
});
|
|
7017
|
-
return this._vite;
|
|
6994
|
+
}), this._vite;
|
|
7018
6995
|
}
|
|
7019
6996
|
/**
|
|
7020
6997
|
* Resolved project configuration.
|
|
@@ -7071,13 +7048,14 @@ class TestProject {
|
|
|
7071
7048
|
}
|
|
7072
7049
|
/** @internal */
|
|
7073
7050
|
async _initializeGlobalSetup() {
|
|
7074
|
-
if (this._globalSetups)
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7051
|
+
if (!this._globalSetups) {
|
|
7052
|
+
this._globalSetups = await loadGlobalSetupFiles(this.runner, this.config.globalSetup);
|
|
7053
|
+
for (const globalSetupFile of this._globalSetups) {
|
|
7054
|
+
const teardown = await globalSetupFile.setup?.(this);
|
|
7055
|
+
if (teardown == null || !!globalSetupFile.teardown) continue;
|
|
7056
|
+
if (typeof teardown !== "function") throw new TypeError(`invalid return value in globalSetup file ${globalSetupFile.file}. Must return a function`);
|
|
7057
|
+
globalSetupFile.teardown = teardown;
|
|
7058
|
+
}
|
|
7081
7059
|
}
|
|
7082
7060
|
}
|
|
7083
7061
|
onTestsRerun(cb) {
|
|
@@ -7089,8 +7067,7 @@ class TestProject {
|
|
|
7089
7067
|
}
|
|
7090
7068
|
/** @internal */
|
|
7091
7069
|
async _teardownGlobalSetup() {
|
|
7092
|
-
if (
|
|
7093
|
-
for (const globalSetupFile of [...this._globalSetups].reverse()) await globalSetupFile.teardown?.();
|
|
7070
|
+
if (this._globalSetups) for (const globalSetupFile of [...this._globalSetups].reverse()) await globalSetupFile.teardown?.();
|
|
7094
7071
|
}
|
|
7095
7072
|
/** @deprecated use `vitest.logger` instead */
|
|
7096
7073
|
get logger() {
|
|
@@ -7120,12 +7097,8 @@ class TestProject {
|
|
|
7120
7097
|
* @param filters String filters to match the test files.
|
|
7121
7098
|
*/
|
|
7122
7099
|
async globTestFiles(filters = []) {
|
|
7123
|
-
const dir = this.config.dir || this.config.root;
|
|
7124
|
-
|
|
7125
|
-
const typecheck = this.config.typecheck;
|
|
7126
|
-
const [testFiles, typecheckTestFiles] = await Promise.all([typecheck.enabled && typecheck.only ? [] : this.globAllTestFiles(include, exclude, includeSource, dir), typecheck.enabled ? this.typecheckFilesList || this.globFiles(typecheck.include, typecheck.exclude, dir) : []]);
|
|
7127
|
-
this.typecheckFilesList = typecheckTestFiles;
|
|
7128
|
-
return {
|
|
7100
|
+
const dir = this.config.dir || this.config.root, { include, exclude, includeSource } = this.config, typecheck = this.config.typecheck, [testFiles, typecheckTestFiles] = await Promise.all([typecheck.enabled && typecheck.only ? [] : this.globAllTestFiles(include, exclude, includeSource, dir), typecheck.enabled ? this.typecheckFilesList || this.globFiles(typecheck.include, typecheck.exclude, dir) : []]);
|
|
7101
|
+
return this.typecheckFilesList = typecheckTestFiles, {
|
|
7129
7102
|
testFiles: this.filterFiles(testFiles, filters, dir),
|
|
7130
7103
|
typecheckTestFiles: this.filterFiles(typecheckTestFiles, filters, dir)
|
|
7131
7104
|
};
|
|
@@ -7144,8 +7117,7 @@ class TestProject {
|
|
|
7144
7117
|
}
|
|
7145
7118
|
}));
|
|
7146
7119
|
}
|
|
7147
|
-
this.testFilesList = testFiles;
|
|
7148
|
-
return testFiles;
|
|
7120
|
+
return this.testFilesList = testFiles, testFiles;
|
|
7149
7121
|
}
|
|
7150
7122
|
isBrowserEnabled() {
|
|
7151
7123
|
return isBrowserEnabled(this.config);
|
|
@@ -7182,8 +7154,7 @@ class TestProject {
|
|
|
7182
7154
|
cwd,
|
|
7183
7155
|
ignore: exclude,
|
|
7184
7156
|
expandDirectories: false
|
|
7185
|
-
};
|
|
7186
|
-
const files = await glob(include, globOptions);
|
|
7157
|
+
}, files = await glob(include, globOptions);
|
|
7187
7158
|
// keep the slashes consistent with Vite
|
|
7188
7159
|
// we are not using the pathe here because it normalizes the drive letter on Windows
|
|
7189
7160
|
// and we want to keep it the same as working dir
|
|
@@ -7196,16 +7167,10 @@ class TestProject {
|
|
|
7196
7167
|
if (this._isCachedTestFile(moduleId)) return true;
|
|
7197
7168
|
const relativeId = relative(this.config.dir || this.config.root, moduleId);
|
|
7198
7169
|
if (pm.isMatch(relativeId, this.config.exclude)) return false;
|
|
7199
|
-
if (pm.isMatch(relativeId, this.config.include))
|
|
7200
|
-
this.markTestFile(moduleId);
|
|
7201
|
-
return true;
|
|
7202
|
-
}
|
|
7170
|
+
if (pm.isMatch(relativeId, this.config.include)) return this.markTestFile(moduleId), true;
|
|
7203
7171
|
if (this.config.includeSource?.length && pm.isMatch(relativeId, this.config.includeSource)) {
|
|
7204
7172
|
const code = source?.() || readFileSync(moduleId, "utf-8");
|
|
7205
|
-
if (this.isInSourceTestCode(code))
|
|
7206
|
-
this.markTestFile(moduleId);
|
|
7207
|
-
return true;
|
|
7208
|
-
}
|
|
7173
|
+
if (this.isInSourceTestCode(code)) return this.markTestFile(moduleId), true;
|
|
7209
7174
|
}
|
|
7210
7175
|
return false;
|
|
7211
7176
|
}
|
|
@@ -7218,7 +7183,7 @@ class TestProject {
|
|
|
7218
7183
|
}
|
|
7219
7184
|
filterFiles(testFiles, filters, dir) {
|
|
7220
7185
|
if (filters.length && process.platform === "win32") filters = filters.map((f) => slash(f));
|
|
7221
|
-
|
|
7186
|
+
return filters.length ? testFiles.filter((t) => {
|
|
7222
7187
|
const testFile = relative(dir, t).toLocaleLowerCase();
|
|
7223
7188
|
return filters.some((f) => {
|
|
7224
7189
|
// if filter is a full file path, we should include it if it's in the same folder
|
|
@@ -7226,8 +7191,7 @@ class TestProject {
|
|
|
7226
7191
|
const relativePath = f.endsWith("/") ? join(relative(dir, f), "/") : relative(dir, f);
|
|
7227
7192
|
return testFile.includes(f.toLocaleLowerCase()) || testFile.includes(relativePath.toLocaleLowerCase());
|
|
7228
7193
|
});
|
|
7229
|
-
});
|
|
7230
|
-
return testFiles;
|
|
7194
|
+
}) : testFiles;
|
|
7231
7195
|
}
|
|
7232
7196
|
_parentBrowser;
|
|
7233
7197
|
/** @internal */
|
|
@@ -7238,25 +7202,23 @@ class TestProject {
|
|
|
7238
7202
|
await this.vitest.packageInstaller.ensureInstalled("@vitest/browser", this.config.root, this.vitest.version);
|
|
7239
7203
|
const { createBrowserServer, distRoot } = await import('@vitest/browser');
|
|
7240
7204
|
let cacheDir;
|
|
7241
|
-
const browser = await createBrowserServer(this, this.vite.config.configFile, [
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7205
|
+
const browser = await createBrowserServer(this, this.vite.config.configFile, [
|
|
7206
|
+
{
|
|
7207
|
+
name: "vitest:browser-cacheDir",
|
|
7208
|
+
configResolved(config) {
|
|
7209
|
+
cacheDir = config.cacheDir;
|
|
7210
|
+
}
|
|
7211
|
+
},
|
|
7212
|
+
...MocksPlugins({ filter(id) {
|
|
7213
|
+
return !(id.includes(distRoot) || id.includes(cacheDir));
|
|
7214
|
+
} }),
|
|
7215
|
+
MetaEnvReplacerPlugin()
|
|
7216
|
+
], [CoverageTransform(this.vitest)]);
|
|
7217
|
+
if (this._parentBrowser = browser, this.config.browser.ui) setup(this.vitest, browser.vite);
|
|
7252
7218
|
});
|
|
7253
7219
|
/** @internal */
|
|
7254
7220
|
_initBrowserServer = deduped(async () => {
|
|
7255
|
-
await this._parent?._initParentBrowser();
|
|
7256
|
-
if (!this.browser && this._parent?._parentBrowser) {
|
|
7257
|
-
this.browser = this._parent._parentBrowser.spawn(this);
|
|
7258
|
-
await this.vitest.report("onBrowserInit", this);
|
|
7259
|
-
}
|
|
7221
|
+
if (await this._parent?._initParentBrowser(), !this.browser && this._parent?._parentBrowser) this.browser = this._parent._parentBrowser.spawn(this), await this.vitest.report("onBrowserInit", this);
|
|
7260
7222
|
});
|
|
7261
7223
|
/**
|
|
7262
7224
|
* Closes the project and all associated resources. This can only be called once; the closing promise is cached until the server restarts.
|
|
@@ -7269,8 +7231,7 @@ class TestProject {
|
|
|
7269
7231
|
this.browser?.close(),
|
|
7270
7232
|
this.clearTmpDir()
|
|
7271
7233
|
].filter(Boolean)).then(() => {
|
|
7272
|
-
this._provided = {};
|
|
7273
|
-
this._vite = void 0;
|
|
7234
|
+
this._provided = {}, this._vite = void 0;
|
|
7274
7235
|
});
|
|
7275
7236
|
return this.closingPromise;
|
|
7276
7237
|
}
|
|
@@ -7279,7 +7240,7 @@ class TestProject {
|
|
|
7279
7240
|
* @param moduleId The ID of the module in Vite module graph
|
|
7280
7241
|
*/
|
|
7281
7242
|
import(moduleId) {
|
|
7282
|
-
return this.runner.
|
|
7243
|
+
return this.runner.import(moduleId);
|
|
7283
7244
|
}
|
|
7284
7245
|
/** @deprecated use `name` instead */
|
|
7285
7246
|
getName() {
|
|
@@ -7294,36 +7255,22 @@ class TestProject {
|
|
|
7294
7255
|
}
|
|
7295
7256
|
/** @internal */
|
|
7296
7257
|
async _configureServer(options, server) {
|
|
7297
|
-
this._config = resolveConfig(this.vitest, {
|
|
7258
|
+
for (const _providedKey in this._config = resolveConfig(this.vitest, {
|
|
7298
7259
|
...options,
|
|
7299
7260
|
coverage: this.vitest.config.coverage
|
|
7300
|
-
}, server.config)
|
|
7301
|
-
this._setHash();
|
|
7302
|
-
for (const _providedKey in this.config.provide) {
|
|
7261
|
+
}, server.config), this._setHash(), this.config.provide) {
|
|
7303
7262
|
const providedKey = _providedKey;
|
|
7304
7263
|
// type is very strict here, so we cast it to any
|
|
7305
7264
|
this.provide(providedKey, this.config.provide[providedKey]);
|
|
7306
7265
|
}
|
|
7307
|
-
this.closingPromise = void 0;
|
|
7308
|
-
|
|
7309
|
-
this.
|
|
7310
|
-
const node = this.vitenode;
|
|
7311
|
-
this.runner = new ViteNodeRunner({
|
|
7312
|
-
root: server.config.root,
|
|
7313
|
-
base: server.config.base,
|
|
7314
|
-
fetchModule(id) {
|
|
7315
|
-
return node.fetchModule(id);
|
|
7316
|
-
},
|
|
7317
|
-
resolveId(id, importer) {
|
|
7318
|
-
return node.resolveId(id, importer);
|
|
7319
|
-
}
|
|
7320
|
-
});
|
|
7266
|
+
this.closingPromise = void 0, this._resolver = new VitestResolver(server.config.cacheDir, this._config), this._vite = server;
|
|
7267
|
+
const environment = server.environments.__vitest__;
|
|
7268
|
+
this.runner = new ServerModuleRunner(environment, this._resolver, this._config);
|
|
7321
7269
|
}
|
|
7322
7270
|
_serializeOverriddenConfig() {
|
|
7323
7271
|
// TODO: serialize the config _once_ or when needed
|
|
7324
7272
|
const config = serializeConfig(this.config, this.vitest.config, this.vite.config);
|
|
7325
|
-
|
|
7326
|
-
return deepMerge(config, this.vitest.configOverride);
|
|
7273
|
+
return this.vitest.configOverride ? deepMerge(config, this.vitest.configOverride) : config;
|
|
7327
7274
|
}
|
|
7328
7275
|
async clearTmpDir() {
|
|
7329
7276
|
try {
|
|
@@ -7336,9 +7283,10 @@ class TestProject {
|
|
|
7336
7283
|
}
|
|
7337
7284
|
/** @internal */
|
|
7338
7285
|
_initBrowserProvider = deduped(async () => {
|
|
7339
|
-
if (!this.isBrowserEnabled() || this.browser?.provider)
|
|
7340
|
-
|
|
7341
|
-
|
|
7286
|
+
if (!(!this.isBrowserEnabled() || this.browser?.provider)) {
|
|
7287
|
+
if (!this.browser) await this._initBrowserServer();
|
|
7288
|
+
await this.browser?.initBrowserProvider(this);
|
|
7289
|
+
}
|
|
7342
7290
|
});
|
|
7343
7291
|
/** @internal */
|
|
7344
7292
|
_provideObject(context) {
|
|
@@ -7351,40 +7299,25 @@ class TestProject {
|
|
|
7351
7299
|
/** @internal */
|
|
7352
7300
|
static _createBasicProject(vitest) {
|
|
7353
7301
|
const project = new TestProject(vitest.config.name || vitest.config.root, vitest);
|
|
7354
|
-
project.
|
|
7355
|
-
project.runner = vitest.runner;
|
|
7356
|
-
project._vite = vitest.server;
|
|
7357
|
-
project._config = vitest.config;
|
|
7358
|
-
project._setHash();
|
|
7359
|
-
project._provideObject(vitest.config.provide);
|
|
7360
|
-
return project;
|
|
7302
|
+
return project.runner = vitest.runner, project._vite = vitest.server, project._config = vitest.config, project._resolver = vitest._resolver, project._setHash(), project._provideObject(vitest.config.provide), project;
|
|
7361
7303
|
}
|
|
7362
7304
|
/** @internal */
|
|
7363
7305
|
static _cloneBrowserProject(parent, config) {
|
|
7364
7306
|
const clone = new TestProject(parent.path, parent.vitest);
|
|
7365
|
-
clone.
|
|
7366
|
-
clone.runner = parent.runner;
|
|
7367
|
-
clone._vite = parent._vite;
|
|
7368
|
-
clone._config = config;
|
|
7369
|
-
clone._setHash();
|
|
7370
|
-
clone._parent = parent;
|
|
7371
|
-
clone._provideObject(config.provide);
|
|
7372
|
-
return clone;
|
|
7307
|
+
return clone.runner = parent.runner, clone._vite = parent._vite, clone._resolver = parent._resolver, clone._config = config, clone._setHash(), clone._parent = parent, clone._provideObject(config.provide), clone;
|
|
7373
7308
|
}
|
|
7374
7309
|
}
|
|
7375
7310
|
function deduped(cb) {
|
|
7376
7311
|
let _promise;
|
|
7377
|
-
return (...args) => {
|
|
7312
|
+
return ((...args) => {
|
|
7378
7313
|
if (!_promise) _promise = cb(...args).finally(() => {
|
|
7379
7314
|
_promise = void 0;
|
|
7380
7315
|
});
|
|
7381
7316
|
return _promise;
|
|
7382
|
-
};
|
|
7317
|
+
});
|
|
7383
7318
|
}
|
|
7384
7319
|
async function initializeProject(workspacePath, ctx, options) {
|
|
7385
|
-
const project = new TestProject(workspacePath, ctx, options)
|
|
7386
|
-
const { configFile,...restOptions } = options;
|
|
7387
|
-
const config = {
|
|
7320
|
+
const project = new TestProject(workspacePath, ctx, options), { configFile,...restOptions } = options, config = {
|
|
7388
7321
|
...restOptions,
|
|
7389
7322
|
configFile,
|
|
7390
7323
|
configLoader: ctx.vite.config.inlineConfig.configLoader,
|
|
@@ -7394,25 +7327,20 @@ async function initializeProject(workspacePath, ctx, options) {
|
|
|
7394
7327
|
workspacePath
|
|
7395
7328
|
})]
|
|
7396
7329
|
};
|
|
7397
|
-
await createViteServer(config);
|
|
7398
|
-
return project;
|
|
7330
|
+
return await createViteServer(config), project;
|
|
7399
7331
|
}
|
|
7400
7332
|
function generateHash(str) {
|
|
7401
7333
|
let hash = 0;
|
|
7402
7334
|
if (str.length === 0) return `${hash}`;
|
|
7403
7335
|
for (let i = 0; i < str.length; i++) {
|
|
7404
7336
|
const char = str.charCodeAt(i);
|
|
7405
|
-
hash = (hash << 5) - hash + char;
|
|
7406
|
-
hash = hash & hash;
|
|
7337
|
+
hash = (hash << 5) - hash + char, hash = hash & hash;
|
|
7407
7338
|
}
|
|
7408
7339
|
return `${hash}`;
|
|
7409
7340
|
}
|
|
7410
7341
|
|
|
7411
7342
|
async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projectsDefinition, names) {
|
|
7412
|
-
const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition)
|
|
7413
|
-
// cli options that affect the project config,
|
|
7414
|
-
// not all options are allowed to be overridden
|
|
7415
|
-
const overridesOptions = [
|
|
7343
|
+
const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition), overridesOptions = [
|
|
7416
7344
|
"logHeapUsage",
|
|
7417
7345
|
"allowOnly",
|
|
7418
7346
|
"sequence",
|
|
@@ -7431,21 +7359,12 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
|
|
|
7431
7359
|
"inspect",
|
|
7432
7360
|
"inspectBrk",
|
|
7433
7361
|
"fileParallelism"
|
|
7434
|
-
]
|
|
7435
|
-
const cliOverrides = overridesOptions.reduce((acc, name) => {
|
|
7362
|
+
], cliOverrides = overridesOptions.reduce((acc, name) => {
|
|
7436
7363
|
if (name in cliOptions) acc[name] = cliOptions[name];
|
|
7437
7364
|
return acc;
|
|
7438
|
-
}, {});
|
|
7439
|
-
const projectPromises = [];
|
|
7440
|
-
const fileProjects = [...configFiles, ...nonConfigDirectories];
|
|
7441
|
-
const concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
|
|
7365
|
+
}, {}), projectPromises = [], fileProjects = [...configFiles, ...nonConfigDirectories], concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
|
|
7442
7366
|
projectConfigs.forEach((options, index) => {
|
|
7443
|
-
const configRoot = vitest.config.root;
|
|
7444
|
-
// if extends a config file, resolve the file path
|
|
7445
|
-
const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : options.extends === true ? vitest.vite.config.configFile || false : false;
|
|
7446
|
-
// if `root` is configured, resolve it relative to the workspace file or vite root (like other options)
|
|
7447
|
-
// if `root` is not specified, inline configs use the same root as the root project
|
|
7448
|
-
const root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
|
|
7367
|
+
const configRoot = vitest.config.root, configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : options.extends === true ? vitest.vite.config.configFile || false : false, root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
|
|
7449
7368
|
projectPromises.push(concurrent(() => initializeProject(index, vitest, {
|
|
7450
7369
|
...options,
|
|
7451
7370
|
root,
|
|
@@ -7463,8 +7382,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
|
|
|
7463
7382
|
if (project) projectPromises.push(Promise.resolve(project));
|
|
7464
7383
|
continue;
|
|
7465
7384
|
}
|
|
7466
|
-
const configFile = path.endsWith("/") ? false : path;
|
|
7467
|
-
const root = path.endsWith("/") ? path : dirname(path);
|
|
7385
|
+
const configFile = path.endsWith("/") ? false : path, root = path.endsWith("/") ? path : dirname(path);
|
|
7468
7386
|
projectPromises.push(concurrent(() => initializeProject(path, vitest, {
|
|
7469
7387
|
root,
|
|
7470
7388
|
configFile,
|
|
@@ -7477,9 +7395,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
|
|
|
7477
7395
|
vitest.config.project.length ? `The filter matched no projects: ${vitest.config.project.join(", ")}. ` : "",
|
|
7478
7396
|
`The projects definition: ${JSON.stringify(projectsDefinition, null, 4)}.`
|
|
7479
7397
|
].join(""));
|
|
7480
|
-
const resolvedProjectsPromises = await Promise.allSettled(projectPromises);
|
|
7481
|
-
const errors = [];
|
|
7482
|
-
const resolvedProjects = [];
|
|
7398
|
+
const resolvedProjectsPromises = await Promise.allSettled(projectPromises), errors = [], resolvedProjects = [];
|
|
7483
7399
|
for (const result of resolvedProjectsPromises) if (result.status === "rejected") {
|
|
7484
7400
|
if (result.reason instanceof VitestFilteredOutProjectError)
|
|
7485
7401
|
// filter out filtered out projects
|
|
@@ -7491,8 +7407,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
|
|
|
7491
7407
|
for (const project of resolvedProjects) {
|
|
7492
7408
|
const name = project.name;
|
|
7493
7409
|
if (names.has(name)) {
|
|
7494
|
-
const duplicate = resolvedProjects.find((p) => p.name === name && p !== project)
|
|
7495
|
-
const filesError = fileProjects.length ? [
|
|
7410
|
+
const duplicate = resolvedProjects.find((p) => p.name === name && p !== project), filesError = fileProjects.length ? [
|
|
7496
7411
|
"\n\nYour config matched these files:\n",
|
|
7497
7412
|
fileProjects.map((p) => ` - ${relative(vitest.config.root, p)}`).join("\n"),
|
|
7498
7413
|
"\n\n"
|
|
@@ -7514,24 +7429,18 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
|
|
|
7514
7429
|
const removeProjects = /* @__PURE__ */ new Set();
|
|
7515
7430
|
resolvedProjects.forEach((project) => {
|
|
7516
7431
|
if (!project.config.browser.enabled) return;
|
|
7517
|
-
const instances = project.config.browser.instances || [];
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
}
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
"Read more: https://vitest.dev/guide/browser/config#browser-instances"
|
|
7530
|
-
].filter(Boolean).join("")));
|
|
7531
|
-
}
|
|
7532
|
-
const originalName = project.config.name;
|
|
7533
|
-
// if original name is in the --project=name filter, keep all instances
|
|
7534
|
-
const filteredInstances = vitest.matchesProjectFilter(originalName) ? instances : instances.filter((instance) => {
|
|
7432
|
+
const instances = project.config.browser.instances || [], browser = project.config.browser.name;
|
|
7433
|
+
if (instances.length === 0 && browser) instances.push({
|
|
7434
|
+
browser,
|
|
7435
|
+
name: project.name ? `${project.name} (${browser})` : browser
|
|
7436
|
+
}), vitest.logger.warn(withLabel("yellow", "Vitest", [
|
|
7437
|
+
`No browser "instances" were defined`,
|
|
7438
|
+
project.name ? ` for the "${project.name}" project. ` : ". ",
|
|
7439
|
+
`Running tests in "${project.config.browser.name}" browser. `,
|
|
7440
|
+
"The \"browser.name\" field is deprecated since Vitest 3. ",
|
|
7441
|
+
"Read more: https://vitest.dev/guide/browser/config#browser-instances"
|
|
7442
|
+
].filter(Boolean).join("")));
|
|
7443
|
+
const originalName = project.config.name, filteredInstances = vitest.matchesProjectFilter(originalName) ? instances : instances.filter((instance) => {
|
|
7535
7444
|
const newName = instance.name;
|
|
7536
7445
|
return vitest.matchesProjectFilter(newName);
|
|
7537
7446
|
});
|
|
@@ -7544,8 +7453,7 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
|
|
|
7544
7453
|
filteredInstances.forEach((config, index) => {
|
|
7545
7454
|
const browser = config.browser;
|
|
7546
7455
|
if (!browser) {
|
|
7547
|
-
const nth = index + 1;
|
|
7548
|
-
const ending = nth === 2 ? "nd" : nth === 3 ? "rd" : "th";
|
|
7456
|
+
const nth = index + 1, ending = nth === 2 ? "nd" : nth === 3 ? "rd" : "th";
|
|
7549
7457
|
throw new Error(`The browser configuration must have a "browser" property. The ${nth}${ending} item in "browser.instances" doesn't have it. Make sure your${originalName ? ` "${originalName}"` : ""} configuration is correct.`);
|
|
7550
7458
|
}
|
|
7551
7459
|
const name = config.name;
|
|
@@ -7560,18 +7468,15 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
|
|
|
7560
7468
|
clonedConfig.name = name;
|
|
7561
7469
|
const clone = TestProject._cloneBrowserProject(project, clonedConfig);
|
|
7562
7470
|
resolvedProjects.push(clone);
|
|
7563
|
-
});
|
|
7564
|
-
|
|
7565
|
-
});
|
|
7566
|
-
resolvedProjects = resolvedProjects.filter((project) => !removeProjects.has(project));
|
|
7471
|
+
}), removeProjects.add(project);
|
|
7472
|
+
}), resolvedProjects = resolvedProjects.filter((project) => !removeProjects.has(project));
|
|
7567
7473
|
const headedBrowserProjects = resolvedProjects.filter((project) => {
|
|
7568
7474
|
return project.config.browser.enabled && !project.config.browser.headless;
|
|
7569
7475
|
});
|
|
7570
7476
|
if (headedBrowserProjects.length > 1) {
|
|
7571
7477
|
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("");
|
|
7572
7478
|
if (!isTTY) throw new Error(`${message} Please, filter projects with --browser=name or --project=name flag or run tests with "headless: true" option.`);
|
|
7573
|
-
const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; })
|
|
7574
|
-
const { projectName } = await prompts.default({
|
|
7479
|
+
const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; }), { projectName } = await prompts.default({
|
|
7575
7480
|
type: "select",
|
|
7576
7481
|
name: "projectName",
|
|
7577
7482
|
choices: headedBrowserProjects.map((project) => ({
|
|
@@ -7586,10 +7491,9 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
|
|
|
7586
7491
|
return resolvedProjects;
|
|
7587
7492
|
}
|
|
7588
7493
|
function cloneConfig(project, { browser,...config }) {
|
|
7589
|
-
const { locators, viewport, testerHtmlPath, headless, screenshotDirectory, screenshotFailures, browser: _browser, name,...overrideConfig } = config;
|
|
7590
|
-
const currentConfig = project.config.browser;
|
|
7494
|
+
const { locators, viewport, testerHtmlPath, headless, screenshotDirectory, screenshotFailures, browser: _browser, name,...overrideConfig } = config, currentConfig = project.config.browser, clonedConfig = deepClone(project.config);
|
|
7591
7495
|
return mergeConfig({
|
|
7592
|
-
...
|
|
7496
|
+
...clonedConfig,
|
|
7593
7497
|
browser: {
|
|
7594
7498
|
...project.config.browser,
|
|
7595
7499
|
locators: locators ? { testIdAttribute: locators.testIdAttribute ?? currentConfig.locators.testIdAttribute } : project.config.browser.locators,
|
|
@@ -7601,18 +7505,15 @@ function cloneConfig(project, { browser,...config }) {
|
|
|
7601
7505
|
name: browser,
|
|
7602
7506
|
providerOptions: config,
|
|
7603
7507
|
instances: void 0
|
|
7604
|
-
}
|
|
7508
|
+
},
|
|
7509
|
+
include: overrideConfig.include && overrideConfig.include.length > 0 ? [] : clonedConfig.include,
|
|
7510
|
+
exclude: overrideConfig.exclude && overrideConfig.exclude.length > 0 ? [] : clonedConfig.exclude,
|
|
7511
|
+
includeSource: overrideConfig.includeSource && overrideConfig.includeSource.length > 0 ? [] : clonedConfig.includeSource
|
|
7605
7512
|
}, overrideConfig);
|
|
7606
7513
|
}
|
|
7607
7514
|
async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition) {
|
|
7608
7515
|
// project configurations that were specified directly
|
|
7609
|
-
const projectsOptions = [];
|
|
7610
|
-
// custom config files that were specified directly or resolved from a directory
|
|
7611
|
-
const projectsConfigFiles = [];
|
|
7612
|
-
// custom glob matches that should be resolved as directories or config files
|
|
7613
|
-
const projectsGlobMatches = [];
|
|
7614
|
-
// directories that don't have a config file inside, but should be treated as projects
|
|
7615
|
-
const nonConfigProjectDirectories = [];
|
|
7516
|
+
const projectsOptions = [], projectsConfigFiles = [], projectsGlobMatches = [], nonConfigProjectDirectories = [];
|
|
7616
7517
|
for (const definition of projectsDefinition) if (typeof definition === "string") {
|
|
7617
7518
|
const stringOption = definition.replace("<rootDir>", vitest.config.root);
|
|
7618
7519
|
// if the string doesn't contain a glob, we can resolve it directly
|
|
@@ -7656,8 +7557,7 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
|
|
|
7656
7557
|
"**/*.timestamp-*",
|
|
7657
7558
|
"**/.DS_Store"
|
|
7658
7559
|
]
|
|
7659
|
-
};
|
|
7660
|
-
const projectsFs = await glob(projectsGlobMatches, globOptions);
|
|
7560
|
+
}, projectsFs = await glob(projectsGlobMatches, globOptions);
|
|
7661
7561
|
await Promise.all(projectsFs.map(async (path) => {
|
|
7662
7562
|
// directories are allowed with a glob like `packages/*`
|
|
7663
7563
|
// in this case every directory is treated as a project
|
|
@@ -7676,21 +7576,15 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
|
|
|
7676
7576
|
};
|
|
7677
7577
|
}
|
|
7678
7578
|
async function resolveDirectoryConfig(directory) {
|
|
7679
|
-
const files = new Set(await promises.readdir(directory));
|
|
7680
|
-
|
|
7681
|
-
// this simulates how `findUp` works in packages/vitest/src/node/create.ts:29
|
|
7682
|
-
const configFile = configFiles.find((file) => files.has(file));
|
|
7683
|
-
if (configFile) return resolve(directory, configFile);
|
|
7684
|
-
return null;
|
|
7579
|
+
const files = new Set(await promises.readdir(directory)), configFile = configFiles.find((file) => files.has(file));
|
|
7580
|
+
return configFile ? resolve(directory, configFile) : null;
|
|
7685
7581
|
}
|
|
7686
7582
|
function getDefaultTestProject(vitest) {
|
|
7687
|
-
const filter = vitest.config.project;
|
|
7688
|
-
const project = vitest._ensureRootProject();
|
|
7583
|
+
const filter = vitest.config.project, project = vitest._ensureRootProject();
|
|
7689
7584
|
if (!filter.length) return project;
|
|
7690
7585
|
// check for the project name and browser names
|
|
7691
7586
|
const hasProjects = getPotentialProjectNames(project).some((p) => vitest.matchesProjectFilter(p));
|
|
7692
|
-
|
|
7693
|
-
return null;
|
|
7587
|
+
return hasProjects ? project : null;
|
|
7694
7588
|
}
|
|
7695
7589
|
function getPotentialProjectNames(project) {
|
|
7696
7590
|
const names = [project.name];
|
|
@@ -7702,7 +7596,7 @@ function getPotentialProjectNames(project) {
|
|
|
7702
7596
|
async function loadCustomReporterModule(path, runner) {
|
|
7703
7597
|
let customReporterModule;
|
|
7704
7598
|
try {
|
|
7705
|
-
customReporterModule = await runner.
|
|
7599
|
+
customReporterModule = await runner.import(path);
|
|
7706
7600
|
} catch (customReporterModuleError) {
|
|
7707
7601
|
throw new Error(`Failed to load custom Reporter from ${path}`, { cause: customReporterModuleError });
|
|
7708
7602
|
}
|
|
@@ -7710,12 +7604,11 @@ async function loadCustomReporterModule(path, runner) {
|
|
|
7710
7604
|
return customReporterModule.default;
|
|
7711
7605
|
}
|
|
7712
7606
|
function createReporters(reporterReferences, ctx) {
|
|
7713
|
-
const runner = ctx.runner
|
|
7714
|
-
const promisedReporters = reporterReferences.map(async (referenceOrInstance) => {
|
|
7607
|
+
const runner = ctx.runner, promisedReporters = reporterReferences.map(async (referenceOrInstance) => {
|
|
7715
7608
|
if (Array.isArray(referenceOrInstance)) {
|
|
7716
7609
|
const [reporterName, reporterOptions] = referenceOrInstance;
|
|
7717
7610
|
if (reporterName === "html") {
|
|
7718
|
-
await ctx.packageInstaller.ensureInstalled("@vitest/ui",
|
|
7611
|
+
await ctx.packageInstaller.ensureInstalled("@vitest/ui", ctx.config.root, ctx.version);
|
|
7719
7612
|
const CustomReporter = await loadCustomReporterModule("@vitest/ui/reporter", runner);
|
|
7720
7613
|
return new CustomReporter(reporterOptions);
|
|
7721
7614
|
} else if (reporterName in ReportersMap) {
|
|
@@ -7752,14 +7645,12 @@ function parseFilter(filter) {
|
|
|
7752
7645
|
filename: parsedFilename,
|
|
7753
7646
|
lineNumber: Number.parseInt(lineNumber)
|
|
7754
7647
|
};
|
|
7755
|
-
|
|
7756
|
-
|
|
7648
|
+
if (lineNumber.match(/^\d+-\d+$/)) throw new RangeLocationFilterProvidedError(filter);
|
|
7649
|
+
return { filename: filter };
|
|
7757
7650
|
}
|
|
7758
7651
|
function groupFilters(filters) {
|
|
7759
|
-
const groupedFilters_ = groupBy(filters, (f) => f.filename)
|
|
7760
|
-
|
|
7761
|
-
const [filename, filters] = entry;
|
|
7762
|
-
const testLocations = filters.map((f) => f.lineNumber);
|
|
7652
|
+
const groupedFilters_ = groupBy(filters, (f) => f.filename), groupedFilters = Object.fromEntries(Object.entries(groupedFilters_).map((entry) => {
|
|
7653
|
+
const [filename, filters] = entry, testLocations = filters.map((f) => f.lineNumber);
|
|
7763
7654
|
return [filename, testLocations.filter((l) => l !== void 0)];
|
|
7764
7655
|
}));
|
|
7765
7656
|
return groupedFilters;
|
|
@@ -7778,45 +7669,35 @@ class VitestSpecifications {
|
|
|
7778
7669
|
if (project._isCachedTestFile(moduleId)) specs.push(project.createSpecification(moduleId));
|
|
7779
7670
|
if (project._isCachedTypecheckFile(moduleId)) specs.push(project.createSpecification(moduleId, [], "typescript"));
|
|
7780
7671
|
}
|
|
7781
|
-
specs.forEach((spec) => this.ensureSpecificationCached(spec));
|
|
7782
|
-
return specs;
|
|
7672
|
+
return specs.forEach((spec) => this.ensureSpecificationCached(spec)), specs;
|
|
7783
7673
|
}
|
|
7784
7674
|
async getRelevantTestSpecifications(filters = []) {
|
|
7785
7675
|
return this.filterTestsBySource(await this.globTestSpecifications(filters));
|
|
7786
7676
|
}
|
|
7787
7677
|
async globTestSpecifications(filters = []) {
|
|
7788
|
-
const files = [];
|
|
7789
|
-
const dir = process.cwd();
|
|
7790
|
-
const parsedFilters = filters.map((f) => parseFilter(f));
|
|
7678
|
+
const files = [], dir = process.cwd(), parsedFilters = filters.map((f) => parseFilter(f));
|
|
7791
7679
|
// Require includeTaskLocation when a location filter is passed
|
|
7792
7680
|
if (!this.vitest.config.includeTaskLocation && parsedFilters.some((f) => f.lineNumber !== void 0)) throw new IncludeTaskLocationDisabledError();
|
|
7793
7681
|
const testLines = groupFilters(parsedFilters.map((f) => ({
|
|
7794
7682
|
...f,
|
|
7795
7683
|
filename: resolve(dir, f.filename)
|
|
7796
|
-
})));
|
|
7797
|
-
|
|
7798
|
-
const testLocHasMatch = {};
|
|
7799
|
-
await Promise.all(this.vitest.projects.map(async (project) => {
|
|
7684
|
+
}))), testLocHasMatch = {};
|
|
7685
|
+
return await Promise.all(this.vitest.projects.map(async (project) => {
|
|
7800
7686
|
const { testFiles, typecheckTestFiles } = await project.globTestFiles(parsedFilters.map((f) => f.filename));
|
|
7801
7687
|
testFiles.forEach((file) => {
|
|
7802
7688
|
const lines = testLines[file];
|
|
7803
7689
|
testLocHasMatch[file] = true;
|
|
7804
7690
|
const spec = project.createSpecification(file, lines);
|
|
7805
|
-
this.ensureSpecificationCached(spec);
|
|
7806
|
-
|
|
7807
|
-
});
|
|
7808
|
-
typecheckTestFiles.forEach((file) => {
|
|
7691
|
+
this.ensureSpecificationCached(spec), files.push(spec);
|
|
7692
|
+
}), typecheckTestFiles.forEach((file) => {
|
|
7809
7693
|
const lines = testLines[file];
|
|
7810
7694
|
testLocHasMatch[file] = true;
|
|
7811
7695
|
const spec = project.createSpecification(file, lines, "typescript");
|
|
7812
|
-
this.ensureSpecificationCached(spec);
|
|
7813
|
-
files.push(spec);
|
|
7696
|
+
this.ensureSpecificationCached(spec), files.push(spec);
|
|
7814
7697
|
});
|
|
7815
|
-
}))
|
|
7816
|
-
Object.entries(testLines).forEach(([filepath, loc]) => {
|
|
7698
|
+
})), Object.entries(testLines).forEach(([filepath, loc]) => {
|
|
7817
7699
|
if (loc.length !== 0 && !testLocHasMatch[filepath]) throw new LocationFilterFileNotFoundError(relative(dir, filepath));
|
|
7818
|
-
});
|
|
7819
|
-
return files;
|
|
7700
|
+
}), files;
|
|
7820
7701
|
}
|
|
7821
7702
|
clearCache(moduleId) {
|
|
7822
7703
|
if (moduleId) this._cachedSpecs.delete(moduleId);
|
|
@@ -7826,30 +7707,20 @@ class VitestSpecifications {
|
|
|
7826
7707
|
return this._cachedSpecs.get(moduleId);
|
|
7827
7708
|
}
|
|
7828
7709
|
ensureSpecificationCached(spec) {
|
|
7829
|
-
const file = spec.moduleId;
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
if (index === -1) {
|
|
7833
|
-
specs.push(spec);
|
|
7834
|
-
this._cachedSpecs.set(file, specs);
|
|
7835
|
-
} else specs.splice(index, 1, spec);
|
|
7710
|
+
const file = spec.moduleId, specs = this._cachedSpecs.get(file) || [], index = specs.findIndex((_s) => _s.project === spec.project && _s.pool === spec.pool);
|
|
7711
|
+
if (index === -1) specs.push(spec), this._cachedSpecs.set(file, specs);
|
|
7712
|
+
else specs.splice(index, 1, spec);
|
|
7836
7713
|
return specs;
|
|
7837
7714
|
}
|
|
7838
7715
|
async filterTestsBySource(specs) {
|
|
7839
7716
|
if (this.vitest.config.changed && !this.vitest.config.related) {
|
|
7840
|
-
const { VitestGit } = await import('./git.
|
|
7841
|
-
|
|
7842
|
-
const related = await vitestGit.findChangedFiles({ changedSince: this.vitest.config.changed });
|
|
7843
|
-
if (!related) {
|
|
7844
|
-
process.exitCode = 1;
|
|
7845
|
-
throw new GitNotFoundError();
|
|
7846
|
-
}
|
|
7717
|
+
const { VitestGit } = await import('./git.BFNcloKD.js'), vitestGit = new VitestGit(this.vitest.config.root), related = await vitestGit.findChangedFiles({ changedSince: this.vitest.config.changed });
|
|
7718
|
+
if (!related) throw process.exitCode = 1, new GitNotFoundError();
|
|
7847
7719
|
this.vitest.config.related = Array.from(new Set(related));
|
|
7848
7720
|
}
|
|
7849
7721
|
const related = this.vitest.config.related;
|
|
7850
7722
|
if (!related) return specs;
|
|
7851
|
-
const forceRerunTriggers = this.vitest.config.forceRerunTriggers;
|
|
7852
|
-
const matcher = forceRerunTriggers.length ? pm(forceRerunTriggers) : void 0;
|
|
7723
|
+
const forceRerunTriggers = this.vitest.config.forceRerunTriggers, matcher = forceRerunTriggers.length ? pm(forceRerunTriggers) : void 0;
|
|
7853
7724
|
if (matcher && related.some((file) => matcher(file))) return specs;
|
|
7854
7725
|
// don't run anything if no related sources are found
|
|
7855
7726
|
// if we are in watch mode, we want to process all tests
|
|
@@ -7857,8 +7728,7 @@ class VitestSpecifications {
|
|
|
7857
7728
|
const testGraphs = await Promise.all(specs.map(async (spec) => {
|
|
7858
7729
|
const deps = await this.getTestDependencies(spec);
|
|
7859
7730
|
return [spec, deps];
|
|
7860
|
-
}));
|
|
7861
|
-
const runningTests = [];
|
|
7731
|
+
})), runningTests = [];
|
|
7862
7732
|
for (const [specification, deps] of testGraphs)
|
|
7863
7733
|
// if deps or the test itself were changed
|
|
7864
7734
|
if (related.some((path) => path === specification.moduleId || deps.has(path))) runningTests.push(specification);
|
|
@@ -7868,8 +7738,7 @@ class VitestSpecifications {
|
|
|
7868
7738
|
const addImports = async (project, filepath) => {
|
|
7869
7739
|
if (deps.has(filepath)) return;
|
|
7870
7740
|
deps.add(filepath);
|
|
7871
|
-
const mod = project.vite.moduleGraph.getModuleById(filepath);
|
|
7872
|
-
const transformed = mod?.ssrTransformResult || await project.vitenode.transformRequest(filepath);
|
|
7741
|
+
const mod = project.vite.environments.ssr.moduleGraph.getModuleById(filepath), transformed = mod?.transformResult || await project.vite.environments.ssr.transformRequest(filepath);
|
|
7873
7742
|
if (!transformed) return;
|
|
7874
7743
|
const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
|
|
7875
7744
|
await Promise.all(dependencies.map(async (dep) => {
|
|
@@ -7877,9 +7746,7 @@ class VitestSpecifications {
|
|
|
7877
7746
|
if (!fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)) await addImports(project, fsPath);
|
|
7878
7747
|
}));
|
|
7879
7748
|
};
|
|
7880
|
-
await addImports(spec.project, spec.moduleId);
|
|
7881
|
-
deps.delete(spec.moduleId);
|
|
7882
|
-
return deps;
|
|
7749
|
+
return await addImports(spec.project, spec.moduleId), deps.delete(spec.moduleId), deps;
|
|
7883
7750
|
}
|
|
7884
7751
|
}
|
|
7885
7752
|
|
|
@@ -7905,10 +7772,7 @@ class ReportedTaskImplementation {
|
|
|
7905
7772
|
location;
|
|
7906
7773
|
/** @internal */
|
|
7907
7774
|
constructor(task, project) {
|
|
7908
|
-
this.task = task;
|
|
7909
|
-
this.project = project;
|
|
7910
|
-
this.id = task.id;
|
|
7911
|
-
this.location = task.location;
|
|
7775
|
+
this.task = task, this.project = project, this.id = task.id, this.location = task.location;
|
|
7912
7776
|
}
|
|
7913
7777
|
/**
|
|
7914
7778
|
* Checks if the test did not fail the suite.
|
|
@@ -7930,8 +7794,7 @@ class ReportedTaskImplementation {
|
|
|
7930
7794
|
*/
|
|
7931
7795
|
static register(task, project) {
|
|
7932
7796
|
const state = new this(task, project);
|
|
7933
|
-
storeTask(project, task, state);
|
|
7934
|
-
return state;
|
|
7797
|
+
return storeTask(project, task, state), state;
|
|
7935
7798
|
}
|
|
7936
7799
|
}
|
|
7937
7800
|
class TestCase extends ReportedTaskImplementation {
|
|
@@ -7955,9 +7818,7 @@ class TestCase extends ReportedTaskImplementation {
|
|
|
7955
7818
|
parent;
|
|
7956
7819
|
/** @internal */
|
|
7957
7820
|
constructor(task, project) {
|
|
7958
|
-
super(task, project);
|
|
7959
|
-
this.name = task.name;
|
|
7960
|
-
this.module = getReportedTask(project, task.file);
|
|
7821
|
+
super(task, project), this.name = task.name, this.module = getReportedTask(project, task.file);
|
|
7961
7822
|
const suite = this.task.suite;
|
|
7962
7823
|
if (suite) this.parent = getReportedTask(project, suite);
|
|
7963
7824
|
else this.parent = this.module;
|
|
@@ -7979,8 +7840,7 @@ class TestCase extends ReportedTaskImplementation {
|
|
|
7979
7840
|
* - **skipped**: Test was skipped during collection or dynamically with `ctx.skip()`.
|
|
7980
7841
|
*/
|
|
7981
7842
|
result() {
|
|
7982
|
-
const result = this.task.result;
|
|
7983
|
-
const mode = result?.state || this.task.mode;
|
|
7843
|
+
const result = this.task.result, mode = result?.state || this.task.mode;
|
|
7984
7844
|
if (!result && (mode === "skip" || mode === "todo")) return {
|
|
7985
7845
|
state: "skipped",
|
|
7986
7846
|
note: void 0,
|
|
@@ -7991,16 +7851,14 @@ class TestCase extends ReportedTaskImplementation {
|
|
|
7991
7851
|
errors: void 0
|
|
7992
7852
|
};
|
|
7993
7853
|
const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
|
|
7994
|
-
|
|
7854
|
+
return state === "skipped" ? {
|
|
7995
7855
|
state,
|
|
7996
7856
|
note: result.note,
|
|
7997
7857
|
errors: void 0
|
|
7998
|
-
}
|
|
7999
|
-
if (state === "passed") return {
|
|
7858
|
+
} : state === "passed" ? {
|
|
8000
7859
|
state,
|
|
8001
7860
|
errors: result.errors
|
|
8002
|
-
}
|
|
8003
|
-
return {
|
|
7861
|
+
} : {
|
|
8004
7862
|
state,
|
|
8005
7863
|
errors: result.errors || []
|
|
8006
7864
|
};
|
|
@@ -8019,8 +7877,7 @@ class TestCase extends ReportedTaskImplementation {
|
|
|
8019
7877
|
const result = this.task.result;
|
|
8020
7878
|
// startTime should always be available if the test has properly finished
|
|
8021
7879
|
if (!result || !result.startTime) return void 0;
|
|
8022
|
-
const duration = result.duration || 0;
|
|
8023
|
-
const slow = duration > this.project.globalConfig.slowTestThreshold;
|
|
7880
|
+
const duration = result.duration || 0, slow = duration > this.project.globalConfig.slowTestThreshold;
|
|
8024
7881
|
return {
|
|
8025
7882
|
slow,
|
|
8026
7883
|
heap: result.heap,
|
|
@@ -8036,8 +7893,7 @@ class TestCollection {
|
|
|
8036
7893
|
#task;
|
|
8037
7894
|
#project;
|
|
8038
7895
|
constructor(task, project) {
|
|
8039
|
-
this.#task = task;
|
|
8040
|
-
this.#project = project;
|
|
7896
|
+
this.#task = task, this.#project = project;
|
|
8041
7897
|
}
|
|
8042
7898
|
/**
|
|
8043
7899
|
* Returns the test or suite at a specific index.
|
|
@@ -8090,10 +7946,7 @@ class TestCollection {
|
|
|
8090
7946
|
* Filters all suites that are part of this collection and its children.
|
|
8091
7947
|
*/
|
|
8092
7948
|
*allSuites() {
|
|
8093
|
-
for (const child of this) if (child.type === "suite")
|
|
8094
|
-
yield child;
|
|
8095
|
-
yield* child.children.allSuites();
|
|
8096
|
-
}
|
|
7949
|
+
for (const child of this) if (child.type === "suite") yield child, yield* child.children.allSuites();
|
|
8097
7950
|
}
|
|
8098
7951
|
*[Symbol.iterator]() {
|
|
8099
7952
|
for (const task of this.#task.tasks) yield getReportedTask(this.#project, task);
|
|
@@ -8106,8 +7959,7 @@ class SuiteImplementation extends ReportedTaskImplementation {
|
|
|
8106
7959
|
children;
|
|
8107
7960
|
/** @internal */
|
|
8108
7961
|
constructor(task, project) {
|
|
8109
|
-
super(task, project);
|
|
8110
|
-
this.children = new TestCollection(task, project);
|
|
7962
|
+
super(task, project), this.children = new TestCollection(task, project);
|
|
8111
7963
|
}
|
|
8112
7964
|
/**
|
|
8113
7965
|
* Errors that happened outside of the test run during collection, like syntax errors.
|
|
@@ -8137,9 +7989,7 @@ class TestSuite extends SuiteImplementation {
|
|
|
8137
7989
|
options;
|
|
8138
7990
|
/** @internal */
|
|
8139
7991
|
constructor(task, project) {
|
|
8140
|
-
super(task, project);
|
|
8141
|
-
this.name = task.name;
|
|
8142
|
-
this.module = getReportedTask(project, task.file);
|
|
7992
|
+
super(task, project), this.name = task.name, this.module = getReportedTask(project, task.file);
|
|
8143
7993
|
const suite = this.task.suite;
|
|
8144
7994
|
if (suite) this.parent = getReportedTask(project, suite);
|
|
8145
7995
|
else this.parent = this.module;
|
|
@@ -8170,29 +8020,21 @@ class TestModule extends SuiteImplementation {
|
|
|
8170
8020
|
moduleId;
|
|
8171
8021
|
/** @internal */
|
|
8172
8022
|
constructor(task, project) {
|
|
8173
|
-
super(task, project);
|
|
8174
|
-
this.moduleId = task.filepath;
|
|
8023
|
+
super(task, project), this.moduleId = task.filepath;
|
|
8175
8024
|
}
|
|
8176
8025
|
/**
|
|
8177
8026
|
* Checks the running state of the test file.
|
|
8178
8027
|
*/
|
|
8179
8028
|
state() {
|
|
8180
8029
|
const state = this.task.result?.state;
|
|
8181
|
-
|
|
8182
|
-
return getSuiteState(this.task);
|
|
8030
|
+
return state === "queued" ? "queued" : getSuiteState(this.task);
|
|
8183
8031
|
}
|
|
8184
8032
|
/**
|
|
8185
8033
|
* Useful information about the module like duration, memory usage, etc.
|
|
8186
8034
|
* If the module was not executed yet, all diagnostic values will return `0`.
|
|
8187
8035
|
*/
|
|
8188
8036
|
diagnostic() {
|
|
8189
|
-
const setupDuration = this.task.setupDuration || 0;
|
|
8190
|
-
const collectDuration = this.task.collectDuration || 0;
|
|
8191
|
-
const prepareDuration = this.task.prepareDuration || 0;
|
|
8192
|
-
const environmentSetupDuration = this.task.environmentLoad || 0;
|
|
8193
|
-
const duration = this.task.result?.duration || 0;
|
|
8194
|
-
const heap = this.task.result?.heap;
|
|
8195
|
-
const importDurations = this.task.importDurations ?? {};
|
|
8037
|
+
const setupDuration = this.task.setupDuration || 0, collectDuration = this.task.collectDuration || 0, prepareDuration = this.task.prepareDuration || 0, environmentSetupDuration = this.task.environmentLoad || 0, duration = this.task.result?.duration || 0, heap = this.task.result?.heap, importDurations = this.task.importDurations ?? {};
|
|
8196
8038
|
return {
|
|
8197
8039
|
environmentSetupDuration,
|
|
8198
8040
|
prepareDuration,
|
|
@@ -8224,8 +8066,7 @@ function getReportedTask(project, runnerTask) {
|
|
|
8224
8066
|
return reportedTask;
|
|
8225
8067
|
}
|
|
8226
8068
|
function getSuiteState(task) {
|
|
8227
|
-
const mode = task.mode;
|
|
8228
|
-
const state = task.result?.state;
|
|
8069
|
+
const mode = task.mode, state = task.result?.state;
|
|
8229
8070
|
if (mode === "skip" || mode === "todo" || state === "skip" || state === "todo") return "skipped";
|
|
8230
8071
|
if (state == null || state === "run" || state === "only") return "pending";
|
|
8231
8072
|
if (state === "fail") return "failed";
|
|
@@ -8234,8 +8075,7 @@ function getSuiteState(task) {
|
|
|
8234
8075
|
}
|
|
8235
8076
|
|
|
8236
8077
|
function isAggregateError(err) {
|
|
8237
|
-
|
|
8238
|
-
return err instanceof Error && "errors" in err;
|
|
8078
|
+
return typeof AggregateError !== "undefined" && err instanceof AggregateError ? true : err instanceof Error && "errors" in err;
|
|
8239
8079
|
}
|
|
8240
8080
|
class StateManager {
|
|
8241
8081
|
filesMap = /* @__PURE__ */ new Map();
|
|
@@ -8246,6 +8086,7 @@ class StateManager {
|
|
|
8246
8086
|
processTimeoutCauses = /* @__PURE__ */ new Set();
|
|
8247
8087
|
reportedTasksMap = /* @__PURE__ */ new WeakMap();
|
|
8248
8088
|
blobs;
|
|
8089
|
+
transformTime = 0;
|
|
8249
8090
|
onUnhandledError;
|
|
8250
8091
|
/** @internal */
|
|
8251
8092
|
_data = {
|
|
@@ -8265,12 +8106,7 @@ class StateManager {
|
|
|
8265
8106
|
const _error = error;
|
|
8266
8107
|
if (_error && typeof _error === "object" && _error.code === "VITEST_PENDING") {
|
|
8267
8108
|
const task = this.idMap.get(_error.taskId);
|
|
8268
|
-
if (task) {
|
|
8269
|
-
task.mode = "skip";
|
|
8270
|
-
task.result ??= { state: "skip" };
|
|
8271
|
-
task.result.state = "skip";
|
|
8272
|
-
task.result.note = _error.note;
|
|
8273
|
-
}
|
|
8109
|
+
if (task) task.mode = "skip", task.result ??= { state: "skip" }, task.result.state = "skip", task.result.note = _error.note;
|
|
8274
8110
|
return;
|
|
8275
8111
|
}
|
|
8276
8112
|
if (!this.onUnhandledError || this.onUnhandledError(error) !== false) this.errorsSet.add(error);
|
|
@@ -8294,12 +8130,8 @@ class StateManager {
|
|
|
8294
8130
|
* Return files that were running or collected.
|
|
8295
8131
|
*/
|
|
8296
8132
|
getFiles(keys) {
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
// print typecheck files first
|
|
8300
|
-
if (f1.meta?.typecheck && f2.meta?.typecheck) return 0;
|
|
8301
|
-
if (f1.meta?.typecheck) return -1;
|
|
8302
|
-
return 1;
|
|
8133
|
+
return keys ? keys.map((key) => this.filesMap.get(key)).flat().filter((file) => file && !file.local) : Array.from(this.filesMap.values()).flat().filter((file) => !file.local).sort((f1, f2) => {
|
|
8134
|
+
return f1.meta?.typecheck && f2.meta?.typecheck ? 0 : f1.meta?.typecheck ? -1 : 1;
|
|
8303
8135
|
});
|
|
8304
8136
|
}
|
|
8305
8137
|
getTestModules(keys) {
|
|
@@ -8318,25 +8150,17 @@ class StateManager {
|
|
|
8318
8150
|
}
|
|
8319
8151
|
collectFiles(project, files = []) {
|
|
8320
8152
|
files.forEach((file) => {
|
|
8321
|
-
const existing = this.filesMap.get(file.filepath) || [];
|
|
8322
|
-
const otherFiles = existing.filter((i) => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck);
|
|
8323
|
-
const currentFile = existing.find((i) => i.projectName === file.projectName);
|
|
8153
|
+
const existing = this.filesMap.get(file.filepath) || [], otherFiles = existing.filter((i) => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck), currentFile = existing.find((i) => i.projectName === file.projectName);
|
|
8324
8154
|
// keep logs for the previous file because it should always be initiated before the collections phase
|
|
8325
8155
|
// which means that all logs are collected during the collection and not inside tests
|
|
8326
8156
|
if (currentFile) file.logs = currentFile.logs;
|
|
8327
|
-
otherFiles.push(file);
|
|
8328
|
-
this.filesMap.set(file.filepath, otherFiles);
|
|
8329
|
-
this.updateId(file, project);
|
|
8157
|
+
otherFiles.push(file), this.filesMap.set(file.filepath, otherFiles), this.updateId(file, project);
|
|
8330
8158
|
});
|
|
8331
8159
|
}
|
|
8332
8160
|
clearFiles(project, paths = []) {
|
|
8333
8161
|
paths.forEach((path) => {
|
|
8334
|
-
const files = this.filesMap.get(path);
|
|
8335
|
-
|
|
8336
|
-
fileTask.local = true;
|
|
8337
|
-
TestModule.register(fileTask, project);
|
|
8338
|
-
this.idMap.set(fileTask.id, fileTask);
|
|
8339
|
-
if (!files) {
|
|
8162
|
+
const files = this.filesMap.get(path), fileTask = createFileTask(path, project.config.root, project.config.name);
|
|
8163
|
+
if (fileTask.local = true, TestModule.register(fileTask, project), this.idMap.set(fileTask.id, fileTask), !files) {
|
|
8340
8164
|
this.filesMap.set(path, [fileTask]);
|
|
8341
8165
|
return;
|
|
8342
8166
|
}
|
|
@@ -8347,14 +8171,14 @@ class StateManager {
|
|
|
8347
8171
|
});
|
|
8348
8172
|
}
|
|
8349
8173
|
updateId(task, project) {
|
|
8350
|
-
if (this.idMap.get(task.id)
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
}
|
|
8174
|
+
if (this.idMap.get(task.id) !== task) {
|
|
8175
|
+
if (task.type === "suite" && "filepath" in task) TestModule.register(task, project);
|
|
8176
|
+
else if (task.type === "suite") TestSuite.register(task, project);
|
|
8177
|
+
else TestCase.register(task, project);
|
|
8178
|
+
if (this.idMap.set(task.id, task), task.type === "suite") task.tasks.forEach((task) => {
|
|
8179
|
+
this.updateId(task, project);
|
|
8180
|
+
});
|
|
8181
|
+
}
|
|
8358
8182
|
}
|
|
8359
8183
|
getReportedEntity(task) {
|
|
8360
8184
|
return this.reportedTasksMap.get(task);
|
|
@@ -8363,10 +8187,8 @@ class StateManager {
|
|
|
8363
8187
|
for (const [id, result, meta] of packs) {
|
|
8364
8188
|
const task = this.idMap.get(id);
|
|
8365
8189
|
if (task) {
|
|
8366
|
-
task.result = result;
|
|
8367
|
-
task.meta = meta;
|
|
8368
8190
|
// skipped with new PendingError
|
|
8369
|
-
if (result?.state === "skip") task.mode = "skip";
|
|
8191
|
+
if (task.result = result, task.meta = meta, result?.state === "skip") task.mode = "skip";
|
|
8370
8192
|
}
|
|
8371
8193
|
}
|
|
8372
8194
|
}
|
|
@@ -8843,10 +8665,7 @@ class TestRun {
|
|
|
8843
8665
|
}
|
|
8844
8666
|
async start(specifications) {
|
|
8845
8667
|
const filepaths = specifications.map((spec) => spec.moduleId);
|
|
8846
|
-
this.vitest.state.collectPaths(filepaths);
|
|
8847
|
-
await this.vitest.report("onPathsCollected", Array.from(new Set(filepaths)));
|
|
8848
|
-
await this.vitest.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
|
|
8849
|
-
await this.vitest.report("onTestRunStart", [...specifications]);
|
|
8668
|
+
this.vitest.state.collectPaths(filepaths), await this.vitest.report("onTestRunStart", [...specifications]);
|
|
8850
8669
|
}
|
|
8851
8670
|
async enqueued(project, file) {
|
|
8852
8671
|
this.vitest.state.collectFiles(project, [file]);
|
|
@@ -8854,25 +8673,17 @@ class TestRun {
|
|
|
8854
8673
|
await this.vitest.report("onTestModuleQueued", testModule);
|
|
8855
8674
|
}
|
|
8856
8675
|
async collected(project, files) {
|
|
8857
|
-
this.vitest.state.collectFiles(project, files)
|
|
8858
|
-
await Promise.all([this.vitest.report("onCollected", files), ...files.map((file) => {
|
|
8676
|
+
this.vitest.state.collectFiles(project, files), await Promise.all(files.map((file) => {
|
|
8859
8677
|
const testModule = this.vitest.state.getReportedEntity(file);
|
|
8860
8678
|
return this.vitest.report("onTestModuleCollected", testModule);
|
|
8861
|
-
})
|
|
8679
|
+
}));
|
|
8862
8680
|
}
|
|
8863
8681
|
async log(log) {
|
|
8864
|
-
this.vitest.state.updateUserLog(log);
|
|
8865
|
-
await this.vitest.report("onUserConsoleLog", log);
|
|
8682
|
+
this.vitest.state.updateUserLog(log), await this.vitest.report("onUserConsoleLog", log);
|
|
8866
8683
|
}
|
|
8867
8684
|
async annotate(testId, annotation) {
|
|
8868
|
-
const task = this.vitest.state.idMap.get(testId);
|
|
8869
|
-
|
|
8870
|
-
assert$1(task && entity, `Entity must be found for task ${task?.name || testId}`);
|
|
8871
|
-
assert$1(entity.type === "test", `Annotation can only be added to a test, instead got ${entity.type}`);
|
|
8872
|
-
await this.resolveTestAttachment(entity, annotation);
|
|
8873
|
-
entity.task.annotations.push(annotation);
|
|
8874
|
-
await this.vitest.report("onTestCaseAnnotate", entity, annotation);
|
|
8875
|
-
return annotation;
|
|
8685
|
+
const task = this.vitest.state.idMap.get(testId), entity = task && this.vitest.state.getReportedEntity(task);
|
|
8686
|
+
return assert$1(task && entity, `Entity must be found for task ${task?.name || testId}`), assert$1(entity.type === "test", `Annotation can only be added to a test, instead got ${entity.type}`), await this.resolveTestAttachment(entity, annotation), entity.task.annotations.push(annotation), await this.vitest.report("onTestCaseAnnotate", entity, annotation), annotation;
|
|
8876
8687
|
}
|
|
8877
8688
|
async updated(update, events) {
|
|
8878
8689
|
this.vitest.state.updateTasks(update);
|
|
@@ -8885,30 +8696,21 @@ class TestRun {
|
|
|
8885
8696
|
await this.vitest.report("onTaskUpdate", update, events);
|
|
8886
8697
|
}
|
|
8887
8698
|
async end(specifications, errors, coverage) {
|
|
8699
|
+
if (coverage) await this.vitest.report("onCoverage", coverage);
|
|
8888
8700
|
// specification won't have the File task if they were filtered by the --shard command
|
|
8889
|
-
const modules = specifications.map((spec) => spec.testModule).filter((s) => s != null);
|
|
8890
|
-
const files = modules.map((m) => m.task);
|
|
8891
|
-
const state = this.vitest.isCancelling ? "interrupted" : this.hasFailed(modules) ? "failed" : "passed";
|
|
8701
|
+
const modules = specifications.map((spec) => spec.testModule).filter((s) => s != null), state = this.vitest.isCancelling ? "interrupted" : this.hasFailed(modules) ? "failed" : "passed";
|
|
8892
8702
|
if (state !== "passed") process.exitCode = 1;
|
|
8893
|
-
|
|
8894
|
-
await Promise.all([this.vitest.report("onTestRunEnd", modules, [...errors], state), this.vitest.report("onFinished", files, errors, coverage)]);
|
|
8895
|
-
} finally {
|
|
8896
|
-
if (coverage) await this.vitest.report("onCoverage", coverage);
|
|
8897
|
-
}
|
|
8703
|
+
this.vitest.report("onTestRunEnd", modules, [...errors], state);
|
|
8898
8704
|
}
|
|
8899
8705
|
hasFailed(modules) {
|
|
8900
|
-
|
|
8901
|
-
return modules.some((m) => !m.ok());
|
|
8706
|
+
return modules.length ? modules.some((m) => !m.ok()) : !this.vitest.config.passWithNoTests;
|
|
8902
8707
|
}
|
|
8903
8708
|
async reportEvent(id, event, data) {
|
|
8904
|
-
const task = this.vitest.state.idMap.get(id);
|
|
8905
|
-
|
|
8906
|
-
assert$1(task && entity, `Entity must be found for task ${task?.name || id}`);
|
|
8907
|
-
if (event === "suite-prepare" && entity.type === "suite") return await this.vitest.report("onTestSuiteReady", entity);
|
|
8709
|
+
const task = this.vitest.state.idMap.get(id), entity = task && this.vitest.state.getReportedEntity(task);
|
|
8710
|
+
if (assert$1(task && entity, `Entity must be found for task ${task?.name || id}`), event === "suite-prepare" && entity.type === "suite") return await this.vitest.report("onTestSuiteReady", entity);
|
|
8908
8711
|
if (event === "suite-prepare" && entity.type === "module") return await this.vitest.report("onTestModuleStart", entity);
|
|
8909
8712
|
if (event === "suite-finished") {
|
|
8910
|
-
assert$1(entity.type === "suite" || entity.type === "module", "Entity type must be suite or module")
|
|
8911
|
-
if (entity.state() === "skipped")
|
|
8713
|
+
if (assert$1(entity.type === "suite" || entity.type === "module", "Entity type must be suite or module"), entity.state() === "skipped")
|
|
8912
8714
|
// everything inside suite or a module is skipped,
|
|
8913
8715
|
// so we won't get any children events
|
|
8914
8716
|
// we need to report everything manually
|
|
@@ -8920,8 +8722,7 @@ class TestRun {
|
|
|
8920
8722
|
if (event === "test-prepare" && entity.type === "test") return await this.vitest.report("onTestCaseReady", entity);
|
|
8921
8723
|
if (event === "test-finished" && entity.type === "test") return await this.vitest.report("onTestCaseResult", entity);
|
|
8922
8724
|
if (event.startsWith("before-hook") || event.startsWith("after-hook")) {
|
|
8923
|
-
const isBefore = event.startsWith("before-hook")
|
|
8924
|
-
const hook = entity.type === "test" ? {
|
|
8725
|
+
const isBefore = event.startsWith("before-hook"), hook = entity.type === "test" ? {
|
|
8925
8726
|
name: isBefore ? "beforeEach" : "afterEach",
|
|
8926
8727
|
entity
|
|
8927
8728
|
} : {
|
|
@@ -8933,37 +8734,25 @@ class TestRun {
|
|
|
8933
8734
|
// this can only happen in --merge-reports, and annotation is already resolved
|
|
8934
8735
|
if (event === "test-annotation") {
|
|
8935
8736
|
const annotation = data?.annotation;
|
|
8936
|
-
assert$1(annotation && entity.type === "test");
|
|
8937
|
-
await this.vitest.report("onTestCaseAnnotate", entity, annotation);
|
|
8737
|
+
assert$1(annotation && entity.type === "test"), await this.vitest.report("onTestCaseAnnotate", entity, annotation);
|
|
8938
8738
|
}
|
|
8939
8739
|
}
|
|
8940
8740
|
}
|
|
8941
8741
|
async resolveTestAttachment(test, annotation) {
|
|
8942
|
-
const project = test.project;
|
|
8943
|
-
const attachment = annotation.attachment;
|
|
8742
|
+
const project = test.project, attachment = annotation.attachment;
|
|
8944
8743
|
if (!attachment) return attachment;
|
|
8945
8744
|
const path = attachment.path;
|
|
8946
8745
|
if (path && !path.startsWith("http://") && !path.startsWith("https://")) {
|
|
8947
|
-
const currentPath = resolve(project.config.root, path);
|
|
8948
|
-
|
|
8949
|
-
const newPath = resolve(project.config.attachmentsDir, `${sanitizeFilePath(annotation.message)}-${hash}${extname(currentPath)}`);
|
|
8950
|
-
await mkdir(dirname(newPath), { recursive: true });
|
|
8951
|
-
await copyFile(currentPath, newPath);
|
|
8952
|
-
attachment.path = newPath;
|
|
8746
|
+
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)}`);
|
|
8747
|
+
await mkdir(dirname(newPath), { recursive: true }), await copyFile(currentPath, newPath), attachment.path = newPath;
|
|
8953
8748
|
const contentType = attachment.contentType ?? mime.getType(basename(currentPath));
|
|
8954
8749
|
attachment.contentType = contentType || void 0;
|
|
8955
8750
|
}
|
|
8956
8751
|
return attachment;
|
|
8957
8752
|
}
|
|
8958
8753
|
async reportChildren(children) {
|
|
8959
|
-
for (const child of children) if (child.type === "test")
|
|
8960
|
-
|
|
8961
|
-
await this.vitest.report("onTestCaseResult", child);
|
|
8962
|
-
} else {
|
|
8963
|
-
await this.vitest.report("onTestSuiteReady", child);
|
|
8964
|
-
await this.reportChildren(child.children);
|
|
8965
|
-
await this.vitest.report("onTestSuiteResult", child);
|
|
8966
|
-
}
|
|
8754
|
+
for (const child of children) if (child.type === "test") await this.vitest.report("onTestCaseReady", child), await this.vitest.report("onTestCaseResult", child);
|
|
8755
|
+
else await this.vitest.report("onTestSuiteReady", child), await this.reportChildren(child.children), await this.vitest.report("onTestSuiteResult", child);
|
|
8967
8756
|
}
|
|
8968
8757
|
}
|
|
8969
8758
|
function sanitizeFilePath(s) {
|
|
@@ -8991,23 +8780,15 @@ class VitestWatcher {
|
|
|
8991
8780
|
* @internal
|
|
8992
8781
|
*/
|
|
8993
8782
|
onWatcherRerun(cb) {
|
|
8994
|
-
this._onRerun.push(cb);
|
|
8995
|
-
return this;
|
|
8783
|
+
return this._onRerun.push(cb), this;
|
|
8996
8784
|
}
|
|
8997
8785
|
unregisterWatcher = noop;
|
|
8998
8786
|
registerWatcher() {
|
|
8999
8787
|
const watcher = this.vitest.vite.watcher;
|
|
9000
8788
|
if (this.vitest.config.forceRerunTriggers.length) watcher.add(this.vitest.config.forceRerunTriggers);
|
|
9001
|
-
watcher.on("change", this.onChange)
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
this.unregisterWatcher = () => {
|
|
9005
|
-
watcher.off("change", this.onChange);
|
|
9006
|
-
watcher.off("unlink", this.onUnlink);
|
|
9007
|
-
watcher.off("add", this.onAdd);
|
|
9008
|
-
this.unregisterWatcher = noop;
|
|
9009
|
-
};
|
|
9010
|
-
return this;
|
|
8789
|
+
return watcher.on("change", this.onChange), watcher.on("unlink", this.onUnlink), watcher.on("add", this.onAdd), this.unregisterWatcher = () => {
|
|
8790
|
+
watcher.off("change", this.onChange), watcher.off("unlink", this.onUnlink), watcher.off("add", this.onAdd), this.unregisterWatcher = noop;
|
|
8791
|
+
}, this;
|
|
9011
8792
|
}
|
|
9012
8793
|
scheduleRerun(file) {
|
|
9013
8794
|
this._onRerun.forEach((cb) => cb(file));
|
|
@@ -9015,25 +8796,17 @@ class VitestWatcher {
|
|
|
9015
8796
|
getTestFilesFromWatcherTrigger(id) {
|
|
9016
8797
|
if (!this.vitest.config.watchTriggerPatterns) return false;
|
|
9017
8798
|
let triggered = false;
|
|
9018
|
-
this.vitest.config.watchTriggerPatterns.forEach((definition) => {
|
|
8799
|
+
return this.vitest.config.watchTriggerPatterns.forEach((definition) => {
|
|
9019
8800
|
const exec = definition.pattern.exec(id);
|
|
9020
8801
|
if (exec) {
|
|
9021
8802
|
const files = definition.testsToRun(id, exec);
|
|
9022
|
-
if (Array.isArray(files))
|
|
9023
|
-
|
|
9024
|
-
files.forEach((file) => this.changedTests.add(resolve(this.vitest.config.root, file)));
|
|
9025
|
-
} else if (typeof files === "string") {
|
|
9026
|
-
triggered = true;
|
|
9027
|
-
this.changedTests.add(resolve(this.vitest.config.root, files));
|
|
9028
|
-
}
|
|
8803
|
+
if (Array.isArray(files)) triggered = true, files.forEach((file) => this.changedTests.add(resolve(this.vitest.config.root, file)));
|
|
8804
|
+
else if (typeof files === "string") triggered = true, this.changedTests.add(resolve(this.vitest.config.root, files));
|
|
9029
8805
|
}
|
|
9030
|
-
});
|
|
9031
|
-
return triggered;
|
|
8806
|
+
}), triggered;
|
|
9032
8807
|
}
|
|
9033
8808
|
onChange = (id) => {
|
|
9034
|
-
id = slash(id);
|
|
9035
|
-
this.vitest.logger.clearHighlightCache(id);
|
|
9036
|
-
this.vitest.invalidateFile(id);
|
|
8809
|
+
id = slash(id), this.vitest.logger.clearHighlightCache(id), this.vitest.invalidateFile(id);
|
|
9037
8810
|
const testFiles = this.getTestFilesFromWatcherTrigger(id);
|
|
9038
8811
|
if (testFiles) this.scheduleRerun(id);
|
|
9039
8812
|
else {
|
|
@@ -9042,21 +8815,10 @@ class VitestWatcher {
|
|
|
9042
8815
|
}
|
|
9043
8816
|
};
|
|
9044
8817
|
onUnlink = (id) => {
|
|
9045
|
-
id = slash(id);
|
|
9046
|
-
this.vitest.logger.clearHighlightCache(id);
|
|
9047
|
-
this.invalidates.add(id);
|
|
9048
|
-
if (this.vitest.state.filesMap.has(id)) {
|
|
9049
|
-
this.vitest.projects.forEach((project) => project._removeCachedTestFile(id));
|
|
9050
|
-
this.vitest.state.filesMap.delete(id);
|
|
9051
|
-
this.vitest.cache.results.removeFromCache(id);
|
|
9052
|
-
this.vitest.cache.stats.removeStats(id);
|
|
9053
|
-
this.changedTests.delete(id);
|
|
9054
|
-
this.vitest.report("onTestRemoved", id);
|
|
9055
|
-
}
|
|
8818
|
+
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);
|
|
9056
8819
|
};
|
|
9057
8820
|
onAdd = (id) => {
|
|
9058
|
-
id = slash(id);
|
|
9059
|
-
this.vitest.invalidateFile(id);
|
|
8821
|
+
id = slash(id), this.vitest.invalidateFile(id);
|
|
9060
8822
|
const testFiles = this.getTestFilesFromWatcherTrigger(id);
|
|
9061
8823
|
if (testFiles) {
|
|
9062
8824
|
this.scheduleRerun(id);
|
|
@@ -9064,13 +8826,10 @@ class VitestWatcher {
|
|
|
9064
8826
|
}
|
|
9065
8827
|
let fileContent;
|
|
9066
8828
|
const matchingProjects = [];
|
|
9067
|
-
this.vitest.projects.forEach((project) => {
|
|
8829
|
+
if (this.vitest.projects.forEach((project) => {
|
|
9068
8830
|
if (project.matchesTestGlob(id, () => fileContent ??= readFileSync(id, "utf-8"))) matchingProjects.push(project);
|
|
9069
|
-
});
|
|
9070
|
-
|
|
9071
|
-
this.changedTests.add(id);
|
|
9072
|
-
this.scheduleRerun(id);
|
|
9073
|
-
} else {
|
|
8831
|
+
}), matchingProjects.length > 0) this.changedTests.add(id), this.scheduleRerun(id);
|
|
8832
|
+
else {
|
|
9074
8833
|
// it's possible that file was already there but watcher triggered "add" event instead
|
|
9075
8834
|
const needsRerun = this.handleFileChanged(id);
|
|
9076
8835
|
if (needsRerun) this.scheduleRerun(id);
|
|
@@ -9078,51 +8837,33 @@ class VitestWatcher {
|
|
|
9078
8837
|
};
|
|
9079
8838
|
handleSetupFile(filepath) {
|
|
9080
8839
|
let isSetupFile = false;
|
|
9081
|
-
this.vitest.projects.forEach((project) => {
|
|
9082
|
-
|
|
9083
|
-
this.vitest.state.filesMap.forEach((files) => {
|
|
8840
|
+
return this.vitest.projects.forEach((project) => {
|
|
8841
|
+
project.config.setupFiles.includes(filepath) && this.vitest.state.filesMap.forEach((files) => {
|
|
9084
8842
|
files.forEach((file) => {
|
|
9085
|
-
if (file.projectName === project.name)
|
|
9086
|
-
isSetupFile = true;
|
|
9087
|
-
this.changedTests.add(file.filepath);
|
|
9088
|
-
}
|
|
8843
|
+
if (file.projectName === project.name) isSetupFile = true, this.changedTests.add(file.filepath);
|
|
9089
8844
|
});
|
|
9090
8845
|
});
|
|
9091
|
-
});
|
|
9092
|
-
return isSetupFile;
|
|
8846
|
+
}), isSetupFile;
|
|
9093
8847
|
}
|
|
9094
8848
|
/**
|
|
9095
8849
|
* @returns A value indicating whether rerun is needed (changedTests was mutated)
|
|
9096
8850
|
*/
|
|
9097
8851
|
handleFileChanged(filepath) {
|
|
9098
8852
|
if (this.changedTests.has(filepath) || this.invalidates.has(filepath)) return false;
|
|
9099
|
-
if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers))
|
|
9100
|
-
this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file));
|
|
9101
|
-
return true;
|
|
9102
|
-
}
|
|
8853
|
+
if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) return this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file)), true;
|
|
9103
8854
|
if (this.handleSetupFile(filepath)) return true;
|
|
9104
8855
|
const projects = this.vitest.projects.filter((project) => {
|
|
9105
8856
|
const moduleGraph = project.browser?.vite.moduleGraph || project.vite.moduleGraph;
|
|
9106
8857
|
return moduleGraph.getModulesByFile(filepath)?.size;
|
|
9107
8858
|
});
|
|
9108
|
-
if (!projects.length)
|
|
9109
|
-
// if there are no modules it's possible that server was restarted
|
|
9110
|
-
// we don't have information about importers anymore, so let's check if the file is a test file at least
|
|
9111
|
-
if (this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath))) {
|
|
9112
|
-
this.changedTests.add(filepath);
|
|
9113
|
-
return true;
|
|
9114
|
-
}
|
|
9115
|
-
return false;
|
|
9116
|
-
}
|
|
8859
|
+
if (!projects.length) return this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath)) ? (this.changedTests.add(filepath), true) : false;
|
|
9117
8860
|
const files = [];
|
|
9118
8861
|
for (const project of projects) {
|
|
9119
8862
|
const mods = project.browser?.vite.moduleGraph.getModulesByFile(filepath) || project.vite.moduleGraph.getModulesByFile(filepath);
|
|
9120
8863
|
if (!mods || !mods.size) continue;
|
|
9121
|
-
this.invalidates.add(filepath);
|
|
9122
8864
|
// one of test files that we already run, or one of test files that we can run
|
|
9123
|
-
if (this.vitest.state.filesMap.has(filepath) || project._isCachedTestFile(filepath)) {
|
|
9124
|
-
this.changedTests.add(filepath);
|
|
9125
|
-
files.push(filepath);
|
|
8865
|
+
if (this.invalidates.add(filepath), this.vitest.state.filesMap.has(filepath) || project._isCachedTestFile(filepath)) {
|
|
8866
|
+
this.changedTests.add(filepath), files.push(filepath);
|
|
9126
8867
|
continue;
|
|
9127
8868
|
}
|
|
9128
8869
|
let rerun = false;
|
|
@@ -9179,9 +8920,9 @@ class Vitest {
|
|
|
9179
8920
|
/** @internal */ _browserSessions = new BrowserSessions();
|
|
9180
8921
|
/** @internal */ _cliOptions = {};
|
|
9181
8922
|
/** @internal */ reporters = [];
|
|
9182
|
-
/** @internal */
|
|
9183
|
-
/** @internal */ runner = void 0;
|
|
8923
|
+
/** @internal */ runner;
|
|
9184
8924
|
/** @internal */ _testRun = void 0;
|
|
8925
|
+
/** @internal */ _resolver;
|
|
9185
8926
|
isFirstRun = true;
|
|
9186
8927
|
restartsCount = 0;
|
|
9187
8928
|
specifications;
|
|
@@ -9193,12 +8934,7 @@ class Vitest {
|
|
|
9193
8934
|
_cache;
|
|
9194
8935
|
_snapshot;
|
|
9195
8936
|
constructor(mode, cliOptions, options = {}) {
|
|
9196
|
-
this.mode = mode;
|
|
9197
|
-
this._cliOptions = cliOptions;
|
|
9198
|
-
this.logger = new Logger(this, options.stdout, options.stderr);
|
|
9199
|
-
this.packageInstaller = options.packageInstaller || new VitestPackageInstaller();
|
|
9200
|
-
this.specifications = new VitestSpecifications(this);
|
|
9201
|
-
this.watcher = new VitestWatcher(this).onWatcherRerun((file) => this.scheduleRerun([file]));
|
|
8937
|
+
this.mode = mode, this._cliOptions = cliOptions, this.logger = new Logger(this, options.stdout, options.stderr), this.packageInstaller = options.packageInstaller || new VitestPackageInstaller(), this.specifications = new VitestSpecifications(this), this.watcher = new VitestWatcher(this).onWatcherRerun((file) => this.scheduleRerun([file]));
|
|
9202
8938
|
}
|
|
9203
8939
|
_onRestartListeners = [];
|
|
9204
8940
|
_onClose = [];
|
|
@@ -9218,8 +8954,7 @@ class Vitest {
|
|
|
9218
8954
|
* The global config.
|
|
9219
8955
|
*/
|
|
9220
8956
|
get config() {
|
|
9221
|
-
assert(this._config, "config");
|
|
9222
|
-
return this._config;
|
|
8957
|
+
return assert(this._config, "config"), this._config;
|
|
9223
8958
|
}
|
|
9224
8959
|
/** @deprecated use `vitest.vite` instead */
|
|
9225
8960
|
get server() {
|
|
@@ -9229,30 +8964,26 @@ class Vitest {
|
|
|
9229
8964
|
* Global Vite's dev server instance.
|
|
9230
8965
|
*/
|
|
9231
8966
|
get vite() {
|
|
9232
|
-
assert(this._vite, "vite", "server");
|
|
9233
|
-
return this._vite;
|
|
8967
|
+
return assert(this._vite, "vite", "server"), this._vite;
|
|
9234
8968
|
}
|
|
9235
8969
|
/**
|
|
9236
8970
|
* The global test state manager.
|
|
9237
8971
|
* @experimental The State API is experimental and not subject to semver.
|
|
9238
8972
|
*/
|
|
9239
8973
|
get state() {
|
|
9240
|
-
assert(this._state, "state");
|
|
9241
|
-
return this._state;
|
|
8974
|
+
return assert(this._state, "state"), this._state;
|
|
9242
8975
|
}
|
|
9243
8976
|
/**
|
|
9244
8977
|
* The global snapshot manager. You can access the current state on `snapshot.summary`.
|
|
9245
8978
|
*/
|
|
9246
8979
|
get snapshot() {
|
|
9247
|
-
assert(this._snapshot, "snapshot", "snapshot manager");
|
|
9248
|
-
return this._snapshot;
|
|
8980
|
+
return assert(this._snapshot, "snapshot", "snapshot manager"), this._snapshot;
|
|
9249
8981
|
}
|
|
9250
8982
|
/**
|
|
9251
8983
|
* Test results and test file stats cache. Primarily used by the sequencer to sort tests.
|
|
9252
8984
|
*/
|
|
9253
8985
|
get cache() {
|
|
9254
|
-
assert(this._cache, "cache");
|
|
9255
|
-
return this._cache;
|
|
8986
|
+
return assert(this._cache, "cache"), this._cache;
|
|
9256
8987
|
}
|
|
9257
8988
|
/** @deprecated internal */
|
|
9258
8989
|
setServer(options, server) {
|
|
@@ -9260,57 +8991,21 @@ class Vitest {
|
|
|
9260
8991
|
}
|
|
9261
8992
|
/** @internal */
|
|
9262
8993
|
async _setServer(options, server) {
|
|
9263
|
-
this.watcher.unregisterWatcher();
|
|
9264
|
-
clearTimeout(this._rerunTimer);
|
|
9265
|
-
this.restartsCount += 1;
|
|
9266
|
-
this.pool?.close?.();
|
|
9267
|
-
this.pool = void 0;
|
|
9268
|
-
this.closingPromise = void 0;
|
|
9269
|
-
this.projects = [];
|
|
9270
|
-
this.coverageProvider = void 0;
|
|
9271
|
-
this.runningPromise = void 0;
|
|
9272
|
-
this.coreWorkspaceProject = void 0;
|
|
9273
|
-
this.specifications.clearCache();
|
|
9274
|
-
this._onUserTestsRerun = [];
|
|
9275
|
-
this._vite = server;
|
|
8994
|
+
this.watcher.unregisterWatcher(), clearTimeout(this._rerunTimer), this.restartsCount += 1, this.pool?.close?.(), this.pool = void 0, this.closingPromise = void 0, this.projects = [], this.coverageProvider = void 0, this.runningPromise = void 0, this.coreWorkspaceProject = void 0, this.specifications.clearCache(), this._onUserTestsRerun = [], this._vite = server;
|
|
9276
8995
|
const resolved = resolveConfig(this, options, server.config);
|
|
9277
|
-
this._config = resolved;
|
|
9278
|
-
this.
|
|
9279
|
-
|
|
9280
|
-
this.
|
|
9281
|
-
this._testRun = new TestRun(this);
|
|
9282
|
-
if (this.config.watch) this.watcher.registerWatcher();
|
|
9283
|
-
this.vitenode = new ViteNodeServer(server, this.config.server);
|
|
9284
|
-
const node = this.vitenode;
|
|
9285
|
-
this.runner = new ViteNodeRunner({
|
|
9286
|
-
root: server.config.root,
|
|
9287
|
-
base: server.config.base,
|
|
9288
|
-
fetchModule(id) {
|
|
9289
|
-
return node.fetchModule(id);
|
|
9290
|
-
},
|
|
9291
|
-
resolveId(id, importer) {
|
|
9292
|
-
return node.resolveId(id, importer);
|
|
9293
|
-
}
|
|
9294
|
-
});
|
|
9295
|
-
if (this.config.watch) {
|
|
8996
|
+
if (this._config = resolved, this._state = new StateManager({ onUnhandledError: resolved.onUnhandledError }), this._cache = new VitestCache(this.version), this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions }), this._testRun = new TestRun(this), this.config.watch) this.watcher.registerWatcher();
|
|
8997
|
+
this._resolver = new VitestResolver(server.config.cacheDir, resolved);
|
|
8998
|
+
const environment = server.environments.__vitest__;
|
|
8999
|
+
if (this.runner = new ServerModuleRunner(environment, this._resolver, resolved), this.config.watch) {
|
|
9296
9000
|
// hijack server restart
|
|
9297
9001
|
const serverRestart = server.restart;
|
|
9298
|
-
server.restart = async (...args) => {
|
|
9299
|
-
await Promise.all(this._onRestartListeners.map((fn) => fn()));
|
|
9300
|
-
this.report("onServerRestart");
|
|
9301
|
-
await this.close();
|
|
9302
|
-
await serverRestart(...args);
|
|
9303
|
-
};
|
|
9304
9002
|
// since we set `server.hmr: false`, Vite does not auto restart itself
|
|
9305
|
-
server.
|
|
9003
|
+
server.restart = async (...args) => {
|
|
9004
|
+
await Promise.all(this._onRestartListeners.map((fn) => fn())), this.report("onServerRestart"), await this.close(), await serverRestart(...args);
|
|
9005
|
+
}, server.watcher.on("change", async (file) => {
|
|
9306
9006
|
file = normalize(file);
|
|
9307
9007
|
const isConfig = file === server.config.configFile || this.projects.some((p) => p.vite.config.configFile === file);
|
|
9308
|
-
if (isConfig)
|
|
9309
|
-
await Promise.all(this._onRestartListeners.map((fn) => fn("config")));
|
|
9310
|
-
this.report("onServerRestart", "config");
|
|
9311
|
-
await this.close();
|
|
9312
|
-
await serverRestart();
|
|
9313
|
-
}
|
|
9008
|
+
if (isConfig) await Promise.all(this._onRestartListeners.map((fn) => fn("config"))), this.report("onServerRestart", "config"), await this.close(), await serverRestart();
|
|
9314
9009
|
});
|
|
9315
9010
|
}
|
|
9316
9011
|
this.cache.results.setConfig(resolved.root, resolved.cache);
|
|
@@ -9318,28 +9013,24 @@ class Vitest {
|
|
|
9318
9013
|
await this.cache.results.readFromCache();
|
|
9319
9014
|
} catch {}
|
|
9320
9015
|
const projects = await this.resolveProjects(this._cliOptions);
|
|
9321
|
-
this.projects = projects
|
|
9322
|
-
await Promise.all(projects.flatMap((project) => {
|
|
9016
|
+
if (this.projects = projects, await Promise.all(projects.flatMap((project) => {
|
|
9323
9017
|
const hooks = project.vite.config.getSortedPluginHooks("configureVitest");
|
|
9324
9018
|
return hooks.map((hook) => hook({
|
|
9325
9019
|
project,
|
|
9326
9020
|
vitest: this,
|
|
9327
9021
|
injectTestProjects: this.injectTestProject
|
|
9328
9022
|
}));
|
|
9329
|
-
}))
|
|
9330
|
-
if (this._cliOptions.browser?.enabled) {
|
|
9023
|
+
})), this._cliOptions.browser?.enabled) {
|
|
9331
9024
|
const browserProjects = this.projects.filter((p) => p.config.browser.enabled);
|
|
9332
9025
|
if (!browserProjects.length) throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`);
|
|
9333
9026
|
}
|
|
9334
9027
|
if (!this.projects.length) {
|
|
9335
9028
|
const filter = toArray(resolved.project).join("\", \"");
|
|
9336
|
-
|
|
9337
|
-
else throw new Error(`Vitest wasn't able to resolve any project.`);
|
|
9029
|
+
throw filter ? new Error(`No projects matched the filter "${filter}".`) : new Error(`Vitest wasn't able to resolve any project.`);
|
|
9338
9030
|
}
|
|
9339
9031
|
if (!this.coreWorkspaceProject) this.coreWorkspaceProject = TestProject._createBasicProject(this);
|
|
9340
9032
|
if (this.config.testNamePattern) this.configOverride.testNamePattern = this.config.testNamePattern;
|
|
9341
|
-
this.reporters = resolved.mode === "benchmark" ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner) : await createReporters(resolved.reporters, this);
|
|
9342
|
-
await Promise.all(this._onSetServer.map((fn) => fn()));
|
|
9033
|
+
this.reporters = resolved.mode === "benchmark" ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner) : await createReporters(resolved.reporters, this), await Promise.all(this._onSetServer.map((fn) => fn()));
|
|
9343
9034
|
}
|
|
9344
9035
|
/**
|
|
9345
9036
|
* Inject new test projects into the workspace.
|
|
@@ -9347,10 +9038,8 @@ class Vitest {
|
|
|
9347
9038
|
* @returns An array of new test projects. Can be empty if the name was filtered out.
|
|
9348
9039
|
*/
|
|
9349
9040
|
injectTestProject = async (config) => {
|
|
9350
|
-
const currentNames = new Set(this.projects.map((p) => p.name));
|
|
9351
|
-
|
|
9352
|
-
this.projects.push(...projects);
|
|
9353
|
-
return projects;
|
|
9041
|
+
const currentNames = new Set(this.projects.map((p) => p.name)), projects = await resolveProjects(this, this._cliOptions, void 0, Array.isArray(config) ? config : [config], currentNames);
|
|
9042
|
+
return this.projects.push(...projects), projects;
|
|
9354
9043
|
};
|
|
9355
9044
|
/**
|
|
9356
9045
|
* Provide a value to the test context. This value will be available to all tests with `inject`.
|
|
@@ -9366,9 +9055,7 @@ class Vitest {
|
|
|
9366
9055
|
}
|
|
9367
9056
|
/** @internal */
|
|
9368
9057
|
_ensureRootProject() {
|
|
9369
|
-
|
|
9370
|
-
this.coreWorkspaceProject = TestProject._createBasicProject(this);
|
|
9371
|
-
return this.coreWorkspaceProject;
|
|
9058
|
+
return this.coreWorkspaceProject ||= TestProject._createBasicProject(this), this.coreWorkspaceProject;
|
|
9372
9059
|
}
|
|
9373
9060
|
/** @deprecated use `getRootProject` instead */
|
|
9374
9061
|
getCoreWorkspaceProject() {
|
|
@@ -9385,8 +9072,7 @@ class Vitest {
|
|
|
9385
9072
|
* @deprecated use Reported Task API instead
|
|
9386
9073
|
*/
|
|
9387
9074
|
getProjectByTaskId(taskId) {
|
|
9388
|
-
const task = this.state.idMap.get(taskId);
|
|
9389
|
-
const projectName = task.projectName || task?.file?.projectName || "";
|
|
9075
|
+
const task = this.state.idMap.get(taskId), projectName = task.projectName || task?.file?.projectName || "";
|
|
9390
9076
|
return this.getProjectByName(projectName);
|
|
9391
9077
|
}
|
|
9392
9078
|
getProjectByName(name) {
|
|
@@ -9399,7 +9085,7 @@ class Vitest {
|
|
|
9399
9085
|
* @param moduleId The ID of the module in Vite module graph
|
|
9400
9086
|
*/
|
|
9401
9087
|
import(moduleId) {
|
|
9402
|
-
return this.runner.
|
|
9088
|
+
return this.runner.import(moduleId);
|
|
9403
9089
|
}
|
|
9404
9090
|
async resolveProjects(cliOptions) {
|
|
9405
9091
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -9408,8 +9094,7 @@ class Vitest {
|
|
|
9408
9094
|
// user can filter projects with --project flag, `getDefaultTestProject`
|
|
9409
9095
|
// returns the project only if it matches the filter
|
|
9410
9096
|
const project = getDefaultTestProject(this);
|
|
9411
|
-
|
|
9412
|
-
return resolveBrowserProjects(this, new Set([project.name]), [project]);
|
|
9097
|
+
return project ? resolveBrowserProjects(this, new Set([project.name]), [project]) : [];
|
|
9413
9098
|
}
|
|
9414
9099
|
/**
|
|
9415
9100
|
* Glob test files in every project and create a TestSpecification for each file and pool.
|
|
@@ -9419,13 +9104,10 @@ class Vitest {
|
|
|
9419
9104
|
return this.specifications.globTestSpecifications(filters);
|
|
9420
9105
|
}
|
|
9421
9106
|
async initCoverageProvider() {
|
|
9422
|
-
if (this.coverageProvider
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
await this.coverageProvider.initialize(this);
|
|
9426
|
-
this.config.coverage = this.coverageProvider.resolveOptions();
|
|
9107
|
+
if (this.coverageProvider === void 0) {
|
|
9108
|
+
if (this.coverageProvider = await getCoverageProvider(this.config.coverage, this.runner), this.coverageProvider) await this.coverageProvider.initialize(this), this.config.coverage = this.coverageProvider.resolveOptions();
|
|
9109
|
+
return this.coverageProvider;
|
|
9427
9110
|
}
|
|
9428
|
-
return this.coverageProvider;
|
|
9429
9111
|
}
|
|
9430
9112
|
/**
|
|
9431
9113
|
* Merge reports from multiple runs located in the specified directory (value from `--merge-reports` if not specified).
|
|
@@ -9438,23 +9120,15 @@ class Vitest {
|
|
|
9438
9120
|
errors,
|
|
9439
9121
|
coverages,
|
|
9440
9122
|
executionTimes
|
|
9441
|
-
};
|
|
9442
|
-
await this.report("onInit", this);
|
|
9443
|
-
await this.report("onPathsCollected", files.flatMap((f) => f.filepath));
|
|
9123
|
+
}, await this.report("onInit", this);
|
|
9444
9124
|
const specifications = [];
|
|
9445
9125
|
for (const file of files) {
|
|
9446
|
-
const project = this.getProjectByName(file.projectName || "");
|
|
9447
|
-
const specification = project.createSpecification(file.filepath, void 0, file.pool);
|
|
9126
|
+
const project = this.getProjectByName(file.projectName || ""), specification = project.createSpecification(file.filepath, void 0, file.pool);
|
|
9448
9127
|
specifications.push(specification);
|
|
9449
9128
|
}
|
|
9450
|
-
await this.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
|
|
9451
9129
|
await this._testRun.start(specifications).catch(noop);
|
|
9452
9130
|
for (const file of files) await this._reportFileTask(file);
|
|
9453
|
-
this._checkUnhandledErrors(errors)
|
|
9454
|
-
await this._testRun.end(specifications, errors).catch(noop);
|
|
9455
|
-
await this.initCoverageProvider();
|
|
9456
|
-
await this.coverageProvider?.mergeReports?.(coverages);
|
|
9457
|
-
return {
|
|
9131
|
+
return this._checkUnhandledErrors(errors), await this._testRun.end(specifications, errors).catch(noop), await this.initCoverageProvider(), await this.coverageProvider?.mergeReports?.(coverages), {
|
|
9458
9132
|
testModules: this.state.getTestModules(),
|
|
9459
9133
|
unhandledErrors: this.state.getUnhandledErrors()
|
|
9460
9134
|
};
|
|
@@ -9462,10 +9136,8 @@ class Vitest {
|
|
|
9462
9136
|
/** @internal */
|
|
9463
9137
|
async _reportFileTask(file) {
|
|
9464
9138
|
const project = this.getProjectByName(file.projectName || "");
|
|
9465
|
-
await this._testRun.enqueued(project, file).catch(noop);
|
|
9466
|
-
|
|
9467
|
-
const logs = [];
|
|
9468
|
-
const { packs, events } = convertTasksToEvents(file, (task) => {
|
|
9139
|
+
await this._testRun.enqueued(project, file).catch(noop), await this._testRun.collected(project, [file]).catch(noop);
|
|
9140
|
+
const logs = [], { packs, events } = convertTasksToEvents(file, (task) => {
|
|
9469
9141
|
if (task.logs) logs.push(...task.logs);
|
|
9470
9142
|
});
|
|
9471
9143
|
logs.sort((log1, log2) => log1.time - log2.time);
|
|
@@ -9474,12 +9146,10 @@ class Vitest {
|
|
|
9474
9146
|
}
|
|
9475
9147
|
async collect(filters) {
|
|
9476
9148
|
const files = await this.specifications.getRelevantTestSpecifications(filters);
|
|
9477
|
-
|
|
9478
|
-
if (!files.length) return {
|
|
9149
|
+
return files.length ? this.collectTests(files) : {
|
|
9479
9150
|
testModules: [],
|
|
9480
9151
|
unhandledErrors: []
|
|
9481
9152
|
};
|
|
9482
|
-
return this.collectTests(files);
|
|
9483
9153
|
}
|
|
9484
9154
|
/** @deprecated use `getRelevantTestSpecifications` instead */
|
|
9485
9155
|
listFiles(filters) {
|
|
@@ -9502,8 +9172,7 @@ class Vitest {
|
|
|
9502
9172
|
*/
|
|
9503
9173
|
async start(filters) {
|
|
9504
9174
|
try {
|
|
9505
|
-
await this.initCoverageProvider();
|
|
9506
|
-
await this.coverageProvider?.clean(this.config.coverage.clean);
|
|
9175
|
+
await this.initCoverageProvider(), await this.coverageProvider?.clean(this.config.coverage.clean);
|
|
9507
9176
|
} finally {
|
|
9508
9177
|
await this.report("onInit", this);
|
|
9509
9178
|
}
|
|
@@ -9513,20 +9182,13 @@ class Vitest {
|
|
|
9513
9182
|
if (!files.length) {
|
|
9514
9183
|
await this._testRun.start([]);
|
|
9515
9184
|
const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true });
|
|
9516
|
-
await this._testRun.end([], [], coverage);
|
|
9517
|
-
// Report coverage for uncovered files
|
|
9518
|
-
await this.reportCoverage(coverage, true);
|
|
9519
|
-
if (!this.config.watch || !(this.config.changed || this.config.related?.length)) throw new FilesNotFoundError(this.mode);
|
|
9185
|
+
if (await this._testRun.end([], [], coverage), await this.reportCoverage(coverage, true), !this.config.watch || !(this.config.changed || this.config.related?.length)) throw new FilesNotFoundError(this.mode);
|
|
9520
9186
|
}
|
|
9521
9187
|
let testModules = {
|
|
9522
9188
|
testModules: [],
|
|
9523
9189
|
unhandledErrors: []
|
|
9524
9190
|
};
|
|
9525
|
-
if (files.length)
|
|
9526
|
-
// populate once, update cache on watch
|
|
9527
|
-
await this.cache.stats.populateStats(this.config.root, files);
|
|
9528
|
-
testModules = await this.runFiles(files, true);
|
|
9529
|
-
}
|
|
9191
|
+
if (files.length) await this.cache.stats.populateStats(this.config.root, files), testModules = await this.runFiles(files, true);
|
|
9530
9192
|
if (this.config.watch) await this.report("onWatcherStart");
|
|
9531
9193
|
return testModules;
|
|
9532
9194
|
}
|
|
@@ -9536,14 +9198,11 @@ class Vitest {
|
|
|
9536
9198
|
*/
|
|
9537
9199
|
async init() {
|
|
9538
9200
|
try {
|
|
9539
|
-
await this.initCoverageProvider();
|
|
9540
|
-
await this.coverageProvider?.clean(this.config.coverage.clean);
|
|
9201
|
+
await this.initCoverageProvider(), await this.coverageProvider?.clean(this.config.coverage.clean);
|
|
9541
9202
|
} finally {
|
|
9542
9203
|
await this.report("onInit", this);
|
|
9543
9204
|
}
|
|
9544
|
-
|
|
9545
|
-
await this.globTestSpecifications();
|
|
9546
|
-
if (this.config.watch) await this.report("onWatcherStart");
|
|
9205
|
+
if (await this.globTestSpecifications(), this.config.watch) await this.report("onWatcherStart");
|
|
9547
9206
|
}
|
|
9548
9207
|
/**
|
|
9549
9208
|
* @deprecated remove when vscode extension supports "getModuleSpecifications"
|
|
@@ -9576,8 +9235,7 @@ class Vitest {
|
|
|
9576
9235
|
* @param allTestsRun Indicates whether all tests were run. This only matters for coverage.
|
|
9577
9236
|
*/
|
|
9578
9237
|
runTestSpecifications(specifications, allTestsRun = false) {
|
|
9579
|
-
specifications.forEach((spec) => this.specifications.ensureSpecificationCached(spec));
|
|
9580
|
-
return this.runFiles(specifications, allTestsRun);
|
|
9238
|
+
return specifications.forEach((spec) => this.specifications.ensureSpecificationCached(spec)), this.runFiles(specifications, allTestsRun);
|
|
9581
9239
|
}
|
|
9582
9240
|
/**
|
|
9583
9241
|
* Rerun files and trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun` events.
|
|
@@ -9589,24 +9247,14 @@ class Vitest {
|
|
|
9589
9247
|
const files = specifications.map((spec) => spec.moduleId);
|
|
9590
9248
|
await Promise.all([this.report("onWatcherRerun", files, "rerun test"), ...this._onUserTestsRerun.map((fn) => fn(specifications))]);
|
|
9591
9249
|
const result = await this.runTestSpecifications(specifications, allTestsRun);
|
|
9592
|
-
await this.report("onWatcherStart", this.state.getFiles(files));
|
|
9593
|
-
return result;
|
|
9250
|
+
return await this.report("onWatcherStart", this.state.getFiles(files)), result;
|
|
9594
9251
|
}
|
|
9595
9252
|
async runFiles(specs, allTestsRun) {
|
|
9596
|
-
await this._testRun.start(specs)
|
|
9597
|
-
// previous run
|
|
9598
|
-
await this.runningPromise;
|
|
9599
|
-
this._onCancelListeners = [];
|
|
9600
|
-
this.isCancelling = false;
|
|
9601
|
-
// schedule the new run
|
|
9602
|
-
this.runningPromise = (async () => {
|
|
9253
|
+
return await this._testRun.start(specs), await this.runningPromise, this._onCancelListeners = [], this.isCancelling = false, this.runningPromise = (async () => {
|
|
9603
9254
|
try {
|
|
9604
9255
|
if (!this.pool) this.pool = createPool(this);
|
|
9605
9256
|
const invalidates = Array.from(this.watcher.invalidates);
|
|
9606
|
-
this.watcher.invalidates.clear();
|
|
9607
|
-
this.snapshot.clear();
|
|
9608
|
-
this.state.clearErrors();
|
|
9609
|
-
if (!this.isFirstRun && this.config.coverage.cleanOnRerun) await this.coverageProvider?.clean();
|
|
9257
|
+
if (this.watcher.invalidates.clear(), this.snapshot.clear(), this.state.clearErrors(), !this.isFirstRun && this.config.coverage.cleanOnRerun) await this.coverageProvider?.clean();
|
|
9610
9258
|
await this.initializeGlobalSetup(specs);
|
|
9611
9259
|
try {
|
|
9612
9260
|
await this.pool.runTests(specs, invalidates);
|
|
@@ -9623,21 +9271,12 @@ class Vitest {
|
|
|
9623
9271
|
unhandledErrors: this.state.getUnhandledErrors()
|
|
9624
9272
|
};
|
|
9625
9273
|
} finally {
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
const errors = this.state.getUnhandledErrors();
|
|
9629
|
-
this._checkUnhandledErrors(errors);
|
|
9630
|
-
await this._testRun.end(specs, errors, coverage);
|
|
9631
|
-
await this.reportCoverage(coverage, allTestsRun);
|
|
9274
|
+
const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun }), errors = this.state.getUnhandledErrors();
|
|
9275
|
+
this._checkUnhandledErrors(errors), await this._testRun.end(specs, errors, coverage), await this.reportCoverage(coverage, allTestsRun);
|
|
9632
9276
|
}
|
|
9633
9277
|
})().finally(() => {
|
|
9634
|
-
this.runningPromise = void 0;
|
|
9635
|
-
|
|
9636
|
-
// all subsequent runs will treat this as a fresh run
|
|
9637
|
-
this.config.changed = false;
|
|
9638
|
-
this.config.related = void 0;
|
|
9639
|
-
});
|
|
9640
|
-
return await this.runningPromise;
|
|
9278
|
+
this.runningPromise = void 0, this.isFirstRun = false, this.config.changed = false, this.config.related = void 0;
|
|
9279
|
+
}), await this.runningPromise;
|
|
9641
9280
|
}
|
|
9642
9281
|
/**
|
|
9643
9282
|
* Collect tests in specified modules. Vitest will run the files to collect tests.
|
|
@@ -9645,19 +9284,10 @@ class Vitest {
|
|
|
9645
9284
|
*/
|
|
9646
9285
|
async collectTests(specifications) {
|
|
9647
9286
|
const filepaths = specifications.map((spec) => spec.moduleId);
|
|
9648
|
-
this.state.collectPaths(filepaths)
|
|
9649
|
-
// previous run
|
|
9650
|
-
await this.runningPromise;
|
|
9651
|
-
this._onCancelListeners = [];
|
|
9652
|
-
this.isCancelling = false;
|
|
9653
|
-
// schedule the new run
|
|
9654
|
-
this.runningPromise = (async () => {
|
|
9287
|
+
return this.state.collectPaths(filepaths), await this.runningPromise, this._onCancelListeners = [], this.isCancelling = false, this.runningPromise = (async () => {
|
|
9655
9288
|
if (!this.pool) this.pool = createPool(this);
|
|
9656
9289
|
const invalidates = Array.from(this.watcher.invalidates);
|
|
9657
|
-
this.watcher.invalidates.clear();
|
|
9658
|
-
this.snapshot.clear();
|
|
9659
|
-
this.state.clearErrors();
|
|
9660
|
-
await this.initializeGlobalSetup(specifications);
|
|
9290
|
+
this.watcher.invalidates.clear(), this.snapshot.clear(), this.state.clearErrors(), await this.initializeGlobalSetup(specifications);
|
|
9661
9291
|
try {
|
|
9662
9292
|
await this.pool.collectTests(specifications, invalidates);
|
|
9663
9293
|
} catch (err) {
|
|
@@ -9672,28 +9302,21 @@ class Vitest {
|
|
|
9672
9302
|
unhandledErrors: this.state.getUnhandledErrors()
|
|
9673
9303
|
};
|
|
9674
9304
|
})().finally(() => {
|
|
9675
|
-
this.runningPromise = void 0;
|
|
9676
|
-
|
|
9677
|
-
this.config.changed = false;
|
|
9678
|
-
this.config.related = void 0;
|
|
9679
|
-
});
|
|
9680
|
-
return await this.runningPromise;
|
|
9305
|
+
this.runningPromise = void 0, this.config.changed = false, this.config.related = void 0;
|
|
9306
|
+
}), await this.runningPromise;
|
|
9681
9307
|
}
|
|
9682
9308
|
/**
|
|
9683
9309
|
* Gracefully cancel the current test run. Vitest will wait until all running tests are finished before cancelling.
|
|
9684
9310
|
*/
|
|
9685
9311
|
async cancelCurrentRun(reason) {
|
|
9686
|
-
this.isCancelling = true;
|
|
9687
|
-
await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason)));
|
|
9688
|
-
await this.runningPromise;
|
|
9312
|
+
this.isCancelling = true, await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason))), await this.runningPromise;
|
|
9689
9313
|
}
|
|
9690
9314
|
/** @internal */
|
|
9691
9315
|
async _initBrowserServers() {
|
|
9692
9316
|
await Promise.all(this.projects.map((p) => p._initBrowserServer()));
|
|
9693
9317
|
}
|
|
9694
9318
|
async initializeGlobalSetup(paths) {
|
|
9695
|
-
const projects = new Set(paths.map((spec) => spec.project));
|
|
9696
|
-
const coreProject = this.getRootProject();
|
|
9319
|
+
const projects = new Set(paths.map((spec) => spec.project)), coreProject = this.getRootProject();
|
|
9697
9320
|
if (!projects.has(coreProject)) projects.add(coreProject);
|
|
9698
9321
|
for (const project of projects) await project._initializeGlobalSetup();
|
|
9699
9322
|
}
|
|
@@ -9707,8 +9330,7 @@ class Vitest {
|
|
|
9707
9330
|
const specifications = files.flatMap((file) => this.getModuleSpecifications(file));
|
|
9708
9331
|
await Promise.all([this.report("onWatcherRerun", files, trigger), ...this._onUserTestsRerun.map((fn) => fn(specifications))]);
|
|
9709
9332
|
const testResult = await this.runFiles(specifications, allTestsRun);
|
|
9710
|
-
await this.report("onWatcherStart", this.state.getFiles(files));
|
|
9711
|
-
return testResult;
|
|
9333
|
+
return await this.report("onWatcherStart", this.state.getFiles(files)), testResult;
|
|
9712
9334
|
}
|
|
9713
9335
|
/** @internal */
|
|
9714
9336
|
async rerunTask(id) {
|
|
@@ -9728,9 +9350,8 @@ class Vitest {
|
|
|
9728
9350
|
// Empty test name pattern should reset filename pattern as well
|
|
9729
9351
|
if (pattern === "") this.filenamePattern = void 0;
|
|
9730
9352
|
const testNamePattern = pattern ? new RegExp(pattern) : void 0;
|
|
9731
|
-
this.configOverride.testNamePattern = testNamePattern;
|
|
9732
9353
|
// filter only test files that have tests matching the pattern
|
|
9733
|
-
if (testNamePattern) files = files.filter((filepath) => {
|
|
9354
|
+
if (this.configOverride.testNamePattern = testNamePattern, testNamePattern) files = files.filter((filepath) => {
|
|
9734
9355
|
const files = this.state.getFiles([filepath]);
|
|
9735
9356
|
return !files.length || files.some((file) => {
|
|
9736
9357
|
const tasks = getTasks(file);
|
|
@@ -9754,9 +9375,7 @@ class Vitest {
|
|
|
9754
9375
|
* @param files The list of files on the file system
|
|
9755
9376
|
*/
|
|
9756
9377
|
async updateSnapshot(files) {
|
|
9757
|
-
|
|
9758
|
-
files = files || [...this.state.getFailedFilepaths(), ...this.snapshot.summary.uncheckedKeysByFile.map((s) => s.filePath)];
|
|
9759
|
-
this.enableSnapshotUpdate();
|
|
9378
|
+
files = files || [...this.state.getFailedFilepaths(), ...this.snapshot.summary.uncheckedKeysByFile.map((s) => s.filePath)], this.enableSnapshotUpdate();
|
|
9760
9379
|
try {
|
|
9761
9380
|
return await this.rerunFiles(files, "update snapshot", false);
|
|
9762
9381
|
} finally {
|
|
@@ -9774,15 +9393,13 @@ class Vitest {
|
|
|
9774
9393
|
this.configOverride.snapshotOptions = {
|
|
9775
9394
|
updateSnapshot: "all",
|
|
9776
9395
|
snapshotEnvironment: null
|
|
9777
|
-
};
|
|
9778
|
-
this.snapshot.options.updateSnapshot = "all";
|
|
9396
|
+
}, this.snapshot.options.updateSnapshot = "all";
|
|
9779
9397
|
}
|
|
9780
9398
|
/**
|
|
9781
9399
|
* Disable the mode that allows updating snapshots when running tests.
|
|
9782
9400
|
*/
|
|
9783
9401
|
resetSnapshotUpdate() {
|
|
9784
|
-
delete this.configOverride.snapshotOptions;
|
|
9785
|
-
this.snapshot.options.updateSnapshot = this.config.snapshotOptions.updateSnapshot;
|
|
9402
|
+
delete this.configOverride.snapshotOptions, this.snapshot.options.updateSnapshot = this.config.snapshotOptions.updateSnapshot;
|
|
9786
9403
|
}
|
|
9787
9404
|
/**
|
|
9788
9405
|
* Set the global test name pattern to a regexp.
|
|
@@ -9802,51 +9419,37 @@ class Vitest {
|
|
|
9802
9419
|
// we can't use a single `triggerId` yet because vscode extension relies on this
|
|
9803
9420
|
async scheduleRerun(triggerId) {
|
|
9804
9421
|
const currentCount = this.restartsCount;
|
|
9805
|
-
clearTimeout(this._rerunTimer)
|
|
9806
|
-
await this.runningPromise;
|
|
9807
|
-
clearTimeout(this._rerunTimer);
|
|
9808
|
-
// server restarted
|
|
9809
|
-
if (this.restartsCount !== currentCount) return;
|
|
9810
|
-
this._rerunTimer = setTimeout(async () => {
|
|
9422
|
+
clearTimeout(this._rerunTimer), await this.runningPromise, clearTimeout(this._rerunTimer), this.restartsCount === currentCount && (this._rerunTimer = setTimeout(async () => {
|
|
9811
9423
|
if (this.watcher.changedTests.size === 0) {
|
|
9812
9424
|
this.watcher.invalidates.clear();
|
|
9813
9425
|
return;
|
|
9814
9426
|
}
|
|
9815
9427
|
// server restarted
|
|
9816
9428
|
if (this.restartsCount !== currentCount) return;
|
|
9817
|
-
this.isFirstRun = false;
|
|
9818
|
-
this.snapshot.clear();
|
|
9429
|
+
this.isFirstRun = false, this.snapshot.clear();
|
|
9819
9430
|
let files = Array.from(this.watcher.changedTests);
|
|
9820
9431
|
if (this.filenamePattern) {
|
|
9821
9432
|
const filteredFiles = await this.globTestSpecifications(this.filenamePattern);
|
|
9822
|
-
files = files.filter((file) => filteredFiles.some((f) => f.moduleId === file));
|
|
9823
9433
|
// A file that does not match the current filename pattern was changed
|
|
9824
|
-
if (files.length === 0) return;
|
|
9434
|
+
if (files = files.filter((file) => filteredFiles.some((f) => f.moduleId === file)), files.length === 0) return;
|
|
9825
9435
|
}
|
|
9826
9436
|
this.watcher.changedTests.clear();
|
|
9827
|
-
const triggerIds = new Set(triggerId.map((id) => relative(this.config.root, id)))
|
|
9828
|
-
|
|
9829
|
-
// get file specifications and filter them if needed
|
|
9830
|
-
const specifications = files.flatMap((file) => this.getModuleSpecifications(file)).filter((specification) => {
|
|
9831
|
-
if (this._onFilterWatchedSpecification.length === 0) return true;
|
|
9832
|
-
return this._onFilterWatchedSpecification.every((fn) => fn(specification));
|
|
9437
|
+
const triggerIds = new Set(triggerId.map((id) => relative(this.config.root, id))), triggerLabel = Array.from(triggerIds).join(", "), specifications = files.flatMap((file) => this.getModuleSpecifications(file)).filter((specification) => {
|
|
9438
|
+
return this._onFilterWatchedSpecification.length === 0 ? true : this._onFilterWatchedSpecification.every((fn) => fn(specification));
|
|
9833
9439
|
});
|
|
9834
|
-
await Promise.all([this.report("onWatcherRerun", files, triggerLabel), ...this._onUserTestsRerun.map((fn) => fn(specifications))]);
|
|
9835
|
-
|
|
9836
|
-
await this.report("onWatcherStart", this.state.getFiles(files));
|
|
9837
|
-
}, WATCHER_DEBOUNCE);
|
|
9440
|
+
await Promise.all([this.report("onWatcherRerun", files, triggerLabel), ...this._onUserTestsRerun.map((fn) => fn(specifications))]), await this.runFiles(specifications, false), await this.report("onWatcherStart", this.state.getFiles(files));
|
|
9441
|
+
}, WATCHER_DEBOUNCE));
|
|
9838
9442
|
}
|
|
9839
9443
|
/**
|
|
9840
9444
|
* Invalidate a file in all projects.
|
|
9841
9445
|
*/
|
|
9842
9446
|
invalidateFile(filepath) {
|
|
9843
9447
|
this.projects.forEach(({ vite, browser }) => {
|
|
9844
|
-
const
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
}
|
|
9448
|
+
const environments = [...Object.values(vite.environments), ...Object.values(browser?.vite.environments || {})];
|
|
9449
|
+
environments.forEach(({ moduleGraph }) => {
|
|
9450
|
+
const modules = moduleGraph.getModulesByFile(filepath);
|
|
9451
|
+
modules?.forEach((module) => moduleGraph.invalidateModule(module));
|
|
9452
|
+
});
|
|
9850
9453
|
});
|
|
9851
9454
|
}
|
|
9852
9455
|
/** @deprecated use `invalidateFile` */
|
|
@@ -9859,8 +9462,7 @@ class Vitest {
|
|
|
9859
9462
|
}
|
|
9860
9463
|
async reportCoverage(coverage, allTestsRun) {
|
|
9861
9464
|
if (this.state.getCountOfFailedTests() > 0) {
|
|
9862
|
-
await this.coverageProvider?.onTestFailure?.();
|
|
9863
|
-
if (!this.config.coverage.reportOnFailure) return;
|
|
9465
|
+
if (await this.coverageProvider?.onTestFailure?.(), !this.config.coverage.reportOnFailure) return;
|
|
9864
9466
|
}
|
|
9865
9467
|
if (this.coverageProvider) {
|
|
9866
9468
|
await this.coverageProvider.reportCoverage(coverage, { allTestsRun });
|
|
@@ -9883,11 +9485,9 @@ class Vitest {
|
|
|
9883
9485
|
// it's possible that it's not initialized at all because it's not running any tests
|
|
9884
9486
|
if (this.coreWorkspaceProject && !this.projects.includes(this.coreWorkspaceProject)) closePromises.push(this.coreWorkspaceProject.close().then(() => this._vite = void 0));
|
|
9885
9487
|
if (this.pool) closePromises.push((async () => {
|
|
9886
|
-
await this.pool?.close?.();
|
|
9887
|
-
this.pool = void 0;
|
|
9488
|
+
await this.pool?.close?.(), this.pool = void 0;
|
|
9888
9489
|
})());
|
|
9889
|
-
closePromises.push(...this._onClose.map((fn) => fn()))
|
|
9890
|
-
return Promise.allSettled(closePromises).then((results) => {
|
|
9490
|
+
return closePromises.push(...this._onClose.map((fn) => fn())), Promise.allSettled(closePromises).then((results) => {
|
|
9891
9491
|
results.forEach((r) => {
|
|
9892
9492
|
if (r.status === "rejected") this.logger.error("error during close", r.reason);
|
|
9893
9493
|
});
|
|
@@ -9900,11 +9500,9 @@ class Vitest {
|
|
|
9900
9500
|
* @param force If true, the process will exit immediately after closing the projects.
|
|
9901
9501
|
*/
|
|
9902
9502
|
async exit(force = false) {
|
|
9903
|
-
setTimeout(() => {
|
|
9503
|
+
if (setTimeout(() => {
|
|
9904
9504
|
this.report("onProcessTimeout").then(() => {
|
|
9905
|
-
console.warn(`close timed out after ${this.config.teardownTimeout}ms`)
|
|
9906
|
-
this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause));
|
|
9907
|
-
if (!this.pool) {
|
|
9505
|
+
if (console.warn(`close timed out after ${this.config.teardownTimeout}ms`), this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause)), !this.pool) {
|
|
9908
9506
|
const runningServers = [this._vite, ...this.projects.map((p) => p._vite)].filter(Boolean).length;
|
|
9909
9507
|
if (runningServers === 1) console.warn("Tests closed successfully but something prevents Vite server from exiting");
|
|
9910
9508
|
else if (runningServers > 1) console.warn(`Tests closed successfully but something prevents ${runningServers} Vite servers from exiting`);
|
|
@@ -9913,9 +9511,7 @@ class Vitest {
|
|
|
9913
9511
|
}
|
|
9914
9512
|
process.exit();
|
|
9915
9513
|
});
|
|
9916
|
-
}, this.config.teardownTimeout).unref();
|
|
9917
|
-
await this.close();
|
|
9918
|
-
if (force) process.exit();
|
|
9514
|
+
}, this.config.teardownTimeout).unref(), await this.close(), force) process.exit();
|
|
9919
9515
|
}
|
|
9920
9516
|
/** @internal */
|
|
9921
9517
|
async report(name, ...args) {
|
|
@@ -9997,9 +9593,7 @@ class Vitest {
|
|
|
9997
9593
|
*/
|
|
9998
9594
|
matchesProjectFilter(name) {
|
|
9999
9595
|
const projects = this._config?.project || this._cliOptions?.project;
|
|
10000
|
-
|
|
10001
|
-
if (!projects || !projects.length) return true;
|
|
10002
|
-
return toArray(projects).some((project) => {
|
|
9596
|
+
return !projects || !projects.length ? true : toArray(projects).some((project) => {
|
|
10003
9597
|
const regexp = wildcardPatternToRegExp(project);
|
|
10004
9598
|
return regexp.test(name);
|
|
10005
9599
|
});
|
|
@@ -10012,8 +9606,7 @@ function assert(condition, property, name = property) {
|
|
|
10012
9606
|
async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(options))) {
|
|
10013
9607
|
const userConfig = deepMerge({}, options);
|
|
10014
9608
|
async function UIPlugin() {
|
|
10015
|
-
await vitest.packageInstaller.ensureInstalled("@vitest/ui", options.root || process.cwd(), vitest.version);
|
|
10016
|
-
return (await import('@vitest/ui')).default(vitest);
|
|
9609
|
+
return await vitest.packageInstaller.ensureInstalled("@vitest/ui", options.root || process.cwd(), vitest.version), (await import('@vitest/ui')).default(vitest);
|
|
10017
9610
|
}
|
|
10018
9611
|
return [
|
|
10019
9612
|
{
|
|
@@ -10039,14 +9632,9 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
10039
9632
|
let open = false;
|
|
10040
9633
|
if (testConfig.ui && testConfig.open) open = testConfig.uiBase ?? "/__vitest__/";
|
|
10041
9634
|
const resolveOptions = getDefaultResolveOptions();
|
|
10042
|
-
|
|
9635
|
+
let config = {
|
|
10043
9636
|
root: viteConfig.test?.root || options.root,
|
|
10044
9637
|
define: { "process.env.NODE_ENV": "process.env.NODE_ENV" },
|
|
10045
|
-
esbuild: viteConfig.esbuild === false ? false : {
|
|
10046
|
-
target: viteConfig.esbuild?.target || "node18",
|
|
10047
|
-
sourcemap: "external",
|
|
10048
|
-
legalComments: "inline"
|
|
10049
|
-
},
|
|
10050
9638
|
resolve: {
|
|
10051
9639
|
...resolveOptions,
|
|
10052
9640
|
alias: testConfig.alias
|
|
@@ -10063,7 +9651,10 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
10063
9651
|
outDir: "dummy-non-existing-folder",
|
|
10064
9652
|
emptyOutDir: false
|
|
10065
9653
|
},
|
|
10066
|
-
environments: {
|
|
9654
|
+
environments: {
|
|
9655
|
+
ssr: { resolve: resolveOptions },
|
|
9656
|
+
__vitest__: { dev: {} }
|
|
9657
|
+
},
|
|
10067
9658
|
test: {
|
|
10068
9659
|
poolOptions: {
|
|
10069
9660
|
threads: { isolate: options.poolOptions?.threads?.isolate ?? options.isolate ?? testConfig.poolOptions?.threads?.isolate ?? viteConfig.test?.isolate },
|
|
@@ -10073,33 +9664,29 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
10073
9664
|
deps: testConfig.deps ?? viteConfig.test?.deps
|
|
10074
9665
|
}
|
|
10075
9666
|
};
|
|
9667
|
+
if ("rolldownVersion" in vite) config = {
|
|
9668
|
+
...config,
|
|
9669
|
+
oxc: viteConfig.oxc === false ? false : { target: viteConfig.oxc?.target || "node18" }
|
|
9670
|
+
};
|
|
9671
|
+
else config = {
|
|
9672
|
+
...config,
|
|
9673
|
+
esbuild: viteConfig.esbuild === false ? false : {
|
|
9674
|
+
target: viteConfig.esbuild?.target || "node18",
|
|
9675
|
+
sourcemap: "external",
|
|
9676
|
+
legalComments: "inline"
|
|
9677
|
+
}
|
|
9678
|
+
};
|
|
10076
9679
|
// inherit so it's available in VitestOptimizer
|
|
10077
9680
|
// I cannot wait to rewrite all of this in Vitest 4
|
|
10078
9681
|
if (options.cache != null) config.test.cache = options.cache;
|
|
10079
9682
|
if (vitest.configOverride.project)
|
|
10080
9683
|
// project filter was set by the user, so we need to filter the project
|
|
10081
9684
|
options.project = vitest.configOverride.project;
|
|
10082
|
-
config.customLogger = createViteLogger(vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false });
|
|
10083
|
-
config.customLogger = silenceImportViteIgnoreWarning(config.customLogger);
|
|
10084
|
-
// we want inline dependencies to be resolved by analyser plugin so module graph is populated correctly
|
|
10085
|
-
if (viteConfig.ssr?.noExternal !== true) {
|
|
10086
|
-
const inline = testConfig.server?.deps?.inline;
|
|
10087
|
-
if (inline === true) config.ssr = { noExternal: true };
|
|
10088
|
-
else {
|
|
10089
|
-
const noExternal = viteConfig.ssr?.noExternal;
|
|
10090
|
-
const noExternalArray = typeof noExternal !== "undefined" ? toArray(noExternal) : void 0;
|
|
10091
|
-
// filter the same packages
|
|
10092
|
-
const uniqueInline = inline && noExternalArray ? inline.filter((dep) => !noExternalArray.includes(dep)) : inline;
|
|
10093
|
-
config.ssr = { noExternal: uniqueInline };
|
|
10094
|
-
}
|
|
10095
|
-
}
|
|
10096
9685
|
// chokidar fsevents is unstable on macos when emitting "ready" event
|
|
10097
|
-
if (process.platform === "darwin" && false);
|
|
9686
|
+
if (config.customLogger = createViteLogger(vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false }), config.customLogger = silenceImportViteIgnoreWarning(config.customLogger), process.platform === "darwin" && false);
|
|
10098
9687
|
const classNameStrategy = typeof testConfig.css !== "boolean" && testConfig.css?.modules?.classNameStrategy || "stable";
|
|
10099
9688
|
if (classNameStrategy !== "scoped") {
|
|
10100
|
-
config.css ??= {}
|
|
10101
|
-
config.css.modules ??= {};
|
|
10102
|
-
if (config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
|
|
9689
|
+
if (config.css ??= {}, config.css.modules ??= {}, config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
|
|
10103
9690
|
const root = vitest.config.root || options.root || process.cwd();
|
|
10104
9691
|
return generateScopedClassName(classNameStrategy, name, relative(root, filename));
|
|
10105
9692
|
};
|
|
@@ -10110,17 +9697,11 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
10110
9697
|
const viteConfigTest = viteConfig.test || {};
|
|
10111
9698
|
if (viteConfigTest.watch === false) viteConfigTest.run = true;
|
|
10112
9699
|
if ("alias" in viteConfigTest) delete viteConfigTest.alias;
|
|
10113
|
-
|
|
10114
|
-
options = deepMerge({}, configDefaults, viteConfigTest, options);
|
|
10115
|
-
options.api = resolveApiServerConfig(options, defaultPort);
|
|
9700
|
+
options = deepMerge({}, configDefaults, viteConfigTest, options), options.api = resolveApiServerConfig(options, defaultPort);
|
|
10116
9701
|
// we replace every "import.meta.env" with "process.env"
|
|
10117
9702
|
// to allow reassigning, so we need to put all envs on process.env
|
|
10118
9703
|
const { PROD, DEV,...envs } = viteConfig.env;
|
|
10119
|
-
|
|
10120
|
-
// so we are making them truthy
|
|
10121
|
-
process.env.PROD ??= PROD ? "1" : "";
|
|
10122
|
-
process.env.DEV ??= DEV ? "1" : "";
|
|
10123
|
-
for (const name in envs) process.env[name] ??= envs[name];
|
|
9704
|
+
for (const name in process.env.PROD ??= PROD ? "1" : "", process.env.DEV ??= DEV ? "1" : "", envs) process.env[name] ??= envs[name];
|
|
10124
9705
|
// don't watch files in run mode
|
|
10125
9706
|
if (!options.watch) viteConfig.server.watch = null;
|
|
10126
9707
|
if (options.ui)
|
|
@@ -10140,20 +9721,20 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
10140
9721
|
order: "post",
|
|
10141
9722
|
async handler(server) {
|
|
10142
9723
|
if (options.watch && false);
|
|
10143
|
-
await vitest._setServer(options, server);
|
|
10144
|
-
if (options.api && options.watch) (await Promise.resolve().then(function () { return setup$1; })).setup(vitest);
|
|
9724
|
+
if (await vitest._setServer(options, server), options.api && options.watch) (await Promise.resolve().then(function () { return setup$1; })).setup(vitest);
|
|
10145
9725
|
// #415, in run mode we don't need the watcher, close it would improve the performance
|
|
10146
9726
|
if (!options.watch) await server.watcher.close();
|
|
10147
9727
|
}
|
|
10148
9728
|
}
|
|
10149
9729
|
},
|
|
10150
|
-
|
|
9730
|
+
MetaEnvReplacerPlugin(),
|
|
10151
9731
|
...CSSEnablerPlugin(vitest),
|
|
10152
9732
|
CoverageTransform(vitest),
|
|
10153
9733
|
VitestCoreResolver(vitest),
|
|
10154
9734
|
...MocksPlugins(),
|
|
10155
9735
|
VitestOptimizer(),
|
|
10156
|
-
NormalizeURLPlugin()
|
|
9736
|
+
NormalizeURLPlugin(),
|
|
9737
|
+
ModuleRunnerTransform()
|
|
10157
9738
|
].filter(notNullish);
|
|
10158
9739
|
}
|
|
10159
9740
|
function removeUndefinedValues(obj) {
|
|
@@ -10162,25 +9743,19 @@ function removeUndefinedValues(obj) {
|
|
|
10162
9743
|
}
|
|
10163
9744
|
|
|
10164
9745
|
async function createVitest(mode, options, viteOverrides = {}, vitestOptions = {}) {
|
|
10165
|
-
const ctx = new Vitest(mode, deepClone(options), vitestOptions);
|
|
10166
|
-
const root = slash(resolve$1(options.root || process.cwd()));
|
|
10167
|
-
const configPath = options.config === false ? false : options.config ? resolve$1(root, options.config) : await findUp(configFiles, { cwd: root });
|
|
9746
|
+
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) : await findUp(configFiles, { cwd: root });
|
|
10168
9747
|
options.config = configPath;
|
|
10169
|
-
const { browser: _removeBrowser,...restOptions } = options
|
|
10170
|
-
const config = {
|
|
9748
|
+
const { browser: _removeBrowser,...restOptions } = options, config = {
|
|
10171
9749
|
configFile: configPath,
|
|
10172
9750
|
configLoader: options.configLoader,
|
|
10173
9751
|
mode: options.mode || mode,
|
|
10174
9752
|
plugins: await VitestPlugin(restOptions, ctx)
|
|
10175
|
-
};
|
|
10176
|
-
const server = await createViteServer(mergeConfig(config, mergeConfig(viteOverrides, { root: options.root })));
|
|
9753
|
+
}, server = await createViteServer(mergeConfig(config, mergeConfig(viteOverrides, { root: options.root })));
|
|
10177
9754
|
if (ctx.config.api?.port) await server.listen();
|
|
10178
9755
|
return ctx;
|
|
10179
9756
|
}
|
|
10180
9757
|
|
|
10181
|
-
const MAX_RESULT_COUNT = 10;
|
|
10182
|
-
const SELECTION_MAX_INDEX = 7;
|
|
10183
|
-
const ESC = "\x1B[";
|
|
9758
|
+
const MAX_RESULT_COUNT = 10, SELECTION_MAX_INDEX = 7, ESC = "\x1B[";
|
|
10184
9759
|
class WatchFilter {
|
|
10185
9760
|
filterRL;
|
|
10186
9761
|
currentKeyword = void 0;
|
|
@@ -10191,23 +9766,17 @@ class WatchFilter {
|
|
|
10191
9766
|
stdin;
|
|
10192
9767
|
stdout;
|
|
10193
9768
|
constructor(message, stdin = process.stdin, stdout$1 = stdout()) {
|
|
10194
|
-
this.message = message
|
|
10195
|
-
this.stdin = stdin;
|
|
10196
|
-
this.stdout = stdout$1;
|
|
10197
|
-
this.filterRL = readline.createInterface({
|
|
9769
|
+
if (this.message = message, this.stdin = stdin, this.stdout = stdout$1, this.filterRL = readline.createInterface({
|
|
10198
9770
|
input: this.stdin,
|
|
10199
9771
|
escapeCodeTimeout: 50
|
|
10200
|
-
});
|
|
10201
|
-
readline.emitKeypressEvents(this.stdin, this.filterRL);
|
|
10202
|
-
if (this.stdin.isTTY) this.stdin.setRawMode(true);
|
|
9772
|
+
}), readline.emitKeypressEvents(this.stdin, this.filterRL), this.stdin.isTTY) this.stdin.setRawMode(true);
|
|
10203
9773
|
}
|
|
10204
9774
|
async filter(filterFunc) {
|
|
10205
9775
|
this.write(this.promptLine());
|
|
10206
9776
|
const resultPromise = createDefer();
|
|
10207
9777
|
this.onKeyPress = this.filterHandler(filterFunc, (result) => {
|
|
10208
9778
|
resultPromise.resolve(result);
|
|
10209
|
-
});
|
|
10210
|
-
this.stdin.on("keypress", this.onKeyPress);
|
|
9779
|
+
}), this.stdin.on("keypress", this.onKeyPress);
|
|
10211
9780
|
try {
|
|
10212
9781
|
return await resultPromise;
|
|
10213
9782
|
} finally {
|
|
@@ -10223,13 +9792,11 @@ class WatchFilter {
|
|
|
10223
9792
|
break;
|
|
10224
9793
|
case key?.ctrl && key?.name === "c":
|
|
10225
9794
|
case key?.name === "escape":
|
|
10226
|
-
this.write(`${ESC}1G${ESC}0J`);
|
|
10227
|
-
onSubmit(void 0);
|
|
9795
|
+
this.write(`${ESC}1G${ESC}0J`), onSubmit(void 0);
|
|
10228
9796
|
return;
|
|
10229
9797
|
case key?.name === "enter":
|
|
10230
9798
|
case key?.name === "return":
|
|
10231
|
-
onSubmit(this.results[this.selectionIndex] || this.currentKeyword || "");
|
|
10232
|
-
this.currentKeyword = void 0;
|
|
9799
|
+
onSubmit(this.results[this.selectionIndex] || this.currentKeyword || ""), this.currentKeyword = void 0;
|
|
10233
9800
|
break;
|
|
10234
9801
|
case key?.name === "up":
|
|
10235
9802
|
if (this.selectionIndex && this.selectionIndex > 0) this.selectionIndex--;
|
|
@@ -10256,17 +9823,13 @@ class WatchFilter {
|
|
|
10256
9823
|
const resultCountLine = this.results.length === 1 ? `Pattern matches ${this.results.length} result` : `Pattern matches ${this.results.length} results`;
|
|
10257
9824
|
let resultBody = "";
|
|
10258
9825
|
if (this.results.length > MAX_RESULT_COUNT) {
|
|
10259
|
-
const offset = this.selectionIndex > SELECTION_MAX_INDEX ? this.selectionIndex - SELECTION_MAX_INDEX : 0;
|
|
10260
|
-
|
|
10261
|
-
const remainingResultCount = this.results.length - offset - displayResults.length;
|
|
10262
|
-
resultBody = `${displayResults.map((result, index) => index + offset === this.selectionIndex ? c.green(` › ${result}`) : c.dim(` › ${result}`)).join("\n")}`;
|
|
10263
|
-
if (remainingResultCount > 0) resultBody += `
|
|
9826
|
+
const offset = this.selectionIndex > SELECTION_MAX_INDEX ? this.selectionIndex - SELECTION_MAX_INDEX : 0, displayResults = this.results.slice(offset, MAX_RESULT_COUNT + offset), remainingResultCount = this.results.length - offset - displayResults.length;
|
|
9827
|
+
if (resultBody = `${displayResults.map((result, index) => index + offset === this.selectionIndex ? c.green(` › ${result}`) : c.dim(` › ${result}`)).join("\n")}`, remainingResultCount > 0) resultBody += `
|
|
10264
9828
|
${c.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "result" : "results"}`)}`;
|
|
10265
9829
|
} else resultBody = this.results.map((result, index) => index === this.selectionIndex ? c.green(` › ${result}`) : c.dim(` › ${result}`)).join("\n");
|
|
10266
9830
|
printStr += `\n${resultCountLine}\n${resultBody}`;
|
|
10267
9831
|
}
|
|
10268
|
-
this.eraseAndPrint(printStr);
|
|
10269
|
-
this.restoreCursor();
|
|
9832
|
+
this.eraseAndPrint(printStr), this.restoreCursor();
|
|
10270
9833
|
}
|
|
10271
9834
|
keywordOffset() {
|
|
10272
9835
|
return `? ${this.message} › `.length + 1;
|
|
@@ -10282,14 +9845,10 @@ ${c.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "
|
|
|
10282
9845
|
// We have to take care of screen width in case of long lines
|
|
10283
9846
|
rows += 1 + Math.floor(Math.max(stripVTControlCharacters(line).length - 1, 0) / columns);
|
|
10284
9847
|
}
|
|
10285
|
-
this.write(`${ESC}1G`);
|
|
10286
|
-
this.write(`${ESC}J`);
|
|
10287
|
-
this.write(str);
|
|
10288
|
-
this.write(`${ESC}${rows - 1}A`);
|
|
9848
|
+
this.write(`${ESC}1G`), this.write(`${ESC}J`), this.write(str), this.write(`${ESC}${rows - 1}A`);
|
|
10289
9849
|
}
|
|
10290
9850
|
close() {
|
|
10291
|
-
this.filterRL.close();
|
|
10292
|
-
if (this.onKeyPress) this.stdin.removeListener("keypress", this.onKeyPress);
|
|
9851
|
+
if (this.filterRL.close(), this.onKeyPress) this.stdin.removeListener("keypress", this.onKeyPress);
|
|
10293
9852
|
if (this.stdin.isTTY) this.stdin.setRawMode(false);
|
|
10294
9853
|
}
|
|
10295
9854
|
restoreCursor() {
|
|
@@ -10314,8 +9873,7 @@ const keys = [
|
|
|
10314
9873
|
["w", "filter by a project name"],
|
|
10315
9874
|
["b", "start the browser server if not started yet"],
|
|
10316
9875
|
["q", "quit"]
|
|
10317
|
-
]
|
|
10318
|
-
const cancelKeys = [
|
|
9876
|
+
], cancelKeys = [
|
|
10319
9877
|
"space",
|
|
10320
9878
|
"c",
|
|
10321
9879
|
"h",
|
|
@@ -10333,17 +9891,12 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10333
9891
|
// Cancel run and exit when ctrl-c or esc is pressed.
|
|
10334
9892
|
// If cancelling takes long and key is pressed multiple times, exit forcefully.
|
|
10335
9893
|
if (str === "" || str === "\x1B" || key && key.ctrl && key.name === "c") {
|
|
10336
|
-
if (!ctx.isCancelling)
|
|
10337
|
-
ctx.logger.log(c.red("Cancelling test run. Press CTRL+c again to exit forcefully.\n"));
|
|
10338
|
-
process.exitCode = 130;
|
|
10339
|
-
await ctx.cancelCurrentRun("keyboard-input");
|
|
10340
|
-
}
|
|
9894
|
+
if (!ctx.isCancelling) ctx.logger.log(c.red("Cancelling test run. Press CTRL+c again to exit forcefully.\n")), process.exitCode = 130, await ctx.cancelCurrentRun("keyboard-input");
|
|
10341
9895
|
return ctx.exit(true);
|
|
10342
9896
|
}
|
|
10343
9897
|
// window not support suspend
|
|
10344
9898
|
if (!isWindows && key && key.ctrl && key.name === "z") {
|
|
10345
|
-
process.kill(process.ppid, "SIGTSTP");
|
|
10346
|
-
process.kill(process.pid, "SIGTSTP");
|
|
9899
|
+
process.kill(process.ppid, "SIGTSTP"), process.kill(process.pid, "SIGTSTP");
|
|
10347
9900
|
return;
|
|
10348
9901
|
}
|
|
10349
9902
|
const name = key?.name;
|
|
@@ -10372,24 +9925,17 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10372
9925
|
if (name === "t") return inputNamePattern();
|
|
10373
9926
|
// change fileNamePattern
|
|
10374
9927
|
if (name === "p") return inputFilePattern();
|
|
10375
|
-
if (name === "b") {
|
|
10376
|
-
|
|
10377
|
-
|
|
10378
|
-
ctx.logger.log();
|
|
10379
|
-
ctx.logger.printBrowserBanner(project);
|
|
10380
|
-
});
|
|
10381
|
-
return null;
|
|
10382
|
-
}
|
|
9928
|
+
if (name === "b") return await ctx._initBrowserServers(), ctx.projects.forEach((project) => {
|
|
9929
|
+
ctx.logger.log(), ctx.logger.printBrowserBanner(project);
|
|
9930
|
+
}), null;
|
|
10383
9931
|
}
|
|
10384
9932
|
async function keypressHandler(str, key) {
|
|
10385
9933
|
await _keypressHandler(str, key);
|
|
10386
9934
|
}
|
|
10387
9935
|
async function inputNamePattern() {
|
|
10388
9936
|
off();
|
|
10389
|
-
const watchFilter = new WatchFilter("Input test name pattern (RegExp)", stdin, stdout)
|
|
10390
|
-
|
|
10391
|
-
const files = ctx.state.getFiles();
|
|
10392
|
-
const tests = getTests(files);
|
|
9937
|
+
const watchFilter = new WatchFilter("Input test name pattern (RegExp)", stdin, stdout), filter = await watchFilter.filter((str) => {
|
|
9938
|
+
const files = ctx.state.getFiles(), tests = getTests(files);
|
|
10393
9939
|
try {
|
|
10394
9940
|
const reg = new RegExp(str);
|
|
10395
9941
|
return tests.map((test) => test.name).filter((testName) => testName.match(reg));
|
|
@@ -10398,11 +9944,8 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10398
9944
|
return [];
|
|
10399
9945
|
}
|
|
10400
9946
|
});
|
|
10401
|
-
on();
|
|
10402
|
-
|
|
10403
|
-
const files = ctx.state.getFilepaths();
|
|
10404
|
-
// if running in standalone mode, Vitest instance doesn't know about any test file
|
|
10405
|
-
const cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
|
|
9947
|
+
if (on(), typeof filter === "undefined") return;
|
|
9948
|
+
const files = ctx.state.getFilepaths(), cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
|
|
10406
9949
|
await ctx.changeNamePattern(filter?.trim() || "", cliFiles, "change pattern");
|
|
10407
9950
|
}
|
|
10408
9951
|
async function inputProjectName() {
|
|
@@ -10413,41 +9956,31 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10413
9956
|
message: "Input a single project name",
|
|
10414
9957
|
initial: ctx.config.project[0] || ""
|
|
10415
9958
|
}]);
|
|
10416
|
-
on();
|
|
10417
|
-
await ctx.changeProjectName(filter.trim());
|
|
9959
|
+
on(), await ctx.changeProjectName(filter.trim());
|
|
10418
9960
|
}
|
|
10419
9961
|
async function inputFilePattern() {
|
|
10420
9962
|
off();
|
|
10421
|
-
const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout)
|
|
10422
|
-
const filter = await watchFilter.filter(async (str) => {
|
|
9963
|
+
const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout), filter = await watchFilter.filter(async (str) => {
|
|
10423
9964
|
const files = await ctx.globTestFiles([str]);
|
|
10424
9965
|
return files.map((file) => relative(ctx.config.root, file[1])).filter((file, index, all) => all.indexOf(file) === index);
|
|
10425
9966
|
});
|
|
10426
|
-
on();
|
|
10427
|
-
if (typeof filter === "undefined") return;
|
|
9967
|
+
if (on(), typeof filter === "undefined") return;
|
|
10428
9968
|
latestFilename = filter?.trim() || "";
|
|
10429
9969
|
const lastResults = watchFilter.getLastResults();
|
|
10430
9970
|
await ctx.changeFilenamePattern(latestFilename, filter && lastResults.length ? lastResults.map((i) => resolve(ctx.config.root, i)) : void 0);
|
|
10431
9971
|
}
|
|
10432
9972
|
let rl;
|
|
10433
9973
|
function on() {
|
|
10434
|
-
off()
|
|
10435
|
-
rl = readline.createInterface({
|
|
9974
|
+
if (off(), rl = readline.createInterface({
|
|
10436
9975
|
input: stdin,
|
|
10437
9976
|
escapeCodeTimeout: 50
|
|
10438
|
-
});
|
|
10439
|
-
readline.emitKeypressEvents(stdin, rl);
|
|
10440
|
-
if (stdin.isTTY) stdin.setRawMode(true);
|
|
9977
|
+
}), readline.emitKeypressEvents(stdin, rl), stdin.isTTY) stdin.setRawMode(true);
|
|
10441
9978
|
stdin.on("keypress", keypressHandler);
|
|
10442
9979
|
}
|
|
10443
9980
|
function off() {
|
|
10444
|
-
rl?.close();
|
|
10445
|
-
rl = void 0;
|
|
10446
|
-
stdin.removeListener("keypress", keypressHandler);
|
|
10447
|
-
if (stdin.isTTY) stdin.setRawMode(false);
|
|
9981
|
+
if (rl?.close(), rl = void 0, stdin.removeListener("keypress", keypressHandler), stdin.isTTY) stdin.setRawMode(false);
|
|
10448
9982
|
}
|
|
10449
|
-
on()
|
|
10450
|
-
return function cleanup() {
|
|
9983
|
+
return on(), function cleanup() {
|
|
10451
9984
|
off();
|
|
10452
9985
|
};
|
|
10453
9986
|
}
|
|
@@ -10458,20 +9991,14 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
|
|
|
10458
9991
|
* Returns a Vitest instance if initialized successfully.
|
|
10459
9992
|
*/
|
|
10460
9993
|
async function startVitest(mode, cliFilters = [], options = {}, viteOverrides, vitestOptions) {
|
|
10461
|
-
const root = resolve(options.root || process.cwd());
|
|
10462
|
-
const ctx = await prepareVitest(mode, options, viteOverrides, vitestOptions, cliFilters);
|
|
9994
|
+
const root = resolve(options.root || process.cwd()), ctx = await prepareVitest(mode, options, viteOverrides, vitestOptions, cliFilters);
|
|
10463
9995
|
if (mode === "test" && ctx.config.coverage.enabled) {
|
|
10464
|
-
const provider = ctx.config.coverage.provider || "v8";
|
|
10465
|
-
const requiredPackages = CoverageProviderMap[provider];
|
|
9996
|
+
const provider = ctx.config.coverage.provider || "v8", requiredPackages = CoverageProviderMap[provider];
|
|
10466
9997
|
if (requiredPackages) {
|
|
10467
|
-
if (!await ctx.packageInstaller.ensureInstalled(requiredPackages, root, ctx.version))
|
|
10468
|
-
process.exitCode = 1;
|
|
10469
|
-
return ctx;
|
|
10470
|
-
}
|
|
9998
|
+
if (!await ctx.packageInstaller.ensureInstalled(requiredPackages, root, ctx.version)) return process.exitCode = 1, ctx;
|
|
10471
9999
|
}
|
|
10472
10000
|
}
|
|
10473
|
-
const stdin = vitestOptions?.stdin || process.stdin;
|
|
10474
|
-
const stdout = vitestOptions?.stdout || process.stdout;
|
|
10001
|
+
const stdin = vitestOptions?.stdin || process.stdin, stdout = vitestOptions?.stdout || process.stdout;
|
|
10475
10002
|
let stdinCleanup;
|
|
10476
10003
|
if (stdin.isTTY && ctx.config.watch) stdinCleanup = registerConsoleShortcuts(ctx, stdin, stdout);
|
|
10477
10004
|
ctx.onAfterSetServer(() => {
|
|
@@ -10483,55 +10010,27 @@ async function startVitest(mode, cliFilters = [], options = {}, viteOverrides, v
|
|
|
10483
10010
|
else if (ctx.config.standalone) await ctx.init();
|
|
10484
10011
|
else await ctx.start(cliFilters);
|
|
10485
10012
|
} catch (e) {
|
|
10486
|
-
|
|
10487
|
-
if (e instanceof GitNotFoundError) {
|
|
10488
|
-
ctx.logger.error(e.message);
|
|
10489
|
-
return ctx;
|
|
10490
|
-
}
|
|
10491
|
-
if (e instanceof IncludeTaskLocationDisabledError || e instanceof RangeLocationFilterProvidedError || e instanceof LocationFilterFileNotFoundError) {
|
|
10492
|
-
ctx.logger.printError(e, { verbose: false });
|
|
10493
|
-
return ctx;
|
|
10494
|
-
}
|
|
10495
|
-
process.exitCode = 1;
|
|
10496
|
-
ctx.logger.printError(e, {
|
|
10013
|
+
return e instanceof FilesNotFoundError ? ctx : e instanceof GitNotFoundError ? (ctx.logger.error(e.message), ctx) : e instanceof IncludeTaskLocationDisabledError || e instanceof RangeLocationFilterProvidedError || e instanceof LocationFilterFileNotFoundError ? (ctx.logger.printError(e, { verbose: false }), ctx) : (process.exitCode = 1, ctx.logger.printError(e, {
|
|
10497
10014
|
fullStack: true,
|
|
10498
10015
|
type: "Unhandled Error"
|
|
10499
|
-
});
|
|
10500
|
-
ctx.logger.error("\n\n");
|
|
10501
|
-
return ctx;
|
|
10016
|
+
}), ctx.logger.error("\n\n"), ctx);
|
|
10502
10017
|
}
|
|
10503
|
-
|
|
10504
|
-
stdinCleanup?.();
|
|
10505
|
-
await ctx.close();
|
|
10506
|
-
return ctx;
|
|
10018
|
+
return ctx.shouldKeepServer() ? ctx : (stdinCleanup?.(), await ctx.close(), ctx);
|
|
10507
10019
|
}
|
|
10508
10020
|
async function prepareVitest(mode, options = {}, viteOverrides, vitestOptions, cliFilters) {
|
|
10509
|
-
process.env.TEST = "true";
|
|
10510
|
-
process.env.VITEST = "true";
|
|
10511
|
-
process.env.NODE_ENV ??= "test";
|
|
10512
|
-
if (options.run) options.watch = false;
|
|
10021
|
+
if (process.env.TEST = "true", process.env.VITEST = "true", process.env.NODE_ENV ??= "test", options.run) options.watch = false;
|
|
10513
10022
|
if (options.standalone && (cliFilters?.length || 0) > 0) options.standalone = false;
|
|
10514
10023
|
// this shouldn't affect _application root_ that can be changed inside config
|
|
10515
|
-
const root = resolve(options.root || process.cwd());
|
|
10516
|
-
|
|
10517
|
-
const environmentPackage = getEnvPackageName(ctx.config.environment);
|
|
10518
|
-
if (environmentPackage && !await ctx.packageInstaller.ensureInstalled(environmentPackage, root)) {
|
|
10519
|
-
process.exitCode = 1;
|
|
10520
|
-
return ctx;
|
|
10521
|
-
}
|
|
10522
|
-
return ctx;
|
|
10024
|
+
const root = resolve(options.root || process.cwd()), ctx = await createVitest(mode, options, viteOverrides, vitestOptions), environmentPackage = getEnvPackageName(ctx.config.environment);
|
|
10025
|
+
return environmentPackage && !await ctx.packageInstaller.ensureInstalled(environmentPackage, root) && (process.exitCode = 1), ctx;
|
|
10523
10026
|
}
|
|
10524
10027
|
function processCollected(ctx, files, options) {
|
|
10525
10028
|
let errorsPrinted = false;
|
|
10526
|
-
forEachSuite(files, (suite) => {
|
|
10029
|
+
if (forEachSuite(files, (suite) => {
|
|
10527
10030
|
suite.errors().forEach((error) => {
|
|
10528
|
-
errorsPrinted = true;
|
|
10529
|
-
ctx.logger.printError(error, { project: suite.project });
|
|
10031
|
+
errorsPrinted = true, ctx.logger.printError(error, { project: suite.project });
|
|
10530
10032
|
});
|
|
10531
|
-
});
|
|
10532
|
-
if (errorsPrinted) return;
|
|
10533
|
-
if (typeof options.json !== "undefined") return processJsonOutput(files, options);
|
|
10534
|
-
return formatCollectedAsString(files).forEach((test) => console.log(test));
|
|
10033
|
+
}), !errorsPrinted) return typeof options.json === "undefined" ? formatCollectedAsString(files).forEach((test) => console.log(test)) : processJsonOutput(files, options);
|
|
10535
10034
|
}
|
|
10536
10035
|
function outputFileList(files, options) {
|
|
10537
10036
|
if (typeof options.json !== "undefined") return outputJsonFileList(files, options);
|
|
@@ -10541,8 +10040,7 @@ function outputJsonFileList(files, options) {
|
|
|
10541
10040
|
if (typeof options.json === "boolean") return console.log(JSON.stringify(formatFilesAsJSON(files), null, 2));
|
|
10542
10041
|
if (typeof options.json === "string") {
|
|
10543
10042
|
const jsonPath = resolve(options.root || process.cwd(), options.json);
|
|
10544
|
-
mkdirSync(dirname(jsonPath), { recursive: true });
|
|
10545
|
-
writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2));
|
|
10043
|
+
mkdirSync(dirname(jsonPath), { recursive: true }), writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2));
|
|
10546
10044
|
}
|
|
10547
10045
|
}
|
|
10548
10046
|
function formatFilesAsJSON(files) {
|
|
@@ -10563,8 +10061,7 @@ function processJsonOutput(files, options) {
|
|
|
10563
10061
|
if (typeof options.json === "boolean") return console.log(JSON.stringify(formatCollectedAsJSON(files), null, 2));
|
|
10564
10062
|
if (typeof options.json === "string") {
|
|
10565
10063
|
const jsonPath = resolve(options.root || process.cwd(), options.json);
|
|
10566
|
-
mkdirSync(dirname(jsonPath), { recursive: true });
|
|
10567
|
-
writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2));
|
|
10064
|
+
mkdirSync(dirname(jsonPath), { recursive: true }), writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2));
|
|
10568
10065
|
}
|
|
10569
10066
|
}
|
|
10570
10067
|
function forEachSuite(modules, callback) {
|
|
@@ -10575,7 +10072,7 @@ function forEachSuite(modules, callback) {
|
|
|
10575
10072
|
}
|
|
10576
10073
|
function formatCollectedAsJSON(files) {
|
|
10577
10074
|
const results = [];
|
|
10578
|
-
files.forEach((file) => {
|
|
10075
|
+
return files.forEach((file) => {
|
|
10579
10076
|
for (const test of file.children.allTests()) {
|
|
10580
10077
|
if (test.result().state === "skipped") continue;
|
|
10581
10078
|
const result = {
|
|
@@ -10586,19 +10083,17 @@ function formatCollectedAsJSON(files) {
|
|
|
10586
10083
|
if (test.location) result.location = test.location;
|
|
10587
10084
|
results.push(result);
|
|
10588
10085
|
}
|
|
10589
|
-
});
|
|
10590
|
-
return results;
|
|
10086
|
+
}), results;
|
|
10591
10087
|
}
|
|
10592
10088
|
function formatCollectedAsString(testModules) {
|
|
10593
10089
|
const results = [];
|
|
10594
|
-
testModules.forEach((testModule) => {
|
|
10090
|
+
return testModules.forEach((testModule) => {
|
|
10595
10091
|
for (const test of testModule.children.allTests()) {
|
|
10596
10092
|
if (test.result().state === "skipped") continue;
|
|
10597
10093
|
const fullName = `${test.module.task.name} > ${test.fullName}`;
|
|
10598
10094
|
results.push((test.project.name ? `[${test.project.name}] ` : "") + fullName);
|
|
10599
10095
|
}
|
|
10600
|
-
});
|
|
10601
|
-
return results;
|
|
10096
|
+
}), results;
|
|
10602
10097
|
}
|
|
10603
10098
|
const envPackageNames = {
|
|
10604
10099
|
"jsdom": "jsdom",
|
|
@@ -10606,10 +10101,7 @@ const envPackageNames = {
|
|
|
10606
10101
|
"edge-runtime": "@edge-runtime/vm"
|
|
10607
10102
|
};
|
|
10608
10103
|
function getEnvPackageName(env) {
|
|
10609
|
-
|
|
10610
|
-
if (env in envPackageNames) return envPackageNames[env];
|
|
10611
|
-
if (env[0] === "." || isAbsolute(env)) return null;
|
|
10612
|
-
return `vitest-environment-${env}`;
|
|
10104
|
+
return env === "node" ? null : env in envPackageNames ? envPackageNames[env] : env[0] === "." || isAbsolute(env) ? null : `vitest-environment-${env}`;
|
|
10613
10105
|
}
|
|
10614
10106
|
|
|
10615
10107
|
var cliApi = /*#__PURE__*/Object.freeze({
|