vitest 4.0.17 → 4.1.0-beta.1
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 +1 -1
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.XJJQZiKB.js → base.CBRNZa3k.js} +8 -7
- package/dist/chunks/{browser.d.ChKACdzH.d.ts → browser.d.8hOapKZr.d.ts} +3 -1
- package/dist/chunks/{cac.jRCLJDDc.js → cac.B1v3xxoC.js} +26 -8
- package/dist/chunks/{cli-api.Cx2DW4Bc.js → cli-api.B4CqEpI6.js} +102 -54
- package/dist/chunks/{config.d.Cy95HiCx.d.ts → config.d.idH22YSr.d.ts} +8 -11
- package/dist/chunks/{console.Cf-YriPC.js → console.uGgdMhyZ.js} +2 -1
- package/dist/chunks/{coverage.AVPTjMgw.js → coverage.BMlOMIWl.js} +14 -4
- package/dist/chunks/{creator.DAmOKTvJ.js → creator.C7WwjkuR.js} +32 -1
- package/dist/chunks/{globals.DOayXfHP.js → globals.DjuGMoMc.js} +10 -9
- package/dist/chunks/{index.Z5E_ObnR.js → index.BEFi2-_3.js} +3 -1
- package/dist/chunks/{index.6Qv1eEA6.js → index.BiOAd_ki.js} +16 -4
- package/dist/chunks/{index.M8mOzt4Y.js → index.Dm4xqZ0s.js} +2 -2
- package/dist/chunks/{index.C5r1PdPD.js → index.DyBZXrH3.js} +1 -1
- package/dist/chunks/{init-forks.BC6ZwHQN.js → init-forks.CHeQ9Moq.js} +1 -1
- package/dist/chunks/{init-threads.CxSxLC0N.js → init-threads.uZiNAuPk.js} +1 -1
- package/dist/chunks/{init.C9kljSTm.js → init.DVtKdFty.js} +21 -6
- package/dist/chunks/{plugin.d.CtqpEehP.d.ts → plugin.d.D8KU2PY_.d.ts} +1 -1
- package/dist/chunks/{reporters.d.CWXNI2jG.d.ts → reporters.d.Db3MiIWX.d.ts} +48 -20
- package/dist/chunks/rpc.HLmECnw_.js +148 -0
- package/dist/chunks/{setup-common.Cm-kSBVi.js → setup-common.BcqLPsn5.js} +1 -1
- package/dist/chunks/{startModuleRunner.DEj0jb3e.js → startModuleRunner.C5CcWyXW.js} +22 -22
- package/dist/chunks/{vi.2VT5v0um.js → test.prxIahgM.js} +500 -119
- package/dist/chunks/{vm.CMjifoPa.js → vm.CrifS09m.js} +5 -8
- package/dist/chunks/{worker.d.Dyxm8DEL.d.ts → worker.d.Bji1eq5g.d.ts} +1 -1
- package/dist/cli.js +2 -2
- package/dist/config.d.ts +9 -9
- package/dist/coverage.d.ts +7 -7
- package/dist/coverage.js +3 -1
- package/dist/environments.js +2 -0
- package/dist/index.d.ts +21 -9
- package/dist/index.js +8 -7
- package/dist/module-evaluator.js +1 -5
- package/dist/node.d.ts +11 -10
- package/dist/node.js +19 -19
- package/dist/reporters.d.ts +7 -7
- package/dist/reporters.js +4 -2
- package/dist/runners.d.ts +23 -4
- package/dist/runners.js +4 -4
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +36 -0
- package/dist/snapshot.js +2 -0
- package/dist/suite.js +2 -0
- package/dist/worker.d.ts +4 -3
- package/dist/worker.js +8 -10
- package/dist/workers/forks.js +9 -11
- package/dist/workers/runVmTests.js +10 -12
- package/dist/workers/threads.js +9 -11
- package/dist/workers/vmForks.js +6 -7
- package/dist/workers/vmThreads.js +6 -7
- package/package.json +23 -27
- package/dist/chunks/date.Bq6ZW5rf.js +0 -73
- package/dist/chunks/rpc.BoxB0q7B.js +0 -76
- package/dist/chunks/test.B8ej_ZHS.js +0 -254
- package/dist/mocker.d.ts +0 -1
- package/dist/mocker.js +0 -1
- package/dist/module-runner.js +0 -17
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as SerializedCoverageConfig, S as SerializedConfig } from './chunks/config.d.
|
|
1
|
+
import { a as SerializedCoverageConfig, S as SerializedConfig } from './chunks/config.d.idH22YSr.js';
|
|
2
2
|
import { R as RuntimeCoverageModuleLoader } from './chunks/coverage.d.BZtK59WP.js';
|
|
3
3
|
import { SerializedDiffOptions } from '@vitest/utils/diff';
|
|
4
4
|
export { O as OTELCarrier, T as Traces } from './chunks/traces.d.402V_yFI.js';
|
package/dist/browser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { l as loadDiffConfig, b as loadSnapshotSerializers, c as setupCommonEnv, s as startCoverageInsideWorker, a as stopCoverageInsideWorker, t as takeCoverageInsideWorker } from './chunks/setup-common.
|
|
1
|
+
export { l as loadDiffConfig, b as loadSnapshotSerializers, c as setupCommonEnv, s as startCoverageInsideWorker, a as stopCoverageInsideWorker, t as takeCoverageInsideWorker } from './chunks/setup-common.BcqLPsn5.js';
|
|
2
2
|
export { T as Traces } from './chunks/traces.CCmnQaNT.js';
|
|
3
3
|
export { collectTests, startTests } from '@vitest/runner';
|
|
4
4
|
import * as spyModule from '@vitest/spy';
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { runInThisContext } from 'node:vm';
|
|
2
2
|
import * as spyModule from '@vitest/spy';
|
|
3
|
-
import { r as resolveTestRunner, a as resolveSnapshotEnvironment, s as setupChaiConfig } from './index.
|
|
4
|
-
import { l as loadEnvironment } from './init.
|
|
3
|
+
import { r as resolveTestRunner, a as resolveSnapshotEnvironment, s as setupChaiConfig } from './index.BiOAd_ki.js';
|
|
4
|
+
import { l as loadEnvironment, e as emitModuleRunner } from './init.DVtKdFty.js';
|
|
5
5
|
import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
|
|
6
|
-
import { s as startVitestModuleRunner, c as createNodeImportMeta } from './startModuleRunner.
|
|
6
|
+
import { s as startVitestModuleRunner, c as createNodeImportMeta } from './startModuleRunner.C5CcWyXW.js';
|
|
7
7
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
8
8
|
import { startTests, collectTests } from '@vitest/runner';
|
|
9
|
-
import { c as setupCommonEnv, s as startCoverageInsideWorker, a as stopCoverageInsideWorker } from './setup-common.
|
|
10
|
-
import { g as globalExpect, v as vi } from './
|
|
9
|
+
import { c as setupCommonEnv, s as startCoverageInsideWorker, a as stopCoverageInsideWorker } from './setup-common.BcqLPsn5.js';
|
|
10
|
+
import { g as globalExpect, v as vi } from './test.prxIahgM.js';
|
|
11
11
|
import { c as closeInspector } from './inspector.CvyFGlXm.js';
|
|
12
12
|
import { createRequire } from 'node:module';
|
|
13
13
|
import timers from 'node:timers';
|
|
14
14
|
import timersPromises from 'node:timers/promises';
|
|
15
15
|
import util from 'node:util';
|
|
16
16
|
import { KNOWN_ASSET_TYPES } from '@vitest/utils/constants';
|
|
17
|
-
import { i as index } from './index.
|
|
17
|
+
import { i as index } from './index.BEFi2-_3.js';
|
|
18
18
|
import { g as getWorkerState, r as resetModules, p as provideWorkerState } from './utils.DvEY5TfP.js';
|
|
19
19
|
|
|
20
20
|
// this should only be used in Node
|
|
@@ -56,7 +56,7 @@ function resolveAsset(mod, url) {
|
|
|
56
56
|
mod.exports = url;
|
|
57
57
|
}
|
|
58
58
|
async function setupConsoleLogSpy() {
|
|
59
|
-
const { createCustomConsole } = await import('./console.
|
|
59
|
+
const { createCustomConsole } = await import('./console.uGgdMhyZ.js');
|
|
60
60
|
globalThis.console = createCustomConsole();
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -158,6 +158,7 @@ async function runBaseTests(method, state, traces) {
|
|
|
158
158
|
createImportMeta: createNodeImportMeta,
|
|
159
159
|
traces
|
|
160
160
|
});
|
|
161
|
+
emitModuleRunner(moduleRunner);
|
|
161
162
|
await run(method, ctx.files, ctx.config, moduleRunner, _currentEnvironment, traces);
|
|
162
163
|
}
|
|
163
164
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FileSpecification } from '@vitest/runner';
|
|
2
2
|
import { O as OTELCarrier } from './traces.d.402V_yFI.js';
|
|
3
|
-
import { T as TestExecutionMethod } from './worker.d.
|
|
3
|
+
import { T as TestExecutionMethod } from './worker.d.Bji1eq5g.js';
|
|
4
4
|
|
|
5
5
|
type SerializedTestSpecification = [project: {
|
|
6
6
|
name: string | undefined;
|
|
@@ -8,6 +8,8 @@ type SerializedTestSpecification = [project: {
|
|
|
8
8
|
}, file: string, options: {
|
|
9
9
|
pool: string;
|
|
10
10
|
testLines?: number[] | undefined;
|
|
11
|
+
testIds?: string[] | undefined;
|
|
12
|
+
testNamePattern?: RegExp | undefined;
|
|
11
13
|
}];
|
|
12
14
|
|
|
13
15
|
interface ModuleDefinitionLocation {
|
|
@@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
|
|
|
3
3
|
import { normalize } from 'pathe';
|
|
4
4
|
import c from 'tinyrainbow';
|
|
5
5
|
import { a as defaultPort, d as defaultBrowserPort } from './constants.D_Q9UYh-.js';
|
|
6
|
-
import { R as ReportersMap } from './index.
|
|
6
|
+
import { R as ReportersMap } from './index.Dm4xqZ0s.js';
|
|
7
7
|
|
|
8
8
|
function toArr(any) {
|
|
9
9
|
return any == null ? [] : Array.isArray(any) ? any : [any];
|
|
@@ -619,7 +619,7 @@ class CAC extends EventEmitter {
|
|
|
619
619
|
|
|
620
620
|
const cac = (name = "") => new CAC(name);
|
|
621
621
|
|
|
622
|
-
var version = "4.0.
|
|
622
|
+
var version = "4.1.0-beta.1";
|
|
623
623
|
|
|
624
624
|
const apiConfig = (port) => ({
|
|
625
625
|
port: {
|
|
@@ -968,7 +968,25 @@ const cliOptionsConfig = {
|
|
|
968
968
|
},
|
|
969
969
|
retry: {
|
|
970
970
|
description: "Retry the test specific number of times if it fails (default: `0`)",
|
|
971
|
-
argument: "<times>"
|
|
971
|
+
argument: "<times>",
|
|
972
|
+
subcommands: {
|
|
973
|
+
count: {
|
|
974
|
+
description: "Number of times to retry a test if it fails (default: `0`)",
|
|
975
|
+
argument: "<times>"
|
|
976
|
+
},
|
|
977
|
+
delay: {
|
|
978
|
+
description: "Delay in milliseconds between retry attempts (default: `0`)",
|
|
979
|
+
argument: "<ms>"
|
|
980
|
+
},
|
|
981
|
+
condition: {
|
|
982
|
+
description: "Regex pattern to match error messages that should trigger a retry. Only errors matching this pattern will cause a retry (default: retry on all errors)",
|
|
983
|
+
argument: "<pattern>",
|
|
984
|
+
transform: (value) => {
|
|
985
|
+
if (typeof value === "string") return new RegExp(value, "i");
|
|
986
|
+
return value;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
}
|
|
972
990
|
},
|
|
973
991
|
diff: {
|
|
974
992
|
description: "DiffOptions object or a path to a module which exports DiffOptions object",
|
|
@@ -1356,11 +1374,11 @@ function normalizeCliOptions(cliFilters, argv) {
|
|
|
1356
1374
|
}
|
|
1357
1375
|
async function start(mode, cliFilters, options) {
|
|
1358
1376
|
try {
|
|
1359
|
-
const { startVitest } = await import('./cli-api.
|
|
1377
|
+
const { startVitest } = await import('./cli-api.B4CqEpI6.js').then(function (n) { return n.q; });
|
|
1360
1378
|
const ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(cliFilters, options));
|
|
1361
1379
|
if (!ctx.shouldKeepServer()) await ctx.exit();
|
|
1362
1380
|
} catch (e) {
|
|
1363
|
-
const { errorBanner } = await import('./index.
|
|
1381
|
+
const { errorBanner } = await import('./index.Dm4xqZ0s.js').then(function (n) { return n.A; });
|
|
1364
1382
|
console.error(`\n${errorBanner("Startup Error")}`);
|
|
1365
1383
|
console.error(e);
|
|
1366
1384
|
console.error("\n\n");
|
|
@@ -1373,12 +1391,12 @@ async function init(project) {
|
|
|
1373
1391
|
console.error(/* @__PURE__ */ new Error("Only the \"browser\" project is supported. Use \"vitest init browser\" to create a new project."));
|
|
1374
1392
|
process.exit(1);
|
|
1375
1393
|
}
|
|
1376
|
-
const { create } = await import('./creator.
|
|
1394
|
+
const { create } = await import('./creator.C7WwjkuR.js');
|
|
1377
1395
|
await create();
|
|
1378
1396
|
}
|
|
1379
1397
|
async function collect(mode, cliFilters, options) {
|
|
1380
1398
|
try {
|
|
1381
|
-
const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.
|
|
1399
|
+
const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.B4CqEpI6.js').then(function (n) { return n.q; });
|
|
1382
1400
|
const ctx = await prepareVitest(mode, {
|
|
1383
1401
|
...normalizeCliOptions(cliFilters, options),
|
|
1384
1402
|
watch: false,
|
|
@@ -1397,7 +1415,7 @@ async function collect(mode, cliFilters, options) {
|
|
|
1397
1415
|
} else outputFileList(await ctx.getRelevantTestSpecifications(cliFilters.map(normalize)), options);
|
|
1398
1416
|
await ctx.close();
|
|
1399
1417
|
} catch (e) {
|
|
1400
|
-
const { errorBanner } = await import('./index.
|
|
1418
|
+
const { errorBanner } = await import('./index.Dm4xqZ0s.js').then(function (n) { return n.A; });
|
|
1401
1419
|
console.error(`\n${errorBanner("Collect Error")}`);
|
|
1402
1420
|
console.error(e);
|
|
1403
1421
|
console.error("\n\n");
|
|
@@ -4,7 +4,7 @@ import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
|
|
|
4
4
|
import path, { resolve as resolve$1 } from 'node:path';
|
|
5
5
|
import { noop, createDefer, slash, withTrailingSlash, cleanUrl, wrapId, isExternalUrl, unwrapId, toArray, deepMerge, nanoid, deepClone, isPrimitive, notNullish } from '@vitest/utils/helpers';
|
|
6
6
|
import { a as any, p as prompt } from './index.D4KonVSU.js';
|
|
7
|
-
import { h as hash, R as RandomSequencer, i as isPackageExists, c as isBrowserEnabled, r as resolveConfig, g as getCoverageProvider, a as resolveApiServerConfig, d as resolveModule } from './coverage.
|
|
7
|
+
import { h as hash, R as RandomSequencer, i as isPackageExists, c as isBrowserEnabled, r as resolveConfig, g as getCoverageProvider, a as resolveApiServerConfig, d as resolveModule } from './coverage.BMlOMIWl.js';
|
|
8
8
|
import * as vite from 'vite';
|
|
9
9
|
import { isFileServingAllowed as isFileServingAllowed$1, parseAst, searchForWorkspaceRoot, fetchModule, version, mergeConfig, createServer, isFileLoadingAllowed, normalizePath } from 'vite';
|
|
10
10
|
import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
|
|
@@ -12,10 +12,10 @@ import * as nodeos from 'node:os';
|
|
|
12
12
|
import nodeos__default, { tmpdir } from 'node:os';
|
|
13
13
|
import { generateHash as generateHash$1, createTaskName, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, hasFailed, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, getTasks, isTestCase } from '@vitest/runner/utils';
|
|
14
14
|
import { SnapshotManager } from '@vitest/snapshot/manager';
|
|
15
|
-
import { v as version$1 } from './cac.
|
|
15
|
+
import { v as version$1 } from './cac.B1v3xxoC.js';
|
|
16
16
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
17
17
|
import { c as createBirpc } from './index.Chj8NDwU.js';
|
|
18
|
-
import { p as parse, d as stringify, e as createIndexLocationsMap, h as TraceMap, o as originalPositionFor, i as ancestor, j as printError, f as formatProjectName, w as withLabel, k as errorBanner, l as divider, m as Typechecker, n as generateCodeFrame, q as escapeRegExp, r as createDefinesScript, R as ReportersMap, u as groupBy, B as BlobReporter, v as readBlobs, x as convertTasksToEvents, H as HangingProcessReporter, y as wildcardPatternToRegExp, z as stdout } from './index.
|
|
18
|
+
import { p as parse, d as stringify, e as createIndexLocationsMap, h as TraceMap, o as originalPositionFor, i as ancestor, j as printError, f as formatProjectName, w as withLabel, k as errorBanner, l as divider, m as Typechecker, n as generateCodeFrame, q as escapeRegExp, r as createDefinesScript, R as ReportersMap, u as groupBy, B as BlobReporter, v as readBlobs, x as convertTasksToEvents, H as HangingProcessReporter, y as wildcardPatternToRegExp, z as stdout } from './index.Dm4xqZ0s.js';
|
|
19
19
|
import require$$0$3 from 'events';
|
|
20
20
|
import require$$1$1 from 'https';
|
|
21
21
|
import require$$2 from 'http';
|
|
@@ -53,7 +53,7 @@ import { c as configDefaults } from './defaults.BOqNVLsY.js';
|
|
|
53
53
|
import { KNOWN_ASSET_RE } from '@vitest/utils/constants';
|
|
54
54
|
import { findNearestPackageData } from '@vitest/utils/resolver';
|
|
55
55
|
import * as esModuleLexer from 'es-module-lexer';
|
|
56
|
-
import { a as BenchmarkReportsMap } from './index.
|
|
56
|
+
import { a as BenchmarkReportsMap } from './index.DyBZXrH3.js';
|
|
57
57
|
import assert$1 from 'node:assert';
|
|
58
58
|
import { serializeValue } from '@vitest/utils/serialize';
|
|
59
59
|
import { parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
@@ -76,6 +76,7 @@ function requireConstants () {
|
|
|
76
76
|
|
|
77
77
|
constants = {
|
|
78
78
|
BINARY_TYPES,
|
|
79
|
+
CLOSE_TIMEOUT: 30000,
|
|
79
80
|
EMPTY_BUFFER: Buffer.alloc(0),
|
|
80
81
|
GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
|
|
81
82
|
hasBlob,
|
|
@@ -2846,6 +2847,7 @@ function requireWebsocket () {
|
|
|
2846
2847
|
|
|
2847
2848
|
const {
|
|
2848
2849
|
BINARY_TYPES,
|
|
2850
|
+
CLOSE_TIMEOUT,
|
|
2849
2851
|
EMPTY_BUFFER,
|
|
2850
2852
|
GUID,
|
|
2851
2853
|
kForOnEventAttribute,
|
|
@@ -2860,7 +2862,6 @@ function requireWebsocket () {
|
|
|
2860
2862
|
const { format, parse } = requireExtension();
|
|
2861
2863
|
const { toBuffer } = requireBufferUtil();
|
|
2862
2864
|
|
|
2863
|
-
const closeTimeout = 30 * 1000;
|
|
2864
2865
|
const kAborted = Symbol('kAborted');
|
|
2865
2866
|
const protocolVersions = [8, 13];
|
|
2866
2867
|
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
|
|
@@ -2916,6 +2917,7 @@ function requireWebsocket () {
|
|
|
2916
2917
|
initAsClient(this, address, protocols, options);
|
|
2917
2918
|
} else {
|
|
2918
2919
|
this._autoPong = options.autoPong;
|
|
2920
|
+
this._closeTimeout = options.closeTimeout;
|
|
2919
2921
|
this._isServer = true;
|
|
2920
2922
|
}
|
|
2921
2923
|
}
|
|
@@ -3457,6 +3459,8 @@ function requireWebsocket () {
|
|
|
3457
3459
|
* times in the same tick
|
|
3458
3460
|
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
|
|
3459
3461
|
* automatically send a pong in response to a ping
|
|
3462
|
+
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait
|
|
3463
|
+
* for the closing handshake to finish after `websocket.close()` is called
|
|
3460
3464
|
* @param {Function} [options.finishRequest] A function which can be used to
|
|
3461
3465
|
* customize the headers of each http request before it is sent
|
|
3462
3466
|
* @param {Boolean} [options.followRedirects=false] Whether or not to follow
|
|
@@ -3483,6 +3487,7 @@ function requireWebsocket () {
|
|
|
3483
3487
|
const opts = {
|
|
3484
3488
|
allowSynchronousEvents: true,
|
|
3485
3489
|
autoPong: true,
|
|
3490
|
+
closeTimeout: CLOSE_TIMEOUT,
|
|
3486
3491
|
protocolVersion: protocolVersions[1],
|
|
3487
3492
|
maxPayload: 100 * 1024 * 1024,
|
|
3488
3493
|
skipUTF8Validation: false,
|
|
@@ -3501,6 +3506,7 @@ function requireWebsocket () {
|
|
|
3501
3506
|
};
|
|
3502
3507
|
|
|
3503
3508
|
websocket._autoPong = opts.autoPong;
|
|
3509
|
+
websocket._closeTimeout = opts.closeTimeout;
|
|
3504
3510
|
|
|
3505
3511
|
if (!protocolVersions.includes(opts.protocolVersion)) {
|
|
3506
3512
|
throw new RangeError(
|
|
@@ -4118,7 +4124,7 @@ function requireWebsocket () {
|
|
|
4118
4124
|
function setCloseTimer(websocket) {
|
|
4119
4125
|
websocket._closeTimer = setTimeout(
|
|
4120
4126
|
websocket._socket.destroy.bind(websocket._socket),
|
|
4121
|
-
|
|
4127
|
+
websocket._closeTimeout
|
|
4122
4128
|
);
|
|
4123
4129
|
}
|
|
4124
4130
|
|
|
@@ -4136,23 +4142,23 @@ function requireWebsocket () {
|
|
|
4136
4142
|
|
|
4137
4143
|
websocket._readyState = WebSocket.CLOSING;
|
|
4138
4144
|
|
|
4139
|
-
let chunk;
|
|
4140
|
-
|
|
4141
4145
|
//
|
|
4142
4146
|
// The close frame might not have been received or the `'end'` event emitted,
|
|
4143
4147
|
// for example, if the socket was destroyed due to an error. Ensure that the
|
|
4144
4148
|
// `receiver` stream is closed after writing any remaining buffered data to
|
|
4145
4149
|
// it. If the readable side of the socket is in flowing mode then there is no
|
|
4146
|
-
// buffered data as everything has been already written
|
|
4147
|
-
//
|
|
4148
|
-
//
|
|
4150
|
+
// buffered data as everything has been already written. If instead, the
|
|
4151
|
+
// socket is paused, any possible buffered data will be read as a single
|
|
4152
|
+
// chunk.
|
|
4149
4153
|
//
|
|
4150
4154
|
if (
|
|
4151
4155
|
!this._readableState.endEmitted &&
|
|
4152
4156
|
!websocket._closeFrameReceived &&
|
|
4153
4157
|
!websocket._receiver._writableState.errorEmitted &&
|
|
4154
|
-
|
|
4158
|
+
this._readableState.length !== 0
|
|
4155
4159
|
) {
|
|
4160
|
+
const chunk = this.read(this._readableState.length);
|
|
4161
|
+
|
|
4156
4162
|
websocket._receiver.write(chunk);
|
|
4157
4163
|
}
|
|
4158
4164
|
|
|
@@ -4483,7 +4489,7 @@ function requireWebsocketServer () {
|
|
|
4483
4489
|
const PerMessageDeflate = requirePermessageDeflate();
|
|
4484
4490
|
const subprotocol = requireSubprotocol();
|
|
4485
4491
|
const WebSocket = requireWebsocket();
|
|
4486
|
-
const { GUID, kWebSocket } = requireConstants();
|
|
4492
|
+
const { CLOSE_TIMEOUT, GUID, kWebSocket } = requireConstants();
|
|
4487
4493
|
|
|
4488
4494
|
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
|
|
4489
4495
|
|
|
@@ -4510,6 +4516,9 @@ function requireWebsocketServer () {
|
|
|
4510
4516
|
* pending connections
|
|
4511
4517
|
* @param {Boolean} [options.clientTracking=true] Specifies whether or not to
|
|
4512
4518
|
* track clients
|
|
4519
|
+
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to
|
|
4520
|
+
* wait for the closing handshake to finish after `websocket.close()` is
|
|
4521
|
+
* called
|
|
4513
4522
|
* @param {Function} [options.handleProtocols] A hook to handle protocols
|
|
4514
4523
|
* @param {String} [options.host] The hostname where to bind the server
|
|
4515
4524
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
@@ -4539,6 +4548,7 @@ function requireWebsocketServer () {
|
|
|
4539
4548
|
perMessageDeflate: false,
|
|
4540
4549
|
handleProtocols: null,
|
|
4541
4550
|
clientTracking: true,
|
|
4551
|
+
closeTimeout: CLOSE_TIMEOUT,
|
|
4542
4552
|
verifyClient: null,
|
|
4543
4553
|
noServer: false,
|
|
4544
4554
|
backlog: null, // use default (511 as implemented in net.js)
|
|
@@ -5327,6 +5337,12 @@ function createDebugger(namespace) {
|
|
|
5327
5337
|
|
|
5328
5338
|
const debug$1 = createDebugger("vitest:ast-collect-info");
|
|
5329
5339
|
const verbose = createDebugger("vitest:ast-collect-verbose");
|
|
5340
|
+
function isTestFunctionName(name) {
|
|
5341
|
+
return name === "it" || name === "test" || name.startsWith("test") || name.endsWith("Test");
|
|
5342
|
+
}
|
|
5343
|
+
function isVitestFunctionName(name) {
|
|
5344
|
+
return name === "describe" || name === "suite" || isTestFunctionName(name);
|
|
5345
|
+
}
|
|
5330
5346
|
function astParseFile(filepath, code) {
|
|
5331
5347
|
const ast = parseAst(code);
|
|
5332
5348
|
if (verbose) verbose("Collecting", filepath, code);
|
|
@@ -5338,12 +5354,7 @@ function astParseFile(filepath, code) {
|
|
|
5338
5354
|
if (callee.type === "CallExpression") return getName(callee.callee);
|
|
5339
5355
|
if (callee.type === "TaggedTemplateExpression") return getName(callee.tag);
|
|
5340
5356
|
if (callee.type === "MemberExpression") {
|
|
5341
|
-
if (callee.object?.type === "Identifier" &&
|
|
5342
|
-
"it",
|
|
5343
|
-
"test",
|
|
5344
|
-
"describe",
|
|
5345
|
-
"suite"
|
|
5346
|
-
].includes(callee.object.name)) return callee.object?.name;
|
|
5357
|
+
if (callee.object?.type === "Identifier" && isVitestFunctionName(callee.object.name)) return callee.object?.name;
|
|
5347
5358
|
if (callee.object?.name?.startsWith("__vite_ssr_") || callee.object?.object?.name?.startsWith("__vite_ssr_") && callee.object?.property?.name === "Vitest") return getName(callee.property);
|
|
5348
5359
|
// call as `__vite_ssr__.test.skip()`
|
|
5349
5360
|
return getName(callee.object?.property);
|
|
@@ -5359,12 +5370,7 @@ function astParseFile(filepath, code) {
|
|
|
5359
5370
|
const { callee } = node;
|
|
5360
5371
|
const name = getName(callee);
|
|
5361
5372
|
if (!name) return;
|
|
5362
|
-
if (!
|
|
5363
|
-
"it",
|
|
5364
|
-
"test",
|
|
5365
|
-
"describe",
|
|
5366
|
-
"suite"
|
|
5367
|
-
].includes(name)) {
|
|
5373
|
+
if (!isVitestFunctionName(name)) {
|
|
5368
5374
|
verbose?.(`Skipping ${name} (unknown call)`);
|
|
5369
5375
|
return;
|
|
5370
5376
|
}
|
|
@@ -5375,7 +5381,9 @@ function astParseFile(filepath, code) {
|
|
|
5375
5381
|
"each",
|
|
5376
5382
|
"for",
|
|
5377
5383
|
"skipIf",
|
|
5378
|
-
"runIf"
|
|
5384
|
+
"runIf",
|
|
5385
|
+
"extend",
|
|
5386
|
+
"scoped"
|
|
5379
5387
|
].includes(mode)) return;
|
|
5380
5388
|
let start;
|
|
5381
5389
|
const end = node.end;
|
|
@@ -5405,7 +5413,7 @@ function astParseFile(filepath, code) {
|
|
|
5405
5413
|
start,
|
|
5406
5414
|
end,
|
|
5407
5415
|
name: message,
|
|
5408
|
-
type: name
|
|
5416
|
+
type: isTestFunctionName(name) ? "test" : "suite",
|
|
5409
5417
|
mode,
|
|
5410
5418
|
task: null,
|
|
5411
5419
|
dynamic: isDynamicEach
|
|
@@ -5494,7 +5502,10 @@ function createFileTask(testFilepath, code, requestMap, options) {
|
|
|
5494
5502
|
});
|
|
5495
5503
|
if (originalLocation.column != null) {
|
|
5496
5504
|
verbose?.(`Found location for`, definition.type, definition.name, `${processedLocation.line}:${processedLocation.column}`, "->", `${originalLocation.line}:${originalLocation.column}`);
|
|
5497
|
-
location =
|
|
5505
|
+
location = {
|
|
5506
|
+
line: originalLocation.line,
|
|
5507
|
+
column: originalLocation.column
|
|
5508
|
+
};
|
|
5498
5509
|
} else debug$1?.("Cannot find original location for", definition.type, definition.name, `${processedLocation.column}:${processedLocation.line}`);
|
|
5499
5510
|
} else debug$1?.("Cannot find original location for", definition.type, definition.name, `${definition.start}`);
|
|
5500
5511
|
if (definition.type === "suite") {
|
|
@@ -5543,7 +5554,7 @@ function createFileTask(testFilepath, code, requestMap, options) {
|
|
|
5543
5554
|
});
|
|
5544
5555
|
calculateSuiteHash(file);
|
|
5545
5556
|
const hasOnly = someTasksAreOnly(file);
|
|
5546
|
-
interpretTaskModes(file, options.testNamePattern, void 0, hasOnly, false, options.allowOnly);
|
|
5557
|
+
interpretTaskModes(file, options.testNamePattern, void 0, void 0, hasOnly, false, options.allowOnly);
|
|
5547
5558
|
markDynamicTests(file.tasks);
|
|
5548
5559
|
if (!file.tasks.length) file.result = {
|
|
5549
5560
|
state: "fail",
|
|
@@ -5570,9 +5581,9 @@ async function astCollectTests(project, filepath) {
|
|
|
5570
5581
|
});
|
|
5571
5582
|
}
|
|
5572
5583
|
async function transformSSR(project, filepath) {
|
|
5573
|
-
const
|
|
5574
|
-
if (
|
|
5575
|
-
return
|
|
5584
|
+
const environment = project.config.environment;
|
|
5585
|
+
if (environment === "jsdom" || environment === "happy-dom") return project.vite.environments.client.transformRequest(filepath);
|
|
5586
|
+
return project.vite.environments.ssr.transformRequest(filepath);
|
|
5576
5587
|
}
|
|
5577
5588
|
function markDynamicTests(tasks) {
|
|
5578
5589
|
for (const task of tasks) {
|
|
@@ -7048,11 +7059,13 @@ function createBrowserPool(vitest) {
|
|
|
7048
7059
|
};
|
|
7049
7060
|
const runWorkspaceTests = async (method, specs) => {
|
|
7050
7061
|
const groupedFiles = /* @__PURE__ */ new Map();
|
|
7051
|
-
for (const { project, moduleId, testLines } of specs) {
|
|
7062
|
+
for (const { project, moduleId, testLines, testIds, testNamePattern } of specs) {
|
|
7052
7063
|
const files = groupedFiles.get(project) || [];
|
|
7053
7064
|
files.push({
|
|
7054
7065
|
filepath: moduleId,
|
|
7055
|
-
testLocations: testLines
|
|
7066
|
+
testLocations: testLines,
|
|
7067
|
+
testIds,
|
|
7068
|
+
testNamePattern
|
|
7056
7069
|
});
|
|
7057
7070
|
groupedFiles.set(project, files);
|
|
7058
7071
|
}
|
|
@@ -8247,7 +8260,9 @@ function createPool(ctx) {
|
|
|
8247
8260
|
context: {
|
|
8248
8261
|
files: specs.map((spec) => ({
|
|
8249
8262
|
filepath: spec.moduleId,
|
|
8250
|
-
testLocations: spec.testLines
|
|
8263
|
+
testLocations: spec.testLines,
|
|
8264
|
+
testNamePattern: spec.testNamePattern,
|
|
8265
|
+
testIds: spec.testIds
|
|
8251
8266
|
})),
|
|
8252
8267
|
invalidates,
|
|
8253
8268
|
providedContext: project.getProvidedContext(),
|
|
@@ -9807,7 +9822,7 @@ function matchPattern(id, moduleDirectories, patterns) {
|
|
|
9807
9822
|
|
|
9808
9823
|
class TestSpecification {
|
|
9809
9824
|
/**
|
|
9810
|
-
* The task
|
|
9825
|
+
* The task id associated with the test module.
|
|
9811
9826
|
*/
|
|
9812
9827
|
taskId;
|
|
9813
9828
|
/**
|
|
@@ -9815,29 +9830,46 @@ class TestSpecification {
|
|
|
9815
9830
|
*/
|
|
9816
9831
|
project;
|
|
9817
9832
|
/**
|
|
9818
|
-
* The
|
|
9833
|
+
* The id of the module in the Vite module graph. It is usually an absolute file path.
|
|
9819
9834
|
*/
|
|
9820
9835
|
moduleId;
|
|
9821
9836
|
/**
|
|
9822
|
-
* The current test pool. It's possible to have multiple pools in a single test project with `
|
|
9823
|
-
* @experimental In
|
|
9837
|
+
* The current test pool. It's possible to have multiple pools in a single test project with `typecheck.enabled`.
|
|
9838
|
+
* @experimental In later versions, the project will only support a single pool.
|
|
9824
9839
|
*/
|
|
9825
9840
|
pool;
|
|
9826
9841
|
/**
|
|
9827
9842
|
* Line numbers of the test locations to run.
|
|
9828
9843
|
*/
|
|
9829
9844
|
testLines;
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9845
|
+
/**
|
|
9846
|
+
* Regular expression pattern to filter test names.
|
|
9847
|
+
*/
|
|
9848
|
+
testNamePattern;
|
|
9849
|
+
/**
|
|
9850
|
+
* The ids of tasks inside of this specification to run.
|
|
9851
|
+
*/
|
|
9852
|
+
testIds;
|
|
9853
|
+
/**
|
|
9854
|
+
* This class represents a test suite for a test module within a single project.
|
|
9855
|
+
* @internal
|
|
9856
|
+
*/
|
|
9857
|
+
constructor(project, moduleId, pool, testLinesOrOptions) {
|
|
9858
|
+
const projectName = project.config.name;
|
|
9859
|
+
const hashName = pool !== "typescript" ? projectName : projectName ? `${projectName}:__typecheck__` : "__typecheck__";
|
|
9833
9860
|
this.taskId = generateFileHash(relative(project.config.root, moduleId), hashName);
|
|
9834
9861
|
this.project = project;
|
|
9835
9862
|
this.moduleId = moduleId;
|
|
9836
9863
|
this.pool = pool;
|
|
9837
|
-
this.testLines =
|
|
9864
|
+
if (Array.isArray(testLinesOrOptions)) this.testLines = testLinesOrOptions;
|
|
9865
|
+
else if (testLinesOrOptions && typeof testLinesOrOptions === "object") {
|
|
9866
|
+
this.testLines = testLinesOrOptions.testLines;
|
|
9867
|
+
this.testNamePattern = testLinesOrOptions.testNamePattern;
|
|
9868
|
+
this.testIds = testLinesOrOptions.testIds;
|
|
9869
|
+
}
|
|
9838
9870
|
}
|
|
9839
9871
|
/**
|
|
9840
|
-
* Test module associated with the specification.
|
|
9872
|
+
* Test module associated with the specification. This will be `undefined` if tests have not been run yet.
|
|
9841
9873
|
*/
|
|
9842
9874
|
get testModule() {
|
|
9843
9875
|
const task = this.project.vitest.state.idMap.get(this.taskId);
|
|
@@ -9853,7 +9885,9 @@ class TestSpecification {
|
|
|
9853
9885
|
this.moduleId,
|
|
9854
9886
|
{
|
|
9855
9887
|
pool: this.pool,
|
|
9856
|
-
testLines: this.testLines
|
|
9888
|
+
testLines: this.testLines,
|
|
9889
|
+
testIds: this.testIds,
|
|
9890
|
+
testNamePattern: this.testNamePattern
|
|
9857
9891
|
}
|
|
9858
9892
|
];
|
|
9859
9893
|
}
|
|
@@ -9962,8 +9996,8 @@ class TestProject {
|
|
|
9962
9996
|
* Creates a new test specification. Specifications describe how to run tests.
|
|
9963
9997
|
* @param moduleId The file path
|
|
9964
9998
|
*/
|
|
9965
|
-
createSpecification(moduleId,
|
|
9966
|
-
return new TestSpecification(this, moduleId, pool || getFilePoolName(this),
|
|
9999
|
+
createSpecification(moduleId, locationsOrOptions, pool) {
|
|
10000
|
+
return new TestSpecification(this, moduleId, pool || getFilePoolName(this), locationsOrOptions);
|
|
9967
10001
|
}
|
|
9968
10002
|
toJSON() {
|
|
9969
10003
|
return {
|
|
@@ -10188,7 +10222,7 @@ class TestProject {
|
|
|
10188
10222
|
if (!this.closingPromise) this.closingPromise = Promise.all([
|
|
10189
10223
|
this.vite?.close(),
|
|
10190
10224
|
this.typechecker?.stop(),
|
|
10191
|
-
this.browser?.close(),
|
|
10225
|
+
(this.browser || this._parent?._parentBrowser?.vite)?.close(),
|
|
10192
10226
|
this.clearTmpDir()
|
|
10193
10227
|
].filter(Boolean)).then(() => {
|
|
10194
10228
|
if (!this.runner.isClosed()) return this.runner.close();
|
|
@@ -12476,7 +12510,7 @@ class Vitest {
|
|
|
12476
12510
|
}
|
|
12477
12511
|
this.filenamePattern = filters && filters?.length > 0 ? filters : void 0;
|
|
12478
12512
|
startSpan.setAttribute("vitest.start.filters", this.filenamePattern || []);
|
|
12479
|
-
const
|
|
12513
|
+
const specifications = await this._traces.$("vitest.config.resolve_include_glob", async () => {
|
|
12480
12514
|
const specifications = await this.specifications.getRelevantTestSpecifications(filters);
|
|
12481
12515
|
startSpan.setAttribute("vitest.start.specifications", specifications.map((s) => {
|
|
12482
12516
|
const relativeModuleId = relative(s.project.config.root, s.moduleId);
|
|
@@ -12486,7 +12520,7 @@ class Vitest {
|
|
|
12486
12520
|
return specifications;
|
|
12487
12521
|
});
|
|
12488
12522
|
// if run with --changed, don't exit if no tests are found
|
|
12489
|
-
if (!
|
|
12523
|
+
if (!specifications.length) {
|
|
12490
12524
|
await this._traces.$("vitest.test_run", async () => {
|
|
12491
12525
|
await this._testRun.start([]);
|
|
12492
12526
|
const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true });
|
|
@@ -12500,10 +12534,10 @@ class Vitest {
|
|
|
12500
12534
|
testModules: [],
|
|
12501
12535
|
unhandledErrors: []
|
|
12502
12536
|
};
|
|
12503
|
-
if (
|
|
12537
|
+
if (specifications.length) {
|
|
12504
12538
|
// populate once, update cache on watch
|
|
12505
|
-
await this.cache.stats.populateStats(this.config.root,
|
|
12506
|
-
testModules = await this.runFiles(
|
|
12539
|
+
await this.cache.stats.populateStats(this.config.root, specifications);
|
|
12540
|
+
testModules = await this.runFiles(specifications, true);
|
|
12507
12541
|
}
|
|
12508
12542
|
if (this.config.watch) await this.report("onWatcherStart");
|
|
12509
12543
|
return testModules;
|
|
@@ -12562,6 +12596,19 @@ class Vitest {
|
|
|
12562
12596
|
return this.runFiles(specifications, allTestsRun);
|
|
12563
12597
|
}
|
|
12564
12598
|
/**
|
|
12599
|
+
* Runs tests for the given file paths. This does not trigger `onWatcher*` events.
|
|
12600
|
+
* @param filepaths A list of file paths to run tests for.
|
|
12601
|
+
* @param allTestsRun Indicates whether all tests were run. This only matters for coverage.
|
|
12602
|
+
*/
|
|
12603
|
+
async runTestFiles(filepaths, allTestsRun = false) {
|
|
12604
|
+
const specifications = await this.specifications.getRelevantTestSpecifications(filepaths);
|
|
12605
|
+
if (!specifications.length) return {
|
|
12606
|
+
testModules: [],
|
|
12607
|
+
unhandledErrors: []
|
|
12608
|
+
};
|
|
12609
|
+
return this.runFiles(specifications, allTestsRun);
|
|
12610
|
+
}
|
|
12611
|
+
/**
|
|
12565
12612
|
* Rerun files and trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun` events.
|
|
12566
12613
|
* @param specifications A list of specifications to run.
|
|
12567
12614
|
* @param allTestsRun Indicates whether all tests were run. This only matters for coverage.
|
|
@@ -13055,7 +13102,8 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
|
|
|
13055
13102
|
// store defines for globalThis to make them
|
|
13056
13103
|
// reassignable when running in worker in src/runtime/setup.ts
|
|
13057
13104
|
const originalDefine = { ...viteConfig.define };
|
|
13058
|
-
|
|
13105
|
+
const defines = deleteDefineConfig(viteConfig);
|
|
13106
|
+
options.defines = defines;
|
|
13059
13107
|
options.viteDefine = originalDefine;
|
|
13060
13108
|
let open = false;
|
|
13061
13109
|
if (testConfig.ui && testConfig.open) open = testConfig.uiBase ?? "/__vitest__/";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PrettyFormatOptions } from '@vitest/pretty-format';
|
|
2
|
-
import { SequenceHooks, SequenceSetupFiles } from '@vitest/runner';
|
|
2
|
+
import { SequenceHooks, SequenceSetupFiles, SerializableRetry } from '@vitest/runner';
|
|
3
3
|
import { SnapshotUpdateState, SnapshotEnvironment } from '@vitest/snapshot';
|
|
4
4
|
import { SerializedDiffOptions } from '@vitest/utils/diff';
|
|
5
5
|
|
|
@@ -30,15 +30,13 @@ interface FakeTimerInstallOpts {
|
|
|
30
30
|
now?: number | Date | undefined;
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* An array with names of global methods and APIs to fake.
|
|
34
|
-
* For instance, `
|
|
35
|
-
* @default everything available globally except `nextTick`
|
|
33
|
+
* An array with names of global methods and APIs to fake. By default, `@sinonjs/fake-timers` does not replace `nextTick()` and `queueMicrotask()`.
|
|
34
|
+
* For instance, `FakeTimers.install({ toFake: ['setTimeout', 'nextTick'] })` will fake only `setTimeout()` and `nextTick()`
|
|
36
35
|
*/
|
|
37
36
|
toFake?: FakeMethod[] | undefined;
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
|
-
* The maximum number of timers that will be run when calling runAll()
|
|
41
|
-
* @default 10000
|
|
39
|
+
* The maximum number of timers that will be run when calling runAll() (default: 1000)
|
|
42
40
|
*/
|
|
43
41
|
loopLimit?: number | undefined;
|
|
44
42
|
|
|
@@ -55,14 +53,13 @@ interface FakeTimerInstallOpts {
|
|
|
55
53
|
advanceTimeDelta?: number | undefined;
|
|
56
54
|
|
|
57
55
|
/**
|
|
58
|
-
* Tells FakeTimers to clear 'native' (i.e. not fake) timers by delegating to their respective handlers.
|
|
59
|
-
*
|
|
56
|
+
* Tells FakeTimers to clear 'native' (i.e. not fake) timers by delegating to their respective handlers. These are not cleared by
|
|
57
|
+
* default, leading to potentially unexpected behavior if timers existed prior to installing FakeTimers. (default: false)
|
|
60
58
|
*/
|
|
61
59
|
shouldClearNativeTimers?: boolean | undefined;
|
|
62
60
|
|
|
63
61
|
/**
|
|
64
|
-
*
|
|
65
|
-
* @default false
|
|
62
|
+
* Tells FakeTimers to not throw an error when faking a timer that does not exist in the global object. (default: false)
|
|
66
63
|
*/
|
|
67
64
|
ignoreMissingTimers?: boolean | undefined;
|
|
68
65
|
}
|
|
@@ -141,7 +138,7 @@ interface SerializedConfig {
|
|
|
141
138
|
truncateThreshold?: number;
|
|
142
139
|
} | undefined;
|
|
143
140
|
diff: string | SerializedDiffOptions | undefined;
|
|
144
|
-
retry:
|
|
141
|
+
retry: SerializableRetry;
|
|
145
142
|
includeTaskLocation: boolean | undefined;
|
|
146
143
|
inspect: boolean | string | undefined;
|
|
147
144
|
inspectBrk: boolean | string | undefined;
|
|
@@ -3,8 +3,9 @@ import { relative } from 'node:path';
|
|
|
3
3
|
import { Writable } from 'node:stream';
|
|
4
4
|
import { getSafeTimers } from '@vitest/utils/timers';
|
|
5
5
|
import c from 'tinyrainbow';
|
|
6
|
-
import { R as RealDate } from './
|
|
6
|
+
import { R as RealDate } from './rpc.HLmECnw_.js';
|
|
7
7
|
import { g as getWorkerState } from './utils.DvEY5TfP.js';
|
|
8
|
+
import './index.Chj8NDwU.js';
|
|
8
9
|
|
|
9
10
|
const UNKNOWN_TEST_ID = "__vitest__unknown_test__";
|
|
10
11
|
function getTaskIdByStack(root) {
|