vitest 5.0.0-beta.5 → 5.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/dist/browser.d.ts +2 -2
- package/dist/browser.js +2 -2
- package/dist/chunks/{artifact.C0OHWdod.js → artifact.BNnEI1sJ.js} +5 -5
- package/dist/chunks/{base.BPbmtl-C.js → base.BKfXyFN7.js} +7 -7
- package/dist/chunks/{browser.d.B-p-y0sB.d.ts → browser.d.DoM6vBOs.d.ts} +3 -3
- package/dist/chunks/{cac.DYQRhgb-.js → cac.DKrA6qEB.js} +6 -6
- package/dist/chunks/{cli-api.SMst4llK.js → cli-api.cZcvaUFI.js} +280 -76
- package/dist/chunks/{config.d.Bkl6J5iR.d.ts → config.d.CKWK3nld.d.ts} +6 -2
- package/dist/chunks/{coverage.d.Dn6XbyQq.d.ts → coverage.d.CCNrKR65.d.ts} +1 -1
- package/dist/chunks/{creator.CJiHagNv.js → creator.C4nK7Krt.js} +3 -3
- package/dist/chunks/{defaults.CUUnbOrq.js → defaults.B_pFOTYy.js} +1 -1
- package/dist/chunks/{globals.D2wDMk06.js → globals.CzUA1xn8.js} +4 -4
- package/dist/chunks/{index.DugGyGng.js → index.B4UTDegh.js} +3 -3
- package/dist/chunks/{index.CXzZ7KB8.js → index.D6NDM5O1.js} +497 -118
- package/dist/chunks/{index.DzNNaFWy.js → index.DNRmy2jU.js} +22 -7
- package/dist/chunks/{index.6dZyLbho.js → index.Djaij2xr.js} +58 -16
- package/dist/chunks/{init-forks.CDWjf0q6.js → init-forks.BG4bCDny.js} +1 -1
- package/dist/chunks/{init-threads.B-vZ8N2q.js → init-threads.DLtIP5Qq.js} +1 -1
- package/dist/chunks/{init.gslB1aqB.js → init.DTAQFCjl.js} +2 -2
- package/dist/chunks/{nativeModuleMocker.CrcWvO03.js → nativeModuleMocker.BKtCThoO.js} +1 -1
- package/dist/chunks/{plugin.d.BuiCQSo8.d.ts → plugin.d.Bpge8Jye.d.ts} +51 -30
- package/dist/chunks/{rpc.d.BLxNuPAq.d.ts → rpc.d.C6-dGZ2f.d.ts} +1 -1
- package/dist/chunks/{setup-common.DRlwpHsL.js → setup-common.ZNdeu5wa.js} +1 -1
- package/dist/chunks/{task-utils.d.CLWcZaUf.d.ts → task-utils.d.mMDXJF_I.d.ts} +20 -1
- package/dist/chunks/{vm._FqKqltU.js → vm.CeHWcIrU.js} +2 -2
- package/dist/chunks/{worker.d.Cb0Z-SnE.d.ts → worker.d.JES7ffPK.d.ts} +2 -2
- package/dist/cli.js +1 -1
- package/dist/config.cjs +1 -1
- package/dist/config.d.ts +8 -8
- package/dist/config.js +1 -1
- package/dist/index.d.ts +237 -12
- package/dist/index.js +6 -6
- package/dist/module-evaluator.d.ts +2 -2
- package/dist/module-evaluator.js +7 -0
- package/dist/node.d.ts +25 -14
- package/dist/node.js +9 -8
- package/dist/runtime.d.ts +3 -3
- package/dist/runtime.js +2 -2
- package/dist/worker.d.ts +3 -3
- package/dist/worker.js +7 -7
- package/dist/workers/forks.js +8 -8
- package/dist/workers/runVmTests.js +7 -7
- package/dist/workers/threads.js +8 -8
- package/dist/workers/vmForks.js +4 -4
- package/dist/workers/vmThreads.js +4 -4
- package/package.json +17 -17
|
@@ -7,24 +7,25 @@ import { unique, createDefer, slash, cleanUrl, withTrailingSlash, wrapId, isExte
|
|
|
7
7
|
import { i as isPackageExists, r as resolveModule } from './index.CesbTg1C.js';
|
|
8
8
|
import * as vite from 'vite';
|
|
9
9
|
import { parseAst, searchForWorkspaceRoot, fetchModule, version, createServer, isFileLoadingAllowed, normalizePath as normalizePath$1, isRunnableDevEnvironment, mergeConfig } from 'vite';
|
|
10
|
-
import { h as hash, b as resolveCoverageReporters,
|
|
10
|
+
import { h as hash, b as resolveCoverageReporters, A as API_TOKEN_FILE, c as isBrowserEnabled, r as resolveConfig$1, R as RandomSequencer, a as resolveApiServerConfig, f as findConfigFile, p as prompt } from './index.Djaij2xr.js';
|
|
11
11
|
import * as nodeos from 'node:os';
|
|
12
12
|
import nodeos__default, { tmpdir, hostname } from 'node:os';
|
|
13
13
|
import { serializeValue } from '@vitest/utils/serialize';
|
|
14
|
-
import { v as version$1 } from './cac.
|
|
14
|
+
import { v as version$1 } from './cac.DKrA6qEB.js';
|
|
15
15
|
import { distDir, rootDir } from '../path.js';
|
|
16
|
-
import { w as validateTags, x as limitConcurrency, y as createTagsFilter } from './artifact.
|
|
16
|
+
import { w as validateTags, x as limitConcurrency, y as createTagsFilter } from './artifact.BNnEI1sJ.js';
|
|
17
17
|
import { N as NativeModuleRunner } from './nativeModuleRunner.WlMdOB52.js';
|
|
18
18
|
import { createFileTask as createFileTask$1, createTaskName, calculateSuiteHash, convertTasksToEvents, hasFailed, generateFileHash, getTestName, hasFailedSnapshot, getTests, getSuites, getTasks, getFullName, someTasksAreOnly, interpretTaskModes } from '../task-utils.js';
|
|
19
19
|
import { Traces } from '../traces.js';
|
|
20
20
|
import { createDebug } from 'obug';
|
|
21
21
|
import { rm, readFile, writeFile, rename, stat, unlink, mkdir, readdir, copyFile } from 'node:fs/promises';
|
|
22
22
|
import c from 'tinyrainbow';
|
|
23
|
+
import crypto, { createHash } from 'node:crypto';
|
|
23
24
|
import module$1, { createRequire, builtinModules, isBuiltin as isBuiltin$1 } from 'node:module';
|
|
24
25
|
import url, { fileURLToPath, pathToFileURL } from 'node:url';
|
|
25
26
|
import pm from 'picomatch';
|
|
26
27
|
import { glob, isDynamicPattern } from 'tinyglobby';
|
|
27
|
-
import { a as coverageConfigDefaults, c as configDefaults } from './defaults.
|
|
28
|
+
import { a as coverageConfigDefaults, c as configDefaults } from './defaults.B_pFOTYy.js';
|
|
28
29
|
import { VitestModuleEvaluator } from '#module-evaluator';
|
|
29
30
|
import { ModuleRunner } from 'vite/module-runner';
|
|
30
31
|
import { Console } from 'node:console';
|
|
@@ -39,7 +40,6 @@ import { defaultStackIgnorePatterns, parseErrorStacktrace, parseStacktrace } fro
|
|
|
39
40
|
import { t as truncateString, e as errorBanner, F as F_POINTER, d as divider, f as formatProjectName, w as withLabel, a as formatTimeString, b as taskFail, s as separator, c as F_CHECK, g as F_DOWN_RIGHT, h as getStateSymbol, r as renderSnapshotSummary, p as padSummaryTitle, i as getStateString$1, j as formatTime, k as countTestErrors, l as F_TREE_NODE_END, m as F_TREE_NODE_MIDDLE, n as noun, o as F_RIGHT } from './utils.DKODp04v.js';
|
|
40
41
|
import { a as isTTY, b as isWindows, i as isForceColor } from './env.BKKtU2WC.js';
|
|
41
42
|
import { isatty } from 'node:tty';
|
|
42
|
-
import crypto, { createHash } from 'node:crypto';
|
|
43
43
|
import EventEmitter$1, { EventEmitter } from 'node:events';
|
|
44
44
|
import { c as createBirpc } from './index.Chj8NDwU.js';
|
|
45
45
|
import { i as isBuiltin, t as toBuiltin } from './modules.BJuCwlRJ.js';
|
|
@@ -47,7 +47,7 @@ import { fork } from 'node:child_process';
|
|
|
47
47
|
import { Worker } from 'node:worker_threads';
|
|
48
48
|
import require$$0$3 from 'events';
|
|
49
49
|
import require$$1$1 from 'https';
|
|
50
|
-
import require$$2 from 'http';
|
|
50
|
+
import require$$2$1 from 'http';
|
|
51
51
|
import require$$3 from 'net';
|
|
52
52
|
import require$$4 from 'tls';
|
|
53
53
|
import require$$1 from 'crypto';
|
|
@@ -55,6 +55,7 @@ import require$$0$2 from 'stream';
|
|
|
55
55
|
import require$$7 from 'url';
|
|
56
56
|
import require$$0 from 'zlib';
|
|
57
57
|
import require$$0$1 from 'buffer';
|
|
58
|
+
import require$$2 from 'util';
|
|
58
59
|
import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.-juJ8b_4.js';
|
|
59
60
|
import { isAgent } from 'std-env';
|
|
60
61
|
import MagicString from 'magic-string';
|
|
@@ -2117,6 +2118,7 @@ class BaseCoverageProvider {
|
|
|
2117
2118
|
coverageFiles = /* @__PURE__ */ new Map();
|
|
2118
2119
|
pendingPromises = [];
|
|
2119
2120
|
coverageFilesDirectory;
|
|
2121
|
+
reportsDirectoryLock;
|
|
2120
2122
|
roots = [];
|
|
2121
2123
|
changedFiles;
|
|
2122
2124
|
_initialize(ctx) {
|
|
@@ -2142,6 +2144,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
2142
2144
|
const shard = this.ctx.config.shard;
|
|
2143
2145
|
const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
|
|
2144
2146
|
this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory);
|
|
2147
|
+
this.reportsDirectoryLock = new ReportsDirectoryLock(resolve$1(this.options.reportsDirectory));
|
|
2145
2148
|
// If --project filter is set pick only roots of resolved projects
|
|
2146
2149
|
this.roots = ctx.config.project?.length ? [...new Set(ctx.projects.map((project) => project.config.root))] : [ctx.config.root];
|
|
2147
2150
|
}
|
|
@@ -2205,6 +2208,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
2205
2208
|
return this.options;
|
|
2206
2209
|
}
|
|
2207
2210
|
async clean(clean = true) {
|
|
2211
|
+
await this.reportsDirectoryLock.acquire();
|
|
2208
2212
|
if (clean && existsSync(this.options.reportsDirectory)) await promises.rm(this.options.reportsDirectory, {
|
|
2209
2213
|
recursive: true,
|
|
2210
2214
|
force: true,
|
|
@@ -2264,10 +2268,14 @@ Update your dependencies and make sure the versions match.`));
|
|
|
2264
2268
|
}
|
|
2265
2269
|
}
|
|
2266
2270
|
async cleanAfterRun() {
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
+
try {
|
|
2272
|
+
this.coverageFiles = /* @__PURE__ */ new Map();
|
|
2273
|
+
await promises.rm(this.coverageFilesDirectory, { recursive: true });
|
|
2274
|
+
// Remove empty reports directory, e.g. when only text-reporter is used
|
|
2275
|
+
if (readdirSync(this.options.reportsDirectory).length === 0) await promises.rm(this.options.reportsDirectory, { recursive: true });
|
|
2276
|
+
} finally {
|
|
2277
|
+
await this.reportsDirectoryLock.release();
|
|
2278
|
+
}
|
|
2271
2279
|
}
|
|
2272
2280
|
async onTestRunStart() {
|
|
2273
2281
|
if (this.options.changed) try {
|
|
@@ -2615,6 +2623,65 @@ function resolveMergeConfig(mod) {
|
|
|
2615
2623
|
if (config) return config;
|
|
2616
2624
|
}
|
|
2617
2625
|
}
|
|
2626
|
+
class ReportsDirectoryLock {
|
|
2627
|
+
lockFile;
|
|
2628
|
+
constructor(reportsDirectory) {
|
|
2629
|
+
this.reportsDirectory = reportsDirectory;
|
|
2630
|
+
const hash = createHash("sha256").update(reportsDirectory).digest("hex").slice(0, 16);
|
|
2631
|
+
this.lockFile = resolve$1(tmpdir(), `vitest-coverage-${hash}.lock`);
|
|
2632
|
+
}
|
|
2633
|
+
async acquire() {
|
|
2634
|
+
if (await this.tryWrite()) return;
|
|
2635
|
+
const owner = await this.readOwner();
|
|
2636
|
+
// We already hold the lock for this directory (e.g. watch-mode reruns).
|
|
2637
|
+
if (owner?.pid === process.pid) return;
|
|
2638
|
+
// Another running Vitest owns this directory.
|
|
2639
|
+
if (owner && isProcessAlive(owner.pid)) throw this.inUseError(owner);
|
|
2640
|
+
// The lock was left behind by a process that no longer exists. Reclaim it.
|
|
2641
|
+
await promises.rm(this.lockFile, { force: true });
|
|
2642
|
+
if (!await this.tryWrite()) throw this.inUseError(await this.readOwner());
|
|
2643
|
+
}
|
|
2644
|
+
async release() {
|
|
2645
|
+
if ((await this.readOwner())?.pid === process.pid) await promises.rm(this.lockFile, { force: true });
|
|
2646
|
+
}
|
|
2647
|
+
async tryWrite() {
|
|
2648
|
+
const payload = JSON.stringify({
|
|
2649
|
+
pid: process.pid,
|
|
2650
|
+
reportsDirectory: this.reportsDirectory
|
|
2651
|
+
});
|
|
2652
|
+
try {
|
|
2653
|
+
// `wx` fails with EEXIST if the file already exists, so only one process wins.
|
|
2654
|
+
await promises.writeFile(this.lockFile, payload, { flag: "wx" });
|
|
2655
|
+
return true;
|
|
2656
|
+
} catch (error) {
|
|
2657
|
+
if (error.code === "EEXIST") return false;
|
|
2658
|
+
throw error;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
async readOwner() {
|
|
2662
|
+
try {
|
|
2663
|
+
const owner = JSON.parse(await promises.readFile(this.lockFile, "utf-8"));
|
|
2664
|
+
return typeof owner?.pid === "number" ? owner : null;
|
|
2665
|
+
} catch {
|
|
2666
|
+
return null;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
inUseError(owner) {
|
|
2670
|
+
return /* @__PURE__ */ new Error(`The coverage report directory "${this.reportsDirectory}" is already in use by another Vitest process${owner ? ` (pid ${owner.pid})` : ""}. Running coverage for multiple Vitest processes in the same directory at the same time is not supported, because they would delete each other's reports.\nGive each run its own "coverage.reportsDirectory" (e.g. --coverage.reportsDirectory=coverage-${process.pid}) or run them sequentially.`);
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
function isProcessAlive(pid) {
|
|
2674
|
+
try {
|
|
2675
|
+
// Sending signal 0 checks if the process exists without actually killing it:
|
|
2676
|
+
// https://nodejs.org/api/process.html#processkillpid-signal
|
|
2677
|
+
process.kill(pid, 0);
|
|
2678
|
+
return true;
|
|
2679
|
+
} catch (error) {
|
|
2680
|
+
// ESRCH means the process is gone. Treat anything else (e.g. EPERM) as alive
|
|
2681
|
+
// so we never reclaim a lock from a process that is still running.
|
|
2682
|
+
return error.code !== "ESRCH";
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2618
2685
|
|
|
2619
2686
|
// this is copy pasted from vite
|
|
2620
2687
|
function normalizeResolvedIdToUrl(environment, resolvedId) {
|
|
@@ -4297,13 +4364,14 @@ class Logger {
|
|
|
4297
4364
|
const color = this.ctx.config.watch ? "blue" : "cyan";
|
|
4298
4365
|
const mode = this.ctx.config.watch ? "DEV" : "RUN";
|
|
4299
4366
|
this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
|
|
4300
|
-
|
|
4301
|
-
if (
|
|
4367
|
+
const seed = this.ctx.getSeed();
|
|
4368
|
+
if (seed != null) this.log(PAD + c.gray(`Running tests with seed "${seed}"`));
|
|
4302
4369
|
if (this.ctx.config.ui) {
|
|
4303
4370
|
const host = this.ctx.config.api?.host || "localhost";
|
|
4304
4371
|
const port = this.ctx.vite.config.server.port;
|
|
4305
|
-
const
|
|
4306
|
-
|
|
4372
|
+
const url = new URL(this.ctx.config.uiBase, `http://${host}:${port}`);
|
|
4373
|
+
url.searchParams.set("token", this.ctx.config.api.token);
|
|
4374
|
+
this.log(PAD + c.dim(c.green(`UI started at ${url}`)));
|
|
4307
4375
|
} else if (this.ctx.config.api?.port) {
|
|
4308
4376
|
const resolvedUrls = this.ctx.vite.resolvedUrls;
|
|
4309
4377
|
// workaround for https://github.com/vitejs/vite/issues/15438, it was fixed in vite 5.1
|
|
@@ -4632,7 +4700,7 @@ class VitestPackageInstaller {
|
|
|
4632
4700
|
if (/* @__PURE__ */ isPackageExists(dependency, { paths: [root, __dirname$1] })) return true;
|
|
4633
4701
|
process.stderr.write(withLabel("red", "MISSING DEPENDENCY", `Cannot find dependency '${dependency}'\n\n`));
|
|
4634
4702
|
if (!isTTY) return false;
|
|
4635
|
-
const { install } = await (await import('./index.
|
|
4703
|
+
const { install } = await (await import('./index.Djaij2xr.js').then(function (n) { return n.i; })).default({
|
|
4636
4704
|
type: "confirm",
|
|
4637
4705
|
name: "install",
|
|
4638
4706
|
message: c.reset(`Do you want to install ${c.green(dependency)}?`)
|
|
@@ -4744,7 +4812,7 @@ function createBrowserPool(vitest) {
|
|
|
4744
4812
|
vitest.onCancel(() => {
|
|
4745
4813
|
isCancelled = true;
|
|
4746
4814
|
});
|
|
4747
|
-
const initialisedPools = await Promise.all(
|
|
4815
|
+
const initialisedPools = await Promise.all(Array.from(groupedFiles.entries(), async ([project, files]) => {
|
|
4748
4816
|
await project._initBrowserProvider();
|
|
4749
4817
|
if (!project.browser) throw new TypeError(`The browser server was not initialized${project.name ? ` for the "${project.name}" project` : ""}. This is a bug in Vitest. Please, open a new issue with reproduction.`);
|
|
4750
4818
|
if (isCancelled) return;
|
|
@@ -4783,7 +4851,7 @@ function createBrowserPool(vitest) {
|
|
|
4783
4851
|
return {
|
|
4784
4852
|
name: "browser",
|
|
4785
4853
|
async close() {
|
|
4786
|
-
await Promise.all(
|
|
4854
|
+
await Promise.all(Array.from(providers, (provider) => provider.close()));
|
|
4787
4855
|
vitest._browserSessions.sessionIds.clear();
|
|
4788
4856
|
providers.clear();
|
|
4789
4857
|
vitest.projects.forEach((project) => {
|
|
@@ -5126,6 +5194,7 @@ class PoolRunner {
|
|
|
5126
5194
|
poolId = void 0;
|
|
5127
5195
|
project;
|
|
5128
5196
|
environment;
|
|
5197
|
+
_lastTestFiles;
|
|
5129
5198
|
_state = RunnerState.IDLE;
|
|
5130
5199
|
_operationLock = null;
|
|
5131
5200
|
_terminatePromise = createDefer();
|
|
@@ -5148,6 +5217,7 @@ class PoolRunner {
|
|
|
5148
5217
|
this.project = options.project;
|
|
5149
5218
|
this.environment = options.environment;
|
|
5150
5219
|
const vitest = this.project.vitest;
|
|
5220
|
+
this._lastTestFiles = [];
|
|
5151
5221
|
this._traces = vitest._traces;
|
|
5152
5222
|
if (this._traces.isEnabled()) {
|
|
5153
5223
|
const { span: workerSpan, context } = this._traces.startContextSpan("vitest.worker");
|
|
@@ -5201,7 +5271,8 @@ class PoolRunner {
|
|
|
5201
5271
|
return span;
|
|
5202
5272
|
}
|
|
5203
5273
|
request(method, context) {
|
|
5204
|
-
this.
|
|
5274
|
+
this._lastTestFiles = context.files.map((f) => f.filepath);
|
|
5275
|
+
this._otel?.files.push(...this._lastTestFiles);
|
|
5205
5276
|
return this.postMessage({
|
|
5206
5277
|
__vitest_worker_request__: true,
|
|
5207
5278
|
type: method,
|
|
@@ -5321,6 +5392,7 @@ class PoolRunner {
|
|
|
5321
5392
|
this._state = RunnerState.STOPPED;
|
|
5322
5393
|
throw error;
|
|
5323
5394
|
} finally {
|
|
5395
|
+
this._lastTestFiles = [];
|
|
5324
5396
|
this._operationLock.resolve();
|
|
5325
5397
|
this._operationLock = null;
|
|
5326
5398
|
this._otel?.span.end();
|
|
@@ -5346,21 +5418,36 @@ class PoolRunner {
|
|
|
5346
5418
|
this._eventEmitter.emit("error", error);
|
|
5347
5419
|
}
|
|
5348
5420
|
};
|
|
5349
|
-
emitUnexpectedExit = () => {
|
|
5350
|
-
const
|
|
5421
|
+
emitUnexpectedExit = (code, signal) => {
|
|
5422
|
+
const hasCode = typeof code === "number";
|
|
5423
|
+
const errorDetails = hasCode || signal ? `with ${hasCode ? `exit code ${code} ` : ""}${signal ? `signal ${signal} ` : ""}` : "";
|
|
5424
|
+
const testFileDetails = this._lastTestFiles.length ? ` while running test file${this._lastTestFiles.length === 1 ? "" : "s"} ${this._lastTestFiles.join(", ")}` : "";
|
|
5425
|
+
const error = /* @__PURE__ */ new Error(`Worker exited unexpectedly ${errorDetails}during ${this._state} state${testFileDetails}`);
|
|
5351
5426
|
this._state = RunnerState.STOPPED;
|
|
5352
5427
|
this._eventEmitter.emit("error", error);
|
|
5353
5428
|
};
|
|
5354
5429
|
waitForStart() {
|
|
5355
5430
|
return new Promise((resolve, reject) => {
|
|
5356
|
-
const
|
|
5431
|
+
const cleanup = () => {
|
|
5432
|
+
this.off("message", onStart);
|
|
5433
|
+
this.off("error", onError);
|
|
5434
|
+
};
|
|
5435
|
+
function onStart(message) {
|
|
5357
5436
|
if (message.type === "started") {
|
|
5358
|
-
|
|
5437
|
+
cleanup();
|
|
5359
5438
|
if (message.error) reject(message.error);
|
|
5360
5439
|
else resolve();
|
|
5361
5440
|
}
|
|
5362
|
-
}
|
|
5441
|
+
}
|
|
5442
|
+
// The worker can die before it ever reports back (e.g. an invalid
|
|
5443
|
+
// `execArgv` makes Node exit immediately). Reject as soon as that
|
|
5444
|
+
// happens instead of waiting for the start timeout to elapse.
|
|
5445
|
+
function onError(error) {
|
|
5446
|
+
cleanup();
|
|
5447
|
+
reject(error);
|
|
5448
|
+
}
|
|
5363
5449
|
this.on("message", onStart);
|
|
5450
|
+
this.on("error", onError);
|
|
5364
5451
|
});
|
|
5365
5452
|
}
|
|
5366
5453
|
withTimeout(promise, timeout) {
|
|
@@ -5924,7 +6011,7 @@ function deepEqual$1(obj1, obj2) {
|
|
|
5924
6011
|
const keys1 = Object.keys(obj1);
|
|
5925
6012
|
const keys2 = Object.keys(obj2);
|
|
5926
6013
|
if (keys1.length !== keys2.length) return false;
|
|
5927
|
-
for (const key of keys1) if (!Object.
|
|
6014
|
+
for (const key of keys1) if (!Object.hasOwn(obj2, key) || !deepEqual$1(obj1[key], obj2[key])) return false;
|
|
5928
6015
|
return true;
|
|
5929
6016
|
}
|
|
5930
6017
|
|
|
@@ -6450,6 +6537,9 @@ function requirePermessageDeflate () {
|
|
|
6450
6537
|
* acknowledge disabling of client context takeover
|
|
6451
6538
|
* @param {Number} [options.concurrencyLimit=10] The number of concurrent
|
|
6452
6539
|
* calls to zlib
|
|
6540
|
+
* @param {Boolean} [options.isServer=false] Create the instance in either
|
|
6541
|
+
* server or client mode
|
|
6542
|
+
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
|
6453
6543
|
* @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
|
|
6454
6544
|
* use of a custom server window size
|
|
6455
6545
|
* @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
|
|
@@ -6460,16 +6550,13 @@ function requirePermessageDeflate () {
|
|
|
6460
6550
|
* deflate
|
|
6461
6551
|
* @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
|
|
6462
6552
|
* inflate
|
|
6463
|
-
* @param {Boolean} [isServer=false] Create the instance in either server or
|
|
6464
|
-
* client mode
|
|
6465
|
-
* @param {Number} [maxPayload=0] The maximum allowed message length
|
|
6466
6553
|
*/
|
|
6467
|
-
constructor(options
|
|
6468
|
-
this._maxPayload = maxPayload | 0;
|
|
6554
|
+
constructor(options) {
|
|
6469
6555
|
this._options = options || {};
|
|
6470
6556
|
this._threshold =
|
|
6471
6557
|
this._options.threshold !== undefined ? this._options.threshold : 1024;
|
|
6472
|
-
this.
|
|
6558
|
+
this._maxPayload = this._options.maxPayload | 0;
|
|
6559
|
+
this._isServer = !!this._options.isServer;
|
|
6473
6560
|
this._deflate = null;
|
|
6474
6561
|
this._inflate = null;
|
|
6475
6562
|
|
|
@@ -7150,6 +7237,10 @@ function requireReceiver () {
|
|
|
7150
7237
|
* extensions
|
|
7151
7238
|
* @param {Boolean} [options.isServer=false] Specifies whether to operate in
|
|
7152
7239
|
* client or server mode
|
|
7240
|
+
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
|
|
7241
|
+
* buffered data chunks
|
|
7242
|
+
* @param {Number} [options.maxFragments=0] The maximum number of message
|
|
7243
|
+
* fragments
|
|
7153
7244
|
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
|
7154
7245
|
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
7155
7246
|
* not to skip UTF-8 validation for text and close messages
|
|
@@ -7164,6 +7255,8 @@ function requireReceiver () {
|
|
|
7164
7255
|
this._binaryType = options.binaryType || BINARY_TYPES[0];
|
|
7165
7256
|
this._extensions = options.extensions || {};
|
|
7166
7257
|
this._isServer = !!options.isServer;
|
|
7258
|
+
this._maxBufferedChunks = options.maxBufferedChunks | 0;
|
|
7259
|
+
this._maxFragments = options.maxFragments | 0;
|
|
7167
7260
|
this._maxPayload = options.maxPayload | 0;
|
|
7168
7261
|
this._skipUTF8Validation = !!options.skipUTF8Validation;
|
|
7169
7262
|
this[kWebSocket] = undefined;
|
|
@@ -7199,6 +7292,22 @@ function requireReceiver () {
|
|
|
7199
7292
|
_write(chunk, encoding, cb) {
|
|
7200
7293
|
if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
|
|
7201
7294
|
|
|
7295
|
+
if (
|
|
7296
|
+
this._maxBufferedChunks > 0 &&
|
|
7297
|
+
this._buffers.length >= this._maxBufferedChunks
|
|
7298
|
+
) {
|
|
7299
|
+
cb(
|
|
7300
|
+
this.createError(
|
|
7301
|
+
RangeError,
|
|
7302
|
+
'Too many buffered chunks',
|
|
7303
|
+
false,
|
|
7304
|
+
1008,
|
|
7305
|
+
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
|
7306
|
+
)
|
|
7307
|
+
);
|
|
7308
|
+
return;
|
|
7309
|
+
}
|
|
7310
|
+
|
|
7202
7311
|
this._bufferedBytes += chunk.length;
|
|
7203
7312
|
this._buffers.push(chunk);
|
|
7204
7313
|
this.startLoop(cb);
|
|
@@ -7595,6 +7704,22 @@ function requireReceiver () {
|
|
|
7595
7704
|
}
|
|
7596
7705
|
|
|
7597
7706
|
if (data.length) {
|
|
7707
|
+
if (
|
|
7708
|
+
this._maxFragments > 0 &&
|
|
7709
|
+
this._fragments.length >= this._maxFragments
|
|
7710
|
+
) {
|
|
7711
|
+
const error = this.createError(
|
|
7712
|
+
RangeError,
|
|
7713
|
+
'Too many message fragments',
|
|
7714
|
+
false,
|
|
7715
|
+
1008,
|
|
7716
|
+
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
|
7717
|
+
);
|
|
7718
|
+
|
|
7719
|
+
cb(error);
|
|
7720
|
+
return;
|
|
7721
|
+
}
|
|
7722
|
+
|
|
7598
7723
|
//
|
|
7599
7724
|
// This message is not compressed so its length is the sum of the payload
|
|
7600
7725
|
// length of all fragments.
|
|
@@ -7634,6 +7759,22 @@ function requireReceiver () {
|
|
|
7634
7759
|
return;
|
|
7635
7760
|
}
|
|
7636
7761
|
|
|
7762
|
+
if (
|
|
7763
|
+
this._maxFragments > 0 &&
|
|
7764
|
+
this._fragments.length >= this._maxFragments
|
|
7765
|
+
) {
|
|
7766
|
+
const error = this.createError(
|
|
7767
|
+
RangeError,
|
|
7768
|
+
'Too many message fragments',
|
|
7769
|
+
false,
|
|
7770
|
+
1008,
|
|
7771
|
+
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
|
7772
|
+
);
|
|
7773
|
+
|
|
7774
|
+
cb(error);
|
|
7775
|
+
return;
|
|
7776
|
+
}
|
|
7777
|
+
|
|
7637
7778
|
this._fragments.push(buf);
|
|
7638
7779
|
}
|
|
7639
7780
|
|
|
@@ -7828,6 +7969,9 @@ function requireSender () {
|
|
|
7828
7969
|
|
|
7829
7970
|
const { Duplex } = require$$0$2;
|
|
7830
7971
|
const { randomFillSync } = require$$1;
|
|
7972
|
+
const {
|
|
7973
|
+
types: { isUint8Array }
|
|
7974
|
+
} = require$$2;
|
|
7831
7975
|
|
|
7832
7976
|
const PerMessageDeflate = requirePermessageDeflate();
|
|
7833
7977
|
const { EMPTY_BUFFER, kWebSocket, NOOP } = requireConstants();
|
|
@@ -8024,8 +8168,10 @@ function requireSender () {
|
|
|
8024
8168
|
|
|
8025
8169
|
if (typeof data === 'string') {
|
|
8026
8170
|
buf.write(data, 2);
|
|
8027
|
-
} else {
|
|
8171
|
+
} else if (isUint8Array(data)) {
|
|
8028
8172
|
buf.set(data, 2);
|
|
8173
|
+
} else {
|
|
8174
|
+
throw new TypeError('Second argument must be a string or a Uint8Array');
|
|
8029
8175
|
}
|
|
8030
8176
|
}
|
|
8031
8177
|
|
|
@@ -8949,7 +9095,7 @@ function requireWebsocket () {
|
|
|
8949
9095
|
|
|
8950
9096
|
const EventEmitter = require$$0$3;
|
|
8951
9097
|
const https = require$$1$1;
|
|
8952
|
-
const http = require$$2;
|
|
9098
|
+
const http = require$$2$1;
|
|
8953
9099
|
const net = require$$3;
|
|
8954
9100
|
const tls = require$$4;
|
|
8955
9101
|
const { randomBytes, createHash } = require$$1;
|
|
@@ -9146,6 +9292,10 @@ function requireWebsocket () {
|
|
|
9146
9292
|
* multiple times in the same tick
|
|
9147
9293
|
* @param {Function} [options.generateMask] The function used to generate the
|
|
9148
9294
|
* masking key
|
|
9295
|
+
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
|
|
9296
|
+
* buffered data chunks
|
|
9297
|
+
* @param {Number} [options.maxFragments=0] The maximum number of message
|
|
9298
|
+
* fragments
|
|
9149
9299
|
* @param {Number} [options.maxPayload=0] The maximum allowed message size
|
|
9150
9300
|
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
9151
9301
|
* not to skip UTF-8 validation for text and close messages
|
|
@@ -9157,6 +9307,8 @@ function requireWebsocket () {
|
|
|
9157
9307
|
binaryType: this.binaryType,
|
|
9158
9308
|
extensions: this._extensions,
|
|
9159
9309
|
isServer: this._isServer,
|
|
9310
|
+
maxBufferedChunks: options.maxBufferedChunks,
|
|
9311
|
+
maxFragments: options.maxFragments,
|
|
9160
9312
|
maxPayload: options.maxPayload,
|
|
9161
9313
|
skipUTF8Validation: options.skipUTF8Validation
|
|
9162
9314
|
});
|
|
@@ -9585,6 +9737,10 @@ function requireWebsocket () {
|
|
|
9585
9737
|
* masking key
|
|
9586
9738
|
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
|
|
9587
9739
|
* handshake request
|
|
9740
|
+
* @param {Number} [options.maxBufferedChunks=1048576] The maximum number of
|
|
9741
|
+
* buffered data chunks
|
|
9742
|
+
* @param {Number} [options.maxFragments=131072] The maximum number of message
|
|
9743
|
+
* fragments
|
|
9588
9744
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
9589
9745
|
* size
|
|
9590
9746
|
* @param {Number} [options.maxRedirects=10] The maximum number of redirects
|
|
@@ -9605,6 +9761,8 @@ function requireWebsocket () {
|
|
|
9605
9761
|
autoPong: true,
|
|
9606
9762
|
closeTimeout: CLOSE_TIMEOUT,
|
|
9607
9763
|
protocolVersion: protocolVersions[1],
|
|
9764
|
+
maxBufferedChunks: 1024 * 1024,
|
|
9765
|
+
maxFragments: 128 * 1024,
|
|
9608
9766
|
maxPayload: 100 * 1024 * 1024,
|
|
9609
9767
|
skipUTF8Validation: false,
|
|
9610
9768
|
perMessageDeflate: true,
|
|
@@ -9638,7 +9796,7 @@ function requireWebsocket () {
|
|
|
9638
9796
|
} else {
|
|
9639
9797
|
try {
|
|
9640
9798
|
parsedUrl = new URL(address);
|
|
9641
|
-
} catch
|
|
9799
|
+
} catch {
|
|
9642
9800
|
throw new SyntaxError(`Invalid URL: ${address}`);
|
|
9643
9801
|
}
|
|
9644
9802
|
}
|
|
@@ -9700,11 +9858,11 @@ function requireWebsocket () {
|
|
|
9700
9858
|
opts.timeout = opts.handshakeTimeout;
|
|
9701
9859
|
|
|
9702
9860
|
if (opts.perMessageDeflate) {
|
|
9703
|
-
perMessageDeflate = new PerMessageDeflate(
|
|
9704
|
-
opts.perMessageDeflate
|
|
9705
|
-
false,
|
|
9706
|
-
opts.maxPayload
|
|
9707
|
-
);
|
|
9861
|
+
perMessageDeflate = new PerMessageDeflate({
|
|
9862
|
+
...opts.perMessageDeflate,
|
|
9863
|
+
isServer: false,
|
|
9864
|
+
maxPayload: opts.maxPayload
|
|
9865
|
+
});
|
|
9708
9866
|
opts.headers['Sec-WebSocket-Extensions'] = format({
|
|
9709
9867
|
[PerMessageDeflate.extensionName]: perMessageDeflate.offer()
|
|
9710
9868
|
});
|
|
@@ -9962,6 +10120,8 @@ function requireWebsocket () {
|
|
|
9962
10120
|
websocket.setSocket(socket, head, {
|
|
9963
10121
|
allowSynchronousEvents: opts.allowSynchronousEvents,
|
|
9964
10122
|
generateMask: opts.generateMask,
|
|
10123
|
+
maxBufferedChunks: opts.maxBufferedChunks,
|
|
10124
|
+
maxFragments: opts.maxFragments,
|
|
9965
10125
|
maxPayload: opts.maxPayload,
|
|
9966
10126
|
skipUTF8Validation: opts.skipUTF8Validation
|
|
9967
10127
|
});
|
|
@@ -10511,12 +10671,14 @@ function requireStream () {
|
|
|
10511
10671
|
|
|
10512
10672
|
requireStream();
|
|
10513
10673
|
|
|
10674
|
+
requireExtension();
|
|
10675
|
+
|
|
10676
|
+
requirePermessageDeflate();
|
|
10677
|
+
|
|
10514
10678
|
requireReceiver();
|
|
10515
10679
|
|
|
10516
10680
|
requireSender();
|
|
10517
10681
|
|
|
10518
|
-
requireWebsocket();
|
|
10519
|
-
|
|
10520
10682
|
var subprotocol;
|
|
10521
10683
|
var hasRequiredSubprotocol;
|
|
10522
10684
|
|
|
@@ -10587,6 +10749,10 @@ function requireSubprotocol () {
|
|
|
10587
10749
|
return subprotocol;
|
|
10588
10750
|
}
|
|
10589
10751
|
|
|
10752
|
+
requireSubprotocol();
|
|
10753
|
+
|
|
10754
|
+
requireWebsocket();
|
|
10755
|
+
|
|
10590
10756
|
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$", "caughtErrors": "none" }] */
|
|
10591
10757
|
|
|
10592
10758
|
var websocketServer;
|
|
@@ -10597,7 +10763,7 @@ function requireWebsocketServer () {
|
|
|
10597
10763
|
hasRequiredWebsocketServer = 1;
|
|
10598
10764
|
|
|
10599
10765
|
const EventEmitter = require$$0$3;
|
|
10600
|
-
const http = require$$2;
|
|
10766
|
+
const http = require$$2$1;
|
|
10601
10767
|
const { Duplex } = require$$0$2;
|
|
10602
10768
|
const { createHash } = require$$1;
|
|
10603
10769
|
|
|
@@ -10637,6 +10803,10 @@ function requireWebsocketServer () {
|
|
|
10637
10803
|
* called
|
|
10638
10804
|
* @param {Function} [options.handleProtocols] A hook to handle protocols
|
|
10639
10805
|
* @param {String} [options.host] The hostname where to bind the server
|
|
10806
|
+
* @param {Number} [options.maxBufferedChunks=1048576] The maximum number of
|
|
10807
|
+
* buffered data chunks
|
|
10808
|
+
* @param {Number} [options.maxFragments=131072] The maximum number of message
|
|
10809
|
+
* fragments
|
|
10640
10810
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
10641
10811
|
* size
|
|
10642
10812
|
* @param {Boolean} [options.noServer=false] Enable no server mode
|
|
@@ -10659,6 +10829,8 @@ function requireWebsocketServer () {
|
|
|
10659
10829
|
options = {
|
|
10660
10830
|
allowSynchronousEvents: true,
|
|
10661
10831
|
autoPong: true,
|
|
10832
|
+
maxBufferedChunks: 1024 * 1024,
|
|
10833
|
+
maxFragments: 128 * 1024,
|
|
10662
10834
|
maxPayload: 100 * 1024 * 1024,
|
|
10663
10835
|
skipUTF8Validation: false,
|
|
10664
10836
|
perMessageDeflate: false,
|
|
@@ -10887,11 +11059,11 @@ function requireWebsocketServer () {
|
|
|
10887
11059
|
this.options.perMessageDeflate &&
|
|
10888
11060
|
secWebSocketExtensions !== undefined
|
|
10889
11061
|
) {
|
|
10890
|
-
const perMessageDeflate = new PerMessageDeflate(
|
|
10891
|
-
this.options.perMessageDeflate,
|
|
10892
|
-
true,
|
|
10893
|
-
this.options.maxPayload
|
|
10894
|
-
);
|
|
11062
|
+
const perMessageDeflate = new PerMessageDeflate({
|
|
11063
|
+
...this.options.perMessageDeflate,
|
|
11064
|
+
isServer: true,
|
|
11065
|
+
maxPayload: this.options.maxPayload
|
|
11066
|
+
});
|
|
10895
11067
|
|
|
10896
11068
|
try {
|
|
10897
11069
|
const offers = extension.parse(secWebSocketExtensions);
|
|
@@ -11018,6 +11190,8 @@ function requireWebsocketServer () {
|
|
|
11018
11190
|
|
|
11019
11191
|
ws.setSocket(socket, head, {
|
|
11020
11192
|
allowSynchronousEvents: this.options.allowSynchronousEvents,
|
|
11193
|
+
maxBufferedChunks: this.options.maxBufferedChunks,
|
|
11194
|
+
maxFragments: this.options.maxFragments,
|
|
11021
11195
|
maxPayload: this.options.maxPayload,
|
|
11022
11196
|
skipUTF8Validation: this.options.skipUTF8Validation
|
|
11023
11197
|
});
|
|
@@ -11629,11 +11803,11 @@ function serializeConfig(project) {
|
|
|
11629
11803
|
expand: config.snapshotOptions.expand ?? globalConfig.snapshotOptions.expand
|
|
11630
11804
|
},
|
|
11631
11805
|
sequence: {
|
|
11632
|
-
shuffle:
|
|
11633
|
-
concurrent:
|
|
11806
|
+
shuffle: config.sequence.shuffle,
|
|
11807
|
+
concurrent: config.sequence.concurrent,
|
|
11634
11808
|
seed: globalConfig.sequence.seed,
|
|
11635
|
-
hooks:
|
|
11636
|
-
setupFiles:
|
|
11809
|
+
hooks: config.sequence.hooks,
|
|
11810
|
+
setupFiles: config.sequence.setupFiles
|
|
11637
11811
|
},
|
|
11638
11812
|
inspect: globalConfig.inspect,
|
|
11639
11813
|
inspectBrk: globalConfig.inspectBrk,
|
|
@@ -12797,7 +12971,10 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
12797
12971
|
ws: false,
|
|
12798
12972
|
preTransformRequests: false,
|
|
12799
12973
|
middlewareMode: true,
|
|
12800
|
-
fs: {
|
|
12974
|
+
fs: {
|
|
12975
|
+
allow: resolveFsAllow(project.vitest.config.root, project.vitest.vite.config.configFile),
|
|
12976
|
+
deny: [API_TOKEN_FILE]
|
|
12977
|
+
}
|
|
12801
12978
|
},
|
|
12802
12979
|
environments: { ssr: { resolve: resolveOptions } },
|
|
12803
12980
|
test: {}
|
|
@@ -12911,7 +13088,7 @@ const defaultInline = [
|
|
|
12911
13088
|
];
|
|
12912
13089
|
const depsExternal = [/\/node_modules\/.*\.cjs\.js$/, /\/node_modules\/.*\.mjs$/];
|
|
12913
13090
|
function guessCJSversion(id) {
|
|
12914
|
-
if (
|
|
13091
|
+
if (ESM_EXT_RE.test(id)) {
|
|
12915
13092
|
for (const i of [
|
|
12916
13093
|
id.replace(ESM_EXT_RE, ".mjs"),
|
|
12917
13094
|
id.replace(ESM_EXT_RE, ".umd.js"),
|
|
@@ -12919,7 +13096,7 @@ function guessCJSversion(id) {
|
|
|
12919
13096
|
id.replace(ESM_EXT_RE, ".js")
|
|
12920
13097
|
]) if (existsSync(i)) return i;
|
|
12921
13098
|
}
|
|
12922
|
-
if (
|
|
13099
|
+
if (ESM_FOLDER_RE.test(id)) {
|
|
12923
13100
|
for (const i of [
|
|
12924
13101
|
id.replace(ESM_FOLDER_RE, "/umd/$1"),
|
|
12925
13102
|
id.replace(ESM_FOLDER_RE, "/cjs/$1"),
|
|
@@ -14313,7 +14490,7 @@ class BaseReporter {
|
|
|
14313
14490
|
getFullName(test, separator) {
|
|
14314
14491
|
if (test === test.file) return test.name;
|
|
14315
14492
|
let name = test.file.name;
|
|
14316
|
-
if (test.location) name += c.dim(`:${test.location.line}
|
|
14493
|
+
if (test.location) name += c.dim(`:${test.location.line}`);
|
|
14317
14494
|
name += separator;
|
|
14318
14495
|
name += getTestName(test, separator);
|
|
14319
14496
|
return name;
|
|
@@ -14744,7 +14921,7 @@ function deepEqual(a, b) {
|
|
|
14744
14921
|
const keysA = Object.keys(a);
|
|
14745
14922
|
const keysB = Object.keys(b);
|
|
14746
14923
|
if (keysA.length !== keysB.length) return false;
|
|
14747
|
-
for (const key of keysA) if (!Object.
|
|
14924
|
+
for (const key of keysA) if (!Object.hasOwn(b, key) || !deepEqual(a[key], b[key])) return false;
|
|
14748
14925
|
return true;
|
|
14749
14926
|
}
|
|
14750
14927
|
function sum(items, cb) {
|
|
@@ -15673,22 +15850,20 @@ class JsonReporter {
|
|
|
15673
15850
|
testResults,
|
|
15674
15851
|
coverageMap: this.coverageMap
|
|
15675
15852
|
};
|
|
15676
|
-
|
|
15677
|
-
}
|
|
15678
|
-
/**
|
|
15679
|
-
* Writes the report to an output file if specified in the config,
|
|
15680
|
-
* or logs it to the console otherwise.
|
|
15681
|
-
* @param report
|
|
15682
|
-
*/
|
|
15683
|
-
async writeReport(report) {
|
|
15853
|
+
const resultString = JSON.stringify(result);
|
|
15684
15854
|
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "json");
|
|
15685
15855
|
if (outputFile) {
|
|
15686
15856
|
const reportFile = resolve$1(this.ctx.config.root, outputFile);
|
|
15687
15857
|
const outputDirectory = dirname(reportFile);
|
|
15688
15858
|
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
15689
|
-
await promises.writeFile(reportFile,
|
|
15859
|
+
await promises.writeFile(reportFile, resultString, "utf-8");
|
|
15690
15860
|
this.ctx.logger.log(`JSON report written to ${reportFile}`);
|
|
15691
|
-
} else this.ctx.logger.log(
|
|
15861
|
+
} else if (this.options.stdout) this.ctx.logger.log(resultString);
|
|
15862
|
+
else {
|
|
15863
|
+
const report = this.ctx.createReport("json");
|
|
15864
|
+
await report.writeFile("output.json", resultString);
|
|
15865
|
+
this.ctx.logger.log(`JSON report written to ${resolve$1(report.root, "output.json")}`);
|
|
15866
|
+
}
|
|
15692
15867
|
}
|
|
15693
15868
|
}
|
|
15694
15869
|
|
|
@@ -15772,6 +15947,8 @@ class JUnitReporter {
|
|
|
15772
15947
|
this.reportFile = resolve$1(this.ctx.config.root, outputFile);
|
|
15773
15948
|
const outputDirectory = dirname(this.reportFile);
|
|
15774
15949
|
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
15950
|
+
} else if (!this.options.stdout) this.reportFile = resolve$1(this.ctx.createReport("junit").root, "output.xml");
|
|
15951
|
+
if (this.reportFile) {
|
|
15775
15952
|
this.fileFd = await promises.open(this.reportFile, "w+");
|
|
15776
15953
|
this.baseLog = async (text) => {
|
|
15777
15954
|
if (!this.fileFd) this.fileFd = await promises.open(this.reportFile, "w+");
|
|
@@ -16151,7 +16328,7 @@ class VerboseReporter extends DefaultReporter {
|
|
|
16151
16328
|
if (this.ctx.config.hideSkippedTests && testResult.state === "skipped" && test.options.mode !== "todo") return;
|
|
16152
16329
|
let title = ` ${this.getEntityPrefix(test)} `;
|
|
16153
16330
|
title += test.module.task.name;
|
|
16154
|
-
if (test.location) title += c.dim(`:${test.location.line}
|
|
16331
|
+
if (test.location) title += c.dim(`:${test.location.line}`);
|
|
16155
16332
|
title += separator;
|
|
16156
16333
|
title += getTestName(test.task, separator);
|
|
16157
16334
|
title += this.getTestCaseSuffix(test);
|
|
@@ -16215,11 +16392,11 @@ function parseFilter(filter) {
|
|
|
16215
16392
|
const colonIndex = filter.lastIndexOf(":");
|
|
16216
16393
|
if (colonIndex === -1) return { filename: filter };
|
|
16217
16394
|
const [parsedFilename, lineNumber] = [filter.substring(0, colonIndex), filter.substring(colonIndex + 1)];
|
|
16218
|
-
if (
|
|
16395
|
+
if (/^\d+$/.test(lineNumber)) return {
|
|
16219
16396
|
filename: parsedFilename,
|
|
16220
16397
|
lineNumber: Number.parseInt(lineNumber)
|
|
16221
16398
|
};
|
|
16222
|
-
else if (
|
|
16399
|
+
else if (/^\d+-\d+$/.test(lineNumber)) throw new RangeLocationFilterProvidedError(filter);
|
|
16223
16400
|
else return { filename: filter };
|
|
16224
16401
|
}
|
|
16225
16402
|
function groupFilters(filters) {
|
|
@@ -16647,7 +16824,7 @@ class TestSuite extends SuiteImplementation {
|
|
|
16647
16824
|
*/
|
|
16648
16825
|
toTestSpecification() {
|
|
16649
16826
|
const isTypecheck = this.task.meta.typecheck === true;
|
|
16650
|
-
const testIds =
|
|
16827
|
+
const testIds = Array.from(this.children.allTests(), (test) => test.id);
|
|
16651
16828
|
return this.project.createSpecification(this.module.moduleId, { testIds }, isTypecheck ? "typecheck" : void 0);
|
|
16652
16829
|
}
|
|
16653
16830
|
/**
|
|
@@ -18219,7 +18396,7 @@ class Vitest {
|
|
|
18219
18396
|
* Returns the seed, if tests are running in a random order.
|
|
18220
18397
|
*/
|
|
18221
18398
|
getSeed() {
|
|
18222
|
-
return this.config.sequence.seed
|
|
18399
|
+
return this.config.sequence.sequencer === RandomSequencer || !!this.config.sequence.shuffle || this.projects.some((p) => !!p.config.sequence.shuffle) ? this.config.sequence.seed : null;
|
|
18223
18400
|
}
|
|
18224
18401
|
/** @internal */
|
|
18225
18402
|
async _reportFileTask(file) {
|
|
@@ -18582,7 +18759,7 @@ class Vitest {
|
|
|
18582
18759
|
*/
|
|
18583
18760
|
async cancelCurrentRun(reason) {
|
|
18584
18761
|
this.isCancelling = true;
|
|
18585
|
-
this.cancelPromise = Promise.all(
|
|
18762
|
+
this.cancelPromise = Promise.all(Array.from(this._onCancelListeners, (listener) => listener(reason)));
|
|
18586
18763
|
await this.cancelPromise.finally(() => this.cancelPromise = void 0);
|
|
18587
18764
|
await this.runningPromise;
|
|
18588
18765
|
}
|
|
@@ -18950,8 +19127,6 @@ async function VitestPlugin(options = {}, vitest = new Vitest(deepClone(options)
|
|
|
18950
19127
|
const defines = deleteDefineConfig(viteConfig);
|
|
18951
19128
|
options.defines = defines;
|
|
18952
19129
|
options.viteDefine = originalDefine;
|
|
18953
|
-
let open = false;
|
|
18954
|
-
if (testConfig.ui && testConfig.open) open = testConfig.uiBase ?? "/__vitest__/";
|
|
18955
19130
|
const resolveOptions = getDefaultResolveOptions();
|
|
18956
19131
|
let config = {
|
|
18957
19132
|
base: "/",
|
|
@@ -18963,11 +19138,14 @@ async function VitestPlugin(options = {}, vitest = new Vitest(deepClone(options)
|
|
|
18963
19138
|
},
|
|
18964
19139
|
server: {
|
|
18965
19140
|
...testConfig.api,
|
|
18966
|
-
open,
|
|
19141
|
+
open: false,
|
|
18967
19142
|
hmr: false,
|
|
18968
19143
|
ws: testConfig.api?.middlewareMode ? false : void 0,
|
|
18969
19144
|
preTransformRequests: false,
|
|
18970
|
-
fs: {
|
|
19145
|
+
fs: {
|
|
19146
|
+
allow: resolveFsAllow(options.root || process.cwd(), testConfig.config),
|
|
19147
|
+
deny: [API_TOKEN_FILE]
|
|
19148
|
+
}
|
|
18971
19149
|
},
|
|
18972
19150
|
build: {
|
|
18973
19151
|
outDir: "dummy-non-existing-folder",
|
|
@@ -19093,7 +19271,33 @@ async function createVitest(modeOrOptions, optionsOrViteOverrides = {}, viteOver
|
|
|
19093
19271
|
};
|
|
19094
19272
|
try {
|
|
19095
19273
|
const server = await createViteServer(mergeConfig(config, mergeConfig(viteOverrides, { root: options.root })));
|
|
19096
|
-
if (ctx.config.api?.port)
|
|
19274
|
+
if (ctx.config.api?.port) {
|
|
19275
|
+
await server.listen();
|
|
19276
|
+
if (ctx.config.ui && ctx.config.open) {
|
|
19277
|
+
// Note: `tokenCreated` is only an approximation of "the browser is not
|
|
19278
|
+
// authenticated yet". If the user clears cookies while the token file
|
|
19279
|
+
// persists, the clean URL will block until they re-open the `?token=`
|
|
19280
|
+
// URL printed in the terminal.
|
|
19281
|
+
if (ctx.config.api.tokenCreated) {
|
|
19282
|
+
// First run that generated the token: no browser holds the auth
|
|
19283
|
+
// cookie yet, so open the authenticated URL to set it. A new tab
|
|
19284
|
+
// here is fine since no clean-URL tab exists to reuse.
|
|
19285
|
+
const url = new URL(ctx.config.uiBase, "http://localhost");
|
|
19286
|
+
url.searchParams.set("token", ctx.config.api.token);
|
|
19287
|
+
server.config.server.open = `${url.pathname}${url.search}`;
|
|
19288
|
+
} else
|
|
19289
|
+
// Subsequent runs: open the clean UI base URL (without `?token=`)
|
|
19290
|
+
// rather than the authenticated URL printed by the logger. On macOS,
|
|
19291
|
+
// `openBrowser` reuses an existing tab whose URL matches via substring
|
|
19292
|
+
// and reloads it (Vite's `bin/openChrome.js`). Since the 302 redirect
|
|
19293
|
+
// strips the token, an already-authenticated tab lives at the clean
|
|
19294
|
+
// URL, so opening the clean URL matches and reloads it; opening the
|
|
19295
|
+
// token URL would never match and would spawn a new tab on every
|
|
19296
|
+
// restart.
|
|
19297
|
+
server.config.server.open = ctx.config.uiBase;
|
|
19298
|
+
server.openBrowser();
|
|
19299
|
+
}
|
|
19300
|
+
}
|
|
19097
19301
|
return ctx;
|
|
19098
19302
|
}
|
|
19099
19303
|
// Vitest can fail at any point inside "setServer" or inside a custom plugin
|