@voidzero-dev/vite-plus-test 0.0.0-0bfcc90f.20260209-0731
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 +691 -0
- package/browser/context.d.ts +4 -0
- package/browser/context.js +20 -0
- package/config.d.ts +3 -0
- package/coverage.d.ts +1 -0
- package/dist/@vitest/browser/client/.vite/manifest.json +24 -0
- package/dist/@vitest/browser/client/__vitest__/assets/index-BUCFJtth.js +57 -0
- package/dist/@vitest/browser/client/__vitest__/assets/index-DlhE0rqZ.css +1 -0
- package/dist/@vitest/browser/client/__vitest__/bg.png +0 -0
- package/dist/@vitest/browser/client/__vitest__/favicon.ico +0 -0
- package/dist/@vitest/browser/client/__vitest__/favicon.svg +5 -0
- package/dist/@vitest/browser/client/__vitest__/index.html +32 -0
- package/dist/@vitest/browser/client/__vitest_browser__/orchestrator-S_3e_uzt.js +345 -0
- package/dist/@vitest/browser/client/__vitest_browser__/tester-k74mgIRa.js +2171 -0
- package/dist/@vitest/browser/client/__vitest_browser__/utils-uxqdqUz8.js +223 -0
- package/dist/@vitest/browser/client/error-catcher.js +82 -0
- package/dist/@vitest/browser/client/esm-client-injector.js +67 -0
- package/dist/@vitest/browser/client/favicon.svg +5 -0
- package/dist/@vitest/browser/client/orchestrator.html +35 -0
- package/dist/@vitest/browser/client/tester/tester.html +13 -0
- package/dist/@vitest/browser/client.js +456 -0
- package/dist/@vitest/browser/context.d.ts +792 -0
- package/dist/@vitest/browser/context.js +541 -0
- package/dist/@vitest/browser/expect-element.js +32 -0
- package/dist/@vitest/browser/index-D6m36C6U.js +11 -0
- package/dist/@vitest/browser/index.d.ts +73 -0
- package/dist/@vitest/browser/index.js +3513 -0
- package/dist/@vitest/browser/jest-dom.d.ts +724 -0
- package/dist/@vitest/browser/locators.d.ts +354 -0
- package/dist/@vitest/browser/locators.js +1 -0
- package/dist/@vitest/browser/matchers.d.ts +29 -0
- package/dist/@vitest/browser/shared/screenshotMatcher/types.d.ts +22 -0
- package/dist/@vitest/browser/state.js +280 -0
- package/dist/@vitest/browser/types.d.ts +69 -0
- package/dist/@vitest/browser-playwright/context.d.ts +1 -0
- package/dist/@vitest/browser-playwright/index.d.ts +106 -0
- package/dist/@vitest/browser-playwright/index.js +1111 -0
- package/dist/@vitest/browser-playwright/locators.js +114 -0
- package/dist/@vitest/browser-preview/context.d.ts +1 -0
- package/dist/@vitest/browser-preview/index.d.ts +19 -0
- package/dist/@vitest/browser-preview/index.js +148 -0
- package/dist/@vitest/browser-preview/locators.js +79 -0
- package/dist/@vitest/browser-webdriverio/context.d.ts +1 -0
- package/dist/@vitest/browser-webdriverio/index.d.ts +63 -0
- package/dist/@vitest/browser-webdriverio/index.js +600 -0
- package/dist/@vitest/browser-webdriverio/locators.js +163 -0
- package/dist/@vitest/expect/index.d.ts +807 -0
- package/dist/@vitest/expect/index.js +1875 -0
- package/dist/@vitest/mocker/auto-register.d.ts +2 -0
- package/dist/@vitest/mocker/auto-register.js +9 -0
- package/dist/@vitest/mocker/automock.d.ts +12 -0
- package/dist/@vitest/mocker/automock.js +1 -0
- package/dist/@vitest/mocker/browser.d.ts +53 -0
- package/dist/@vitest/mocker/browser.js +91 -0
- package/dist/@vitest/mocker/chunk-automock.js +354 -0
- package/dist/@vitest/mocker/chunk-interceptor-native.js +15 -0
- package/dist/@vitest/mocker/chunk-mocker.js +521 -0
- package/dist/@vitest/mocker/chunk-pathe.M-eThtNZ.js +174 -0
- package/dist/@vitest/mocker/chunk-registry.js +185 -0
- package/dist/@vitest/mocker/chunk-utils.js +16 -0
- package/dist/@vitest/mocker/index.d-C-sLYZi-.d.ts +25 -0
- package/dist/@vitest/mocker/index.d.ts +2 -0
- package/dist/@vitest/mocker/index.js +185 -0
- package/dist/@vitest/mocker/mocker.d-TnKRhz7N.d.ts +81 -0
- package/dist/@vitest/mocker/node.d.ts +800 -0
- package/dist/@vitest/mocker/node.js +966 -0
- package/dist/@vitest/mocker/redirect.d.ts +3 -0
- package/dist/@vitest/mocker/redirect.js +79 -0
- package/dist/@vitest/mocker/register.d.ts +9 -0
- package/dist/@vitest/mocker/register.js +41 -0
- package/dist/@vitest/mocker/types.d-B8CCKmHt.d.ts +107 -0
- package/dist/@vitest/pretty-format/index.d.ts +124 -0
- package/dist/@vitest/pretty-format/index.js +1022 -0
- package/dist/@vitest/runner/chunk-tasks.js +340 -0
- package/dist/@vitest/runner/index.d.ts +180 -0
- package/dist/@vitest/runner/index.js +2114 -0
- package/dist/@vitest/runner/tasks.d-C7UxawJ9.d.ts +834 -0
- package/dist/@vitest/runner/types.d.ts +183 -0
- package/dist/@vitest/runner/types.js +1 -0
- package/dist/@vitest/runner/utils.d.ts +45 -0
- package/dist/@vitest/runner/utils.js +5 -0
- package/dist/@vitest/snapshot/environment.d-DHdQ1Csl.d.ts +22 -0
- package/dist/@vitest/snapshot/environment.d.ts +16 -0
- package/dist/@vitest/snapshot/environment.js +40 -0
- package/dist/@vitest/snapshot/index.d.ts +130 -0
- package/dist/@vitest/snapshot/index.js +1437 -0
- package/dist/@vitest/snapshot/manager.d.ts +18 -0
- package/dist/@vitest/snapshot/manager.js +73 -0
- package/dist/@vitest/snapshot/rawSnapshot.d-lFsMJFUd.d.ts +61 -0
- package/dist/@vitest/spy/index.d.ts +384 -0
- package/dist/@vitest/spy/index.js +433 -0
- package/dist/@vitest/utils/chunk-_commonjsHelpers.js +5 -0
- package/dist/@vitest/utils/chunk-pathe.M-eThtNZ.js +156 -0
- package/dist/@vitest/utils/constants.d.ts +21 -0
- package/dist/@vitest/utils/constants.js +49 -0
- package/dist/@vitest/utils/diff.d.ts +93 -0
- package/dist/@vitest/utils/diff.js +2199 -0
- package/dist/@vitest/utils/display.d.ts +29 -0
- package/dist/@vitest/utils/display.js +742 -0
- package/dist/@vitest/utils/error.d.ts +7 -0
- package/dist/@vitest/utils/error.js +42 -0
- package/dist/@vitest/utils/helpers.d.ts +73 -0
- package/dist/@vitest/utils/helpers.js +295 -0
- package/dist/@vitest/utils/highlight.d.ts +9 -0
- package/dist/@vitest/utils/highlight.js +538 -0
- package/dist/@vitest/utils/index.d.ts +5 -0
- package/dist/@vitest/utils/index.js +1 -0
- package/dist/@vitest/utils/offset.d.ts +5 -0
- package/dist/@vitest/utils/offset.js +32 -0
- package/dist/@vitest/utils/resolver.d.ts +7 -0
- package/dist/@vitest/utils/resolver.js +71 -0
- package/dist/@vitest/utils/serialize.d.ts +3 -0
- package/dist/@vitest/utils/serialize.js +118 -0
- package/dist/@vitest/utils/source-map.d.ts +55 -0
- package/dist/@vitest/utils/source-map.js +478 -0
- package/dist/@vitest/utils/timers.d.ts +33 -0
- package/dist/@vitest/utils/timers.js +49 -0
- package/dist/@vitest/utils/types.d-BCElaP-c.d.ts +53 -0
- package/dist/@vitest/utils/types.d.ts +34 -0
- package/dist/@vitest/utils/types.js +1 -0
- package/dist/browser-compat.js +3 -0
- package/dist/browser.d.ts +46 -0
- package/dist/browser.js +20 -0
- package/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -0
- package/dist/chunks/base.CJ0Y4ePK.js +165 -0
- package/dist/chunks/benchmark.B3N2zMcH.js +40 -0
- package/dist/chunks/benchmark.d.DAaHLpsq.d.ts +24 -0
- package/dist/chunks/browser.d.ChKACdzH.d.ts +59 -0
- package/dist/chunks/cac.DVeoLl0M.js +1409 -0
- package/dist/chunks/cli-api.B7PN_QUv.js +13672 -0
- package/dist/chunks/config.d.Cy95HiCx.d.ts +210 -0
- package/dist/chunks/console.Cf-YriPC.js +146 -0
- package/dist/chunks/constants.D_Q9UYh-.js +36 -0
- package/dist/chunks/coverage.AVPTjMgw.js +3292 -0
- package/dist/chunks/coverage.D_JHT54q.js +25 -0
- package/dist/chunks/coverage.d.BZtK59WP.d.ts +37 -0
- package/dist/chunks/creator.DAmOKTvJ.js +673 -0
- package/dist/chunks/date.Bq6ZW5rf.js +73 -0
- package/dist/chunks/defaults.BOqNVLsY.js +74 -0
- package/dist/chunks/env.D4Lgay0q.js +8 -0
- package/dist/chunks/environment.d.CrsxCzP1.d.ts +29 -0
- package/dist/chunks/evaluatedModules.Dg1zASAC.js +17 -0
- package/dist/chunks/evaluatedModules.d.BxJ5omdx.d.ts +7 -0
- package/dist/chunks/git.Bm2pzPAa.js +71 -0
- package/dist/chunks/global.d.B15mdLcR.d.ts +99 -0
- package/dist/chunks/globals.DOayXfHP.js +30 -0
- package/dist/chunks/index.6Qv1eEA6.js +109 -0
- package/dist/chunks/index.C5r1PdPD.js +231 -0
- package/dist/chunks/index.Chj8NDwU.js +206 -0
- package/dist/chunks/index.CyBMJtT7.js +727 -0
- package/dist/chunks/index.D3XRDfWc.js +213 -0
- package/dist/chunks/index.D4KonVSU.js +6343 -0
- package/dist/chunks/index.M8mOzt4Y.js +3839 -0
- package/dist/chunks/index.Z5E_ObnR.js +37 -0
- package/dist/chunks/init-forks._y3TW739.js +41 -0
- package/dist/chunks/init-threads.DBO2kn-p.js +18 -0
- package/dist/chunks/init.B6MLFIaN.js +334 -0
- package/dist/chunks/inspector.CvyFGlXm.js +53 -0
- package/dist/chunks/modules.BJuCwlRJ.js +36 -0
- package/dist/chunks/node.Ce0vMQM7.js +14 -0
- package/dist/chunks/plugin.d.CtqpEehP.d.ts +38 -0
- package/dist/chunks/reporters.d.CWXNI2jG.d.ts +3271 -0
- package/dist/chunks/rpc.BoxB0q7B.js +76 -0
- package/dist/chunks/rpc.d.RH3apGEf.d.ts +64 -0
- package/dist/chunks/setup-common.Cm-kSBVi.js +60 -0
- package/dist/chunks/startModuleRunner.DEj0jb3e.js +861 -0
- package/dist/chunks/suite.d.BJWk38HB.d.ts +10 -0
- package/dist/chunks/test.B8ej_ZHS.js +254 -0
- package/dist/chunks/traces.CCmnQaNT.js +217 -0
- package/dist/chunks/traces.d.402V_yFI.d.ts +18 -0
- package/dist/chunks/utils.DvEY5TfP.js +52 -0
- package/dist/chunks/vi.2VT5v0um.js +3919 -0
- package/dist/chunks/vm.D3epNOPZ.js +744 -0
- package/dist/chunks/worker.d.Dyxm8DEL.d.ts +255 -0
- package/dist/cli.js +28 -0
- package/dist/client/.vite/manifest.json +24 -0
- package/dist/client/__vitest__/assets/index-BUCFJtth.js +57 -0
- package/dist/client/__vitest__/assets/index-DlhE0rqZ.css +1 -0
- package/dist/client/__vitest__/bg.png +0 -0
- package/dist/client/__vitest__/favicon.ico +0 -0
- package/dist/client/__vitest__/favicon.svg +5 -0
- package/dist/client/__vitest__/index.html +32 -0
- package/dist/client/__vitest_browser__/orchestrator-S_3e_uzt.js +345 -0
- package/dist/client/__vitest_browser__/tester-k74mgIRa.js +2171 -0
- package/dist/client/__vitest_browser__/utils-uxqdqUz8.js +223 -0
- package/dist/client/error-catcher.js +82 -0
- package/dist/client/esm-client-injector.js +67 -0
- package/dist/client/favicon.svg +5 -0
- package/dist/client/orchestrator.html +35 -0
- package/dist/client/tester/tester.html +13 -0
- package/dist/client.js +456 -0
- package/dist/config.cjs +94 -0
- package/dist/config.d.ts +104 -0
- package/dist/config.js +15 -0
- package/dist/context.js +541 -0
- package/dist/coverage.d.ts +118 -0
- package/dist/coverage.js +23 -0
- package/dist/dummy.js +2 -0
- package/dist/environments.d.ts +22 -0
- package/dist/environments.js +3 -0
- package/dist/expect-element.js +27 -0
- package/dist/index-D6m36C6U.js +6 -0
- package/dist/index-node.js +7 -0
- package/dist/index.d.ts +510 -0
- package/dist/index.js +19 -0
- package/dist/locators.d.ts +354 -0
- package/dist/locators.js +1 -0
- package/dist/mocker.d.ts +1 -0
- package/dist/mocker.js +1 -0
- package/dist/module-evaluator.d.ts +124 -0
- package/dist/module-evaluator.js +343 -0
- package/dist/module-runner-stub.js +44 -0
- package/dist/module-runner.js +17 -0
- package/dist/node.d.ts +251 -0
- package/dist/node.js +98 -0
- package/dist/path.js +7 -0
- package/dist/plugins/browser-client.mjs +2 -0
- package/dist/plugins/browser-context.mjs +2 -0
- package/dist/plugins/browser-locators.mjs +2 -0
- package/dist/plugins/browser-playwright.mjs +2 -0
- package/dist/plugins/browser-preview.mjs +2 -0
- package/dist/plugins/browser-webdriverio.mjs +2 -0
- package/dist/plugins/browser.mjs +2 -0
- package/dist/plugins/expect.mjs +2 -0
- package/dist/plugins/mocker-automock.mjs +2 -0
- package/dist/plugins/mocker-browser.mjs +2 -0
- package/dist/plugins/mocker-node.mjs +2 -0
- package/dist/plugins/mocker-redirect.mjs +2 -0
- package/dist/plugins/mocker-register.mjs +2 -0
- package/dist/plugins/mocker.mjs +2 -0
- package/dist/plugins/pretty-format.mjs +2 -0
- package/dist/plugins/runner-types.mjs +2 -0
- package/dist/plugins/runner-utils.mjs +2 -0
- package/dist/plugins/runner.mjs +2 -0
- package/dist/plugins/snapshot-environment.mjs +2 -0
- package/dist/plugins/snapshot-manager.mjs +2 -0
- package/dist/plugins/snapshot.mjs +2 -0
- package/dist/plugins/spy.mjs +2 -0
- package/dist/plugins/utils-constants.mjs +2 -0
- package/dist/plugins/utils-diff.mjs +2 -0
- package/dist/plugins/utils-display.mjs +2 -0
- package/dist/plugins/utils-error.mjs +2 -0
- package/dist/plugins/utils-helpers.mjs +2 -0
- package/dist/plugins/utils-highlight.mjs +2 -0
- package/dist/plugins/utils-offset.mjs +2 -0
- package/dist/plugins/utils-resolver.mjs +2 -0
- package/dist/plugins/utils-serialize.mjs +2 -0
- package/dist/plugins/utils-source-map.mjs +2 -0
- package/dist/plugins/utils-timers.mjs +2 -0
- package/dist/plugins/utils.mjs +2 -0
- package/dist/reporters.d.ts +27 -0
- package/dist/reporters.js +24 -0
- package/dist/runners.d.ts +50 -0
- package/dist/runners.js +19 -0
- package/dist/shared/screenshotMatcher/types.d.ts +22 -0
- package/dist/snapshot.d.ts +9 -0
- package/dist/snapshot.js +4 -0
- package/dist/spy.js +1 -0
- package/dist/state.js +280 -0
- package/dist/suite.d.ts +5 -0
- package/dist/suite.js +6 -0
- package/dist/types.d.ts +69 -0
- package/dist/vendor/chai.d.mts +1 -0
- package/dist/vendor/chai.mjs +3577 -0
- package/dist/vendor/es-module-lexer.d.mts +193 -0
- package/dist/vendor/es-module-lexer.mjs +79 -0
- package/dist/vendor/estree-walker.d.mts +583 -0
- package/dist/vendor/estree-walker.mjs +339 -0
- package/dist/vendor/expect-type.d.mts +1574 -0
- package/dist/vendor/expect-type.mjs +214 -0
- package/dist/vendor/magic-string.d.mts +261 -0
- package/dist/vendor/magic-string.mjs +1700 -0
- package/dist/vendor/obug.d.mts +56 -0
- package/dist/vendor/obug.mjs +276 -0
- package/dist/vendor/pathe.d.mts +46 -0
- package/dist/vendor/pathe.mjs +496 -0
- package/dist/vendor/picomatch.d.mts +1 -0
- package/dist/vendor/picomatch.mjs +1855 -0
- package/dist/vendor/shared-3g9mwCWP.mjs +31 -0
- package/dist/vendor/std-env.d.mts +88 -0
- package/dist/vendor/std-env.mjs +159 -0
- package/dist/vendor/tinybench.d.mts +317 -0
- package/dist/vendor/tinybench.mjs +504 -0
- package/dist/vendor/tinyexec.d.mts +72 -0
- package/dist/vendor/tinyexec.mjs +637 -0
- package/dist/vendor/tinyglobby.d.mts +157 -0
- package/dist/vendor/tinyglobby.mjs +832 -0
- package/dist/vendor/tinyrainbow.d.mts +60 -0
- package/dist/vendor/tinyrainbow.mjs +93 -0
- package/dist/vendor/vitest_browser.mjs +2 -0
- package/dist/vendor/vitest_internal_browser.mjs +2 -0
- package/dist/vendor/vitest_runner.mjs +2 -0
- package/dist/vendor/vitest_runners.mjs +2 -0
- package/dist/worker.d.ts +32 -0
- package/dist/worker.js +48 -0
- package/dist/workers/forks.js +54 -0
- package/dist/workers/runVmTests.js +95 -0
- package/dist/workers/threads.js +55 -0
- package/dist/workers/vmForks.js +36 -0
- package/dist/workers/vmThreads.js +37 -0
- package/environments.d.ts +1 -0
- package/globals.d.ts +20 -0
- package/import-meta.d.ts +5 -0
- package/importMeta.d.ts +4 -0
- package/index.cjs +5 -0
- package/index.d.cts +1 -0
- package/jsdom.d.ts +6 -0
- package/mocker.d.ts +1 -0
- package/node.d.ts +1 -0
- package/optional-types.d.ts +7 -0
- package/package.json +335 -0
- package/reporters.d.ts +1 -0
- package/runners.d.ts +1 -0
- package/snapshot.d.ts +1 -0
- package/suite.d.ts +1 -0
- package/suppress-warnings.cjs +21 -0
- package/vitest.mjs +2 -0
- package/worker.d.ts +1 -0
|
@@ -0,0 +1,861 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { isBareImport } from '../@vitest/utils/helpers.js';
|
|
3
|
+
import { i as isBuiltin, a as isBrowserExternal, t as toBuiltin } from './modules.BJuCwlRJ.js';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { normalize as normalize$1, join as join$1 } from '../vendor/pathe.mjs';
|
|
6
|
+
import { distDir } from '../path.js';
|
|
7
|
+
import { serializeValue } from '../@vitest/utils/serialize.js';
|
|
8
|
+
import { VitestModuleEvaluator, unwrapId } from '../module-evaluator.js';
|
|
9
|
+
import { resolve as resolve$1, isAbsolute as isAbsolute$1 } from 'node:path';
|
|
10
|
+
import vm from 'node:vm';
|
|
11
|
+
import { MockerRegistry, mockObject, RedirectedModule, AutomockedModule } from '../@vitest/mocker/index.js';
|
|
12
|
+
import nodeModule from 'node:module';
|
|
13
|
+
import * as viteModuleRunner from '@voidzero-dev/vite-plus-core/module-runner';
|
|
14
|
+
import { T as Traces } from './traces.CCmnQaNT.js';
|
|
15
|
+
|
|
16
|
+
class VitestTransport {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
async invoke(event) {
|
|
21
|
+
if (event.type !== "custom") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support Vite HMR events.`) };
|
|
22
|
+
if (event.event !== "vite:invoke") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support ${event.event} event.`) };
|
|
23
|
+
const { name, data } = event.data;
|
|
24
|
+
if (name === "getBuiltins")
|
|
25
|
+
// we return an empty array here to avoid client-side builtin check,
|
|
26
|
+
// as we need builtins to go through `fetchModule`
|
|
27
|
+
return { result: [] };
|
|
28
|
+
if (name !== "fetchModule") return { error: /* @__PURE__ */ new Error(`Unknown method: ${name}. Expected "fetchModule".`) };
|
|
29
|
+
try {
|
|
30
|
+
return { result: await this.options.fetchModule(...data) };
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return { error };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
38
|
+
function normalizeWindowsPath(input = "") {
|
|
39
|
+
if (!input) return input;
|
|
40
|
+
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
41
|
+
}
|
|
42
|
+
const _UNC_REGEX = /^[/\\]{2}/;
|
|
43
|
+
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
44
|
+
const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
45
|
+
const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
|
|
46
|
+
const normalize = function(path) {
|
|
47
|
+
if (path.length === 0) return ".";
|
|
48
|
+
path = normalizeWindowsPath(path);
|
|
49
|
+
const isUNCPath = path.match(_UNC_REGEX);
|
|
50
|
+
const isPathAbsolute = isAbsolute(path);
|
|
51
|
+
const trailingSeparator = path[path.length - 1] === "/";
|
|
52
|
+
path = normalizeString(path, !isPathAbsolute);
|
|
53
|
+
if (path.length === 0) {
|
|
54
|
+
if (isPathAbsolute) return "/";
|
|
55
|
+
return trailingSeparator ? "./" : ".";
|
|
56
|
+
}
|
|
57
|
+
if (trailingSeparator) path += "/";
|
|
58
|
+
if (_DRIVE_LETTER_RE.test(path)) path += "/";
|
|
59
|
+
if (isUNCPath) {
|
|
60
|
+
if (!isPathAbsolute) return `//./${path}`;
|
|
61
|
+
return `//${path}`;
|
|
62
|
+
}
|
|
63
|
+
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
64
|
+
};
|
|
65
|
+
const join = function(...segments) {
|
|
66
|
+
let path = "";
|
|
67
|
+
for (const seg of segments) {
|
|
68
|
+
if (!seg) continue;
|
|
69
|
+
if (path.length > 0) {
|
|
70
|
+
const pathTrailing = path[path.length - 1] === "/";
|
|
71
|
+
const segLeading = seg[0] === "/";
|
|
72
|
+
if (pathTrailing && segLeading) path += seg.slice(1);
|
|
73
|
+
else path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
74
|
+
} else path += seg;
|
|
75
|
+
}
|
|
76
|
+
return normalize(path);
|
|
77
|
+
};
|
|
78
|
+
function cwd$1() {
|
|
79
|
+
if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
|
|
80
|
+
return "/";
|
|
81
|
+
}
|
|
82
|
+
const resolve = function(...arguments_) {
|
|
83
|
+
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
84
|
+
let resolvedPath = "";
|
|
85
|
+
let resolvedAbsolute = false;
|
|
86
|
+
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
87
|
+
const path = index >= 0 ? arguments_[index] : cwd$1();
|
|
88
|
+
if (!path || path.length === 0) continue;
|
|
89
|
+
resolvedPath = `${path}/${resolvedPath}`;
|
|
90
|
+
resolvedAbsolute = isAbsolute(path);
|
|
91
|
+
}
|
|
92
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
93
|
+
if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
|
|
94
|
+
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
95
|
+
};
|
|
96
|
+
function normalizeString(path, allowAboveRoot) {
|
|
97
|
+
let res = "";
|
|
98
|
+
let lastSegmentLength = 0;
|
|
99
|
+
let lastSlash = -1;
|
|
100
|
+
let dots = 0;
|
|
101
|
+
let char = null;
|
|
102
|
+
for (let index = 0; index <= path.length; ++index) {
|
|
103
|
+
if (index < path.length) char = path[index];
|
|
104
|
+
else if (char === "/") break;
|
|
105
|
+
else char = "/";
|
|
106
|
+
if (char === "/") {
|
|
107
|
+
if (lastSlash === index - 1 || dots === 1);
|
|
108
|
+
else if (dots === 2) {
|
|
109
|
+
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
110
|
+
if (res.length > 2) {
|
|
111
|
+
const lastSlashIndex = res.lastIndexOf("/");
|
|
112
|
+
if (lastSlashIndex === -1) {
|
|
113
|
+
res = "";
|
|
114
|
+
lastSegmentLength = 0;
|
|
115
|
+
} else {
|
|
116
|
+
res = res.slice(0, lastSlashIndex);
|
|
117
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
118
|
+
}
|
|
119
|
+
lastSlash = index;
|
|
120
|
+
dots = 0;
|
|
121
|
+
continue;
|
|
122
|
+
} else if (res.length > 0) {
|
|
123
|
+
res = "";
|
|
124
|
+
lastSegmentLength = 0;
|
|
125
|
+
lastSlash = index;
|
|
126
|
+
dots = 0;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (allowAboveRoot) {
|
|
131
|
+
res += res.length > 0 ? "/.." : "..";
|
|
132
|
+
lastSegmentLength = 2;
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`;
|
|
136
|
+
else res = path.slice(lastSlash + 1, index);
|
|
137
|
+
lastSegmentLength = index - lastSlash - 1;
|
|
138
|
+
}
|
|
139
|
+
lastSlash = index;
|
|
140
|
+
dots = 0;
|
|
141
|
+
} else if (char === "." && dots !== -1) ++dots;
|
|
142
|
+
else dots = -1;
|
|
143
|
+
}
|
|
144
|
+
return res;
|
|
145
|
+
}
|
|
146
|
+
const isAbsolute = function(p) {
|
|
147
|
+
return _IS_ABSOLUTE_RE.test(p);
|
|
148
|
+
};
|
|
149
|
+
const extname = function(p) {
|
|
150
|
+
if (p === "..") return "";
|
|
151
|
+
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
|
|
152
|
+
return match && match[1] || "";
|
|
153
|
+
};
|
|
154
|
+
const dirname = function(p) {
|
|
155
|
+
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
156
|
+
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
|
|
157
|
+
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
158
|
+
};
|
|
159
|
+
const basename = function(p, extension) {
|
|
160
|
+
const segments = normalizeWindowsPath(p).split("/");
|
|
161
|
+
let lastSegment = "";
|
|
162
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
163
|
+
const val = segments[i];
|
|
164
|
+
if (val) {
|
|
165
|
+
lastSegment = val;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const { existsSync, readdirSync, statSync } = fs;
|
|
173
|
+
function findMockRedirect(root, mockPath, external) {
|
|
174
|
+
const path = external || mockPath;
|
|
175
|
+
// it's a node_module alias
|
|
176
|
+
// all mocks should be inside <root>/__mocks__
|
|
177
|
+
if (external || isNodeBuiltin(mockPath) || !existsSync(mockPath)) {
|
|
178
|
+
const mockFolder = join(root, "__mocks__", dirname(path));
|
|
179
|
+
if (!existsSync(mockFolder)) return null;
|
|
180
|
+
const baseOriginal = basename(path);
|
|
181
|
+
function findFile(mockFolder, baseOriginal) {
|
|
182
|
+
const files = readdirSync(mockFolder);
|
|
183
|
+
for (const file of files) if (basename(file, extname(file)) === baseOriginal) {
|
|
184
|
+
const path = resolve(mockFolder, file);
|
|
185
|
+
// if the same name, return the file
|
|
186
|
+
if (statSync(path).isFile()) return path;
|
|
187
|
+
else {
|
|
188
|
+
// find folder/index.{js,ts}
|
|
189
|
+
const indexFile = findFile(path, "index");
|
|
190
|
+
if (indexFile) return indexFile;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
return findFile(mockFolder, baseOriginal);
|
|
196
|
+
}
|
|
197
|
+
const fullPath = resolve(dirname(path), "__mocks__", basename(path));
|
|
198
|
+
return existsSync(fullPath) ? fullPath : null;
|
|
199
|
+
}
|
|
200
|
+
const builtins = new Set([
|
|
201
|
+
...nodeModule.builtinModules,
|
|
202
|
+
"assert/strict",
|
|
203
|
+
"diagnostics_channel",
|
|
204
|
+
"dns/promises",
|
|
205
|
+
"fs/promises",
|
|
206
|
+
"path/posix",
|
|
207
|
+
"path/win32",
|
|
208
|
+
"readline/promises",
|
|
209
|
+
"stream/consumers",
|
|
210
|
+
"stream/promises",
|
|
211
|
+
"stream/web",
|
|
212
|
+
"timers/promises",
|
|
213
|
+
"util/types",
|
|
214
|
+
"wasi"
|
|
215
|
+
]);
|
|
216
|
+
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
|
|
217
|
+
const prefixedBuiltins$1 = new Set([
|
|
218
|
+
"node:sea",
|
|
219
|
+
"node:sqlite",
|
|
220
|
+
"node:test",
|
|
221
|
+
"node:test/reporters"
|
|
222
|
+
]);
|
|
223
|
+
const NODE_BUILTIN_NAMESPACE = "node:";
|
|
224
|
+
function isNodeBuiltin(id) {
|
|
225
|
+
// Added in v18.6.0
|
|
226
|
+
if (nodeModule.isBuiltin) return nodeModule.isBuiltin(id);
|
|
227
|
+
if (prefixedBuiltins$1.has(id)) return true;
|
|
228
|
+
return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const spyModulePath = resolve$1(distDir, "spy.js");
|
|
232
|
+
class VitestMocker {
|
|
233
|
+
static pendingIds = [];
|
|
234
|
+
spyModule;
|
|
235
|
+
primitives;
|
|
236
|
+
filterPublicKeys;
|
|
237
|
+
registries = /* @__PURE__ */ new Map();
|
|
238
|
+
mockContext = { callstack: null };
|
|
239
|
+
_otel;
|
|
240
|
+
constructor(moduleRunner, options) {
|
|
241
|
+
this.moduleRunner = moduleRunner;
|
|
242
|
+
this.options = options;
|
|
243
|
+
const context = this.options.context;
|
|
244
|
+
this._otel = options.traces;
|
|
245
|
+
if (context) this.primitives = vm.runInContext("({ Object, Error, Function, RegExp, Symbol, Array, Map })", context);
|
|
246
|
+
else this.primitives = {
|
|
247
|
+
Object,
|
|
248
|
+
Error,
|
|
249
|
+
Function,
|
|
250
|
+
RegExp,
|
|
251
|
+
Symbol: globalThis.Symbol,
|
|
252
|
+
Array,
|
|
253
|
+
Map
|
|
254
|
+
};
|
|
255
|
+
if (options.spyModule) this.spyModule = options.spyModule;
|
|
256
|
+
const Symbol = this.primitives.Symbol;
|
|
257
|
+
this.filterPublicKeys = [
|
|
258
|
+
"__esModule",
|
|
259
|
+
Symbol.asyncIterator,
|
|
260
|
+
Symbol.hasInstance,
|
|
261
|
+
Symbol.isConcatSpreadable,
|
|
262
|
+
Symbol.iterator,
|
|
263
|
+
Symbol.match,
|
|
264
|
+
Symbol.matchAll,
|
|
265
|
+
Symbol.replace,
|
|
266
|
+
Symbol.search,
|
|
267
|
+
Symbol.split,
|
|
268
|
+
Symbol.species,
|
|
269
|
+
Symbol.toPrimitive,
|
|
270
|
+
Symbol.toStringTag,
|
|
271
|
+
Symbol.unscopables
|
|
272
|
+
];
|
|
273
|
+
}
|
|
274
|
+
get root() {
|
|
275
|
+
return this.options.root;
|
|
276
|
+
}
|
|
277
|
+
get evaluatedModules() {
|
|
278
|
+
return this.moduleRunner.evaluatedModules;
|
|
279
|
+
}
|
|
280
|
+
get moduleDirectories() {
|
|
281
|
+
return this.options.moduleDirectories || [];
|
|
282
|
+
}
|
|
283
|
+
async initializeSpyModule() {
|
|
284
|
+
if (this.spyModule) return;
|
|
285
|
+
this.spyModule = await this.moduleRunner.import(spyModulePath);
|
|
286
|
+
}
|
|
287
|
+
getMockerRegistry() {
|
|
288
|
+
const suite = this.getSuiteFilepath();
|
|
289
|
+
if (!this.registries.has(suite)) this.registries.set(suite, new MockerRegistry());
|
|
290
|
+
return this.registries.get(suite);
|
|
291
|
+
}
|
|
292
|
+
reset() {
|
|
293
|
+
this.registries.clear();
|
|
294
|
+
}
|
|
295
|
+
invalidateModuleById(id) {
|
|
296
|
+
const mockId = this.getMockPath(id);
|
|
297
|
+
const node = this.evaluatedModules.getModuleById(mockId);
|
|
298
|
+
if (node) {
|
|
299
|
+
this.evaluatedModules.invalidateModule(node);
|
|
300
|
+
node.mockedExports = void 0;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
isModuleDirectory(path) {
|
|
304
|
+
return this.moduleDirectories.some((dir) => path.includes(dir));
|
|
305
|
+
}
|
|
306
|
+
getSuiteFilepath() {
|
|
307
|
+
return this.options.getCurrentTestFilepath() || "global";
|
|
308
|
+
}
|
|
309
|
+
createError(message, codeFrame) {
|
|
310
|
+
const Error = this.primitives.Error;
|
|
311
|
+
const error = new Error(message);
|
|
312
|
+
Object.assign(error, { codeFrame });
|
|
313
|
+
return error;
|
|
314
|
+
}
|
|
315
|
+
async resolveId(rawId, importer) {
|
|
316
|
+
return this._otel.$("vitest.mocker.resolve_id", { attributes: {
|
|
317
|
+
"vitest.module.raw_id": rawId,
|
|
318
|
+
"vitest.module.importer": rawId
|
|
319
|
+
} }, async (span) => {
|
|
320
|
+
const result = await this.options.resolveId(rawId, importer);
|
|
321
|
+
if (!result) {
|
|
322
|
+
span.addEvent("could not resolve id, fallback to unresolved values");
|
|
323
|
+
const id = normalizeModuleId(rawId);
|
|
324
|
+
span.setAttributes({
|
|
325
|
+
"vitest.module.id": id,
|
|
326
|
+
"vitest.module.url": rawId,
|
|
327
|
+
"vitest.module.external": id,
|
|
328
|
+
"vitest.module.fallback": true
|
|
329
|
+
});
|
|
330
|
+
return {
|
|
331
|
+
id,
|
|
332
|
+
url: rawId,
|
|
333
|
+
external: id
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
// external is node_module or unresolved module
|
|
337
|
+
// for example, some people mock "vscode" and don't have it installed
|
|
338
|
+
const external = !isAbsolute$1(result.file) || this.isModuleDirectory(result.file) ? normalizeModuleId(rawId) : null;
|
|
339
|
+
const id = normalizeModuleId(result.id);
|
|
340
|
+
span.setAttributes({
|
|
341
|
+
"vitest.module.id": id,
|
|
342
|
+
"vitest.module.url": result.url,
|
|
343
|
+
"vitest.module.external": external ?? false
|
|
344
|
+
});
|
|
345
|
+
return {
|
|
346
|
+
...result,
|
|
347
|
+
id,
|
|
348
|
+
external
|
|
349
|
+
};
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
async resolveMocks() {
|
|
353
|
+
if (!VitestMocker.pendingIds.length) return;
|
|
354
|
+
await Promise.all(VitestMocker.pendingIds.map(async (mock) => {
|
|
355
|
+
const { id, url, external } = await this.resolveId(mock.id, mock.importer);
|
|
356
|
+
if (mock.action === "unmock") this.unmockPath(id);
|
|
357
|
+
if (mock.action === "mock") this.mockPath(mock.id, id, url, external, mock.type, mock.factory);
|
|
358
|
+
}));
|
|
359
|
+
VitestMocker.pendingIds = [];
|
|
360
|
+
}
|
|
361
|
+
ensureModule(id, url) {
|
|
362
|
+
const node = this.evaluatedModules.ensureModule(id, url);
|
|
363
|
+
// TODO
|
|
364
|
+
node.meta = {
|
|
365
|
+
id,
|
|
366
|
+
url,
|
|
367
|
+
code: "",
|
|
368
|
+
file: null,
|
|
369
|
+
invalidate: false
|
|
370
|
+
};
|
|
371
|
+
return node;
|
|
372
|
+
}
|
|
373
|
+
async callFunctionMock(id, url, mock) {
|
|
374
|
+
const node = this.ensureModule(id, url);
|
|
375
|
+
if (node.exports) return node.exports;
|
|
376
|
+
const exports$1 = await mock.resolve();
|
|
377
|
+
const moduleExports = new Proxy(exports$1, { get: (target, prop) => {
|
|
378
|
+
const val = target[prop];
|
|
379
|
+
// 'then' can exist on non-Promise objects, need nested instanceof check for logic to work
|
|
380
|
+
if (prop === "then") {
|
|
381
|
+
if (target instanceof Promise) return target.then.bind(target);
|
|
382
|
+
} else if (!(prop in target)) {
|
|
383
|
+
if (this.filterPublicKeys.includes(prop)) return;
|
|
384
|
+
throw this.createError(`[vitest] No "${String(prop)}" export is defined on the "${mock.raw}" mock. Did you forget to return it from "vi.mock"?
|
|
385
|
+
If you need to partially mock a module, you can use "importOriginal" helper inside:
|
|
386
|
+
`, `vi.mock(import("${mock.raw}"), async (importOriginal) => {
|
|
387
|
+
const actual = await importOriginal()
|
|
388
|
+
return {
|
|
389
|
+
...actual,
|
|
390
|
+
// your mocked methods
|
|
391
|
+
}
|
|
392
|
+
})`);
|
|
393
|
+
}
|
|
394
|
+
return val;
|
|
395
|
+
} });
|
|
396
|
+
node.exports = moduleExports;
|
|
397
|
+
return moduleExports;
|
|
398
|
+
}
|
|
399
|
+
// public method to avoid circular dependency
|
|
400
|
+
getMockContext() {
|
|
401
|
+
return this.mockContext;
|
|
402
|
+
}
|
|
403
|
+
// path used to store mocked dependencies
|
|
404
|
+
getMockPath(dep) {
|
|
405
|
+
return `mock:${dep}`;
|
|
406
|
+
}
|
|
407
|
+
getDependencyMock(id) {
|
|
408
|
+
return this.getMockerRegistry().getById(fixLeadingSlashes(id));
|
|
409
|
+
}
|
|
410
|
+
findMockRedirect(mockPath, external) {
|
|
411
|
+
return findMockRedirect(this.root, mockPath, external);
|
|
412
|
+
}
|
|
413
|
+
mockObject(object, mockExports = {}, behavior = "automock") {
|
|
414
|
+
const createMockInstance = this.spyModule?.createMockInstance;
|
|
415
|
+
if (!createMockInstance) throw this.createError("[vitest] `spyModule` is not defined. This is a Vitest error. Please open a new issue with reproduction.");
|
|
416
|
+
return mockObject({
|
|
417
|
+
globalConstructors: this.primitives,
|
|
418
|
+
createMockInstance,
|
|
419
|
+
type: behavior
|
|
420
|
+
}, object, mockExports);
|
|
421
|
+
}
|
|
422
|
+
unmockPath(id) {
|
|
423
|
+
this.getMockerRegistry().deleteById(id);
|
|
424
|
+
this.invalidateModuleById(id);
|
|
425
|
+
}
|
|
426
|
+
mockPath(originalId, id, url, external, mockType, factory) {
|
|
427
|
+
const registry = this.getMockerRegistry();
|
|
428
|
+
if (mockType === "manual") registry.register("manual", originalId, id, url, factory);
|
|
429
|
+
else if (mockType === "autospy") registry.register("autospy", originalId, id, url);
|
|
430
|
+
else {
|
|
431
|
+
const redirect = this.findMockRedirect(id, external);
|
|
432
|
+
if (redirect) registry.register("redirect", originalId, id, url, redirect);
|
|
433
|
+
else registry.register("automock", originalId, id, url);
|
|
434
|
+
}
|
|
435
|
+
// every time the mock is registered, we remove the previous one from the cache
|
|
436
|
+
this.invalidateModuleById(id);
|
|
437
|
+
}
|
|
438
|
+
async importActual(rawId, importer, callstack) {
|
|
439
|
+
const { url } = await this.resolveId(rawId, importer);
|
|
440
|
+
const node = await this.moduleRunner.fetchModule(url, importer);
|
|
441
|
+
return await this.moduleRunner.cachedRequest(node.url, node, callstack || [importer], void 0, true);
|
|
442
|
+
}
|
|
443
|
+
async importMock(rawId, importer) {
|
|
444
|
+
const { id, url, external } = await this.resolveId(rawId, importer);
|
|
445
|
+
let mock = this.getDependencyMock(id);
|
|
446
|
+
if (!mock) {
|
|
447
|
+
const redirect = this.findMockRedirect(id, external);
|
|
448
|
+
if (redirect) mock = new RedirectedModule(rawId, id, rawId, redirect);
|
|
449
|
+
else mock = new AutomockedModule(rawId, id, rawId);
|
|
450
|
+
}
|
|
451
|
+
if (mock.type === "automock" || mock.type === "autospy") {
|
|
452
|
+
const node = await this.moduleRunner.fetchModule(url, importer);
|
|
453
|
+
const mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true);
|
|
454
|
+
const Object = this.primitives.Object;
|
|
455
|
+
return this.mockObject(mod, Object.create(Object.prototype), mock.type);
|
|
456
|
+
}
|
|
457
|
+
if (mock.type === "manual") return this.callFunctionMock(id, url, mock);
|
|
458
|
+
const node = await this.moduleRunner.fetchModule(mock.redirect);
|
|
459
|
+
return this.moduleRunner.cachedRequest(mock.redirect, node, [importer], void 0, true);
|
|
460
|
+
}
|
|
461
|
+
async requestWithMockedModule(url, evaluatedNode, callstack, mock) {
|
|
462
|
+
return this._otel.$("vitest.mocker.evaluate", async (span) => {
|
|
463
|
+
const mockId = this.getMockPath(evaluatedNode.id);
|
|
464
|
+
span.setAttributes({
|
|
465
|
+
"vitest.module.id": mockId,
|
|
466
|
+
"vitest.mock.type": mock.type,
|
|
467
|
+
"vitest.mock.id": mock.id,
|
|
468
|
+
"vitest.mock.url": mock.url,
|
|
469
|
+
"vitest.mock.raw": mock.raw
|
|
470
|
+
});
|
|
471
|
+
if (mock.type === "automock" || mock.type === "autospy") {
|
|
472
|
+
const cache = this.evaluatedModules.getModuleById(mockId);
|
|
473
|
+
if (cache && cache.mockedExports) return cache.mockedExports;
|
|
474
|
+
const Object = this.primitives.Object;
|
|
475
|
+
// we have to define a separate object that will copy all properties into itself
|
|
476
|
+
// and can't just use the same `exports` define automatically by Vite before the evaluator
|
|
477
|
+
const exports$1 = Object.create(null);
|
|
478
|
+
Object.defineProperty(exports$1, Symbol.toStringTag, {
|
|
479
|
+
value: "Module",
|
|
480
|
+
configurable: true,
|
|
481
|
+
writable: true
|
|
482
|
+
});
|
|
483
|
+
const node = this.ensureModule(mockId, this.getMockPath(evaluatedNode.url));
|
|
484
|
+
node.meta = evaluatedNode.meta;
|
|
485
|
+
node.file = evaluatedNode.file;
|
|
486
|
+
node.mockedExports = exports$1;
|
|
487
|
+
const mod = await this.moduleRunner.cachedRequest(url, node, callstack, void 0, true);
|
|
488
|
+
this.mockObject(mod, exports$1, mock.type);
|
|
489
|
+
return exports$1;
|
|
490
|
+
}
|
|
491
|
+
if (mock.type === "manual" && !callstack.includes(mockId) && !callstack.includes(url)) try {
|
|
492
|
+
callstack.push(mockId);
|
|
493
|
+
// this will not work if user does Promise.all(import(), import())
|
|
494
|
+
// we can also use AsyncLocalStorage to store callstack, but this won't work in the browser
|
|
495
|
+
// maybe we should improve mock API in the future?
|
|
496
|
+
this.mockContext.callstack = callstack;
|
|
497
|
+
return await this.callFunctionMock(mockId, this.getMockPath(url), mock);
|
|
498
|
+
} finally {
|
|
499
|
+
this.mockContext.callstack = null;
|
|
500
|
+
const indexMock = callstack.indexOf(mockId);
|
|
501
|
+
callstack.splice(indexMock, 1);
|
|
502
|
+
}
|
|
503
|
+
else if (mock.type === "redirect" && !callstack.includes(mock.redirect)) {
|
|
504
|
+
span.setAttribute("vitest.mock.redirect", mock.redirect);
|
|
505
|
+
return mock.redirect;
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
async mockedRequest(url, evaluatedNode, callstack) {
|
|
510
|
+
const mock = this.getDependencyMock(evaluatedNode.id);
|
|
511
|
+
if (!mock) return;
|
|
512
|
+
return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
|
|
513
|
+
}
|
|
514
|
+
queueMock(id, importer, factoryOrOptions) {
|
|
515
|
+
const mockType = getMockType(factoryOrOptions);
|
|
516
|
+
VitestMocker.pendingIds.push({
|
|
517
|
+
action: "mock",
|
|
518
|
+
id,
|
|
519
|
+
importer,
|
|
520
|
+
factory: typeof factoryOrOptions === "function" ? factoryOrOptions : void 0,
|
|
521
|
+
type: mockType
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
queueUnmock(id, importer) {
|
|
525
|
+
VitestMocker.pendingIds.push({
|
|
526
|
+
action: "unmock",
|
|
527
|
+
id,
|
|
528
|
+
importer
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function getMockType(factoryOrOptions) {
|
|
533
|
+
if (!factoryOrOptions) return "automock";
|
|
534
|
+
if (typeof factoryOrOptions === "function") return "manual";
|
|
535
|
+
return factoryOrOptions.spy ? "autospy" : "automock";
|
|
536
|
+
}
|
|
537
|
+
// unique id that is not available as "$bare_import" like "test"
|
|
538
|
+
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
|
|
539
|
+
const prefixedBuiltins = new Set([
|
|
540
|
+
"node:sea",
|
|
541
|
+
"node:sqlite",
|
|
542
|
+
"node:test",
|
|
543
|
+
"node:test/reporters"
|
|
544
|
+
]);
|
|
545
|
+
const isWindows$1 = process.platform === "win32";
|
|
546
|
+
// transform file url to id
|
|
547
|
+
// virtual:custom -> virtual:custom
|
|
548
|
+
// \0custom -> \0custom
|
|
549
|
+
// /root/id -> /id
|
|
550
|
+
// /root/id.js -> /id.js
|
|
551
|
+
// C:/root/id.js -> /id.js
|
|
552
|
+
// C:\root\id.js -> /id.js
|
|
553
|
+
// TODO: expose this in vite/module-runner
|
|
554
|
+
function normalizeModuleId(file) {
|
|
555
|
+
if (prefixedBuiltins.has(file)) return file;
|
|
556
|
+
// if it's not in the root, keep it as a path, not a URL
|
|
557
|
+
return slash(file).replace(/^\/@fs\//, isWindows$1 ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/").replace(/^file:\//, "/");
|
|
558
|
+
}
|
|
559
|
+
const windowsSlashRE = /\\/g;
|
|
560
|
+
function slash(p) {
|
|
561
|
+
return p.replace(windowsSlashRE, "/");
|
|
562
|
+
}
|
|
563
|
+
const multipleSlashRe = /^\/+/;
|
|
564
|
+
// module-runner incorrectly replaces file:///path with `///path`
|
|
565
|
+
function fixLeadingSlashes(id) {
|
|
566
|
+
if (id.startsWith("//")) return id.replace(multipleSlashRe, "/");
|
|
567
|
+
return id;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const createNodeImportMeta = (modulePath) => {
|
|
571
|
+
if (!viteModuleRunner.createDefaultImportMeta) throw new Error(`createNodeImportMeta is not supported in this version of Vite.`);
|
|
572
|
+
const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath);
|
|
573
|
+
const href = defaultMeta.url;
|
|
574
|
+
const importMetaResolver = createImportMetaResolver();
|
|
575
|
+
return {
|
|
576
|
+
...defaultMeta,
|
|
577
|
+
main: false,
|
|
578
|
+
resolve(id, parent) {
|
|
579
|
+
return (importMetaResolver ?? defaultMeta.resolve)(id, parent ?? href);
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
function createImportMetaResolver() {
|
|
584
|
+
if (!import.meta.resolve) return;
|
|
585
|
+
return (specifier, importer) => import.meta.resolve(specifier, importer);
|
|
586
|
+
}
|
|
587
|
+
// @ts-expect-error overriding private method
|
|
588
|
+
class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
|
|
589
|
+
mocker;
|
|
590
|
+
moduleExecutionInfo;
|
|
591
|
+
_otel;
|
|
592
|
+
constructor(vitestOptions) {
|
|
593
|
+
const options = vitestOptions;
|
|
594
|
+
const transport = new VitestTransport(options.transport);
|
|
595
|
+
const evaluatedModules = options.evaluatedModules;
|
|
596
|
+
super({
|
|
597
|
+
transport,
|
|
598
|
+
hmr: false,
|
|
599
|
+
evaluatedModules,
|
|
600
|
+
sourcemapInterceptor: "prepareStackTrace",
|
|
601
|
+
createImportMeta: vitestOptions.createImportMeta
|
|
602
|
+
}, options.evaluator);
|
|
603
|
+
this.vitestOptions = vitestOptions;
|
|
604
|
+
this._otel = vitestOptions.traces || new Traces({ enabled: false });
|
|
605
|
+
this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo;
|
|
606
|
+
this.mocker = options.mocker || new VitestMocker(this, {
|
|
607
|
+
spyModule: options.spyModule,
|
|
608
|
+
context: options.vm?.context,
|
|
609
|
+
traces: this._otel,
|
|
610
|
+
resolveId: options.transport.resolveId,
|
|
611
|
+
get root() {
|
|
612
|
+
return options.getWorkerState().config.root;
|
|
613
|
+
},
|
|
614
|
+
get moduleDirectories() {
|
|
615
|
+
return options.getWorkerState().config.deps.moduleDirectories || [];
|
|
616
|
+
},
|
|
617
|
+
getCurrentTestFilepath() {
|
|
618
|
+
return options.getWorkerState().filepath;
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
if (options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
|
|
622
|
+
else Object.defineProperty(globalThis, "__vitest_mocker__", {
|
|
623
|
+
configurable: true,
|
|
624
|
+
writable: true,
|
|
625
|
+
value: this.mocker
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Vite checks that the module has exports emulating the Node.js behaviour,
|
|
630
|
+
* but Vitest is more relaxed.
|
|
631
|
+
*
|
|
632
|
+
* We should keep the Vite behavour when there is a `strict` flag.
|
|
633
|
+
* @internal
|
|
634
|
+
*/
|
|
635
|
+
processImport(exports$1) {
|
|
636
|
+
return exports$1;
|
|
637
|
+
}
|
|
638
|
+
async import(rawId) {
|
|
639
|
+
const resolved = await this._otel.$("vitest.module.resolve_id", { attributes: { "vitest.module.raw_id": rawId } }, async (span) => {
|
|
640
|
+
const result = await this.vitestOptions.transport.resolveId(rawId);
|
|
641
|
+
if (result) span.setAttributes({
|
|
642
|
+
"vitest.module.url": result.url,
|
|
643
|
+
"vitest.module.file": result.file,
|
|
644
|
+
"vitest.module.id": result.id
|
|
645
|
+
});
|
|
646
|
+
return result;
|
|
647
|
+
});
|
|
648
|
+
return super.import(resolved ? resolved.url : rawId);
|
|
649
|
+
}
|
|
650
|
+
async fetchModule(url, importer) {
|
|
651
|
+
return await this.cachedModule(url, importer);
|
|
652
|
+
}
|
|
653
|
+
_cachedRequest(url, module, callstack = [], metadata) {
|
|
654
|
+
// @ts-expect-error "cachedRequest" is private
|
|
655
|
+
return super.cachedRequest(url, module, callstack, metadata);
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* @internal
|
|
659
|
+
*/
|
|
660
|
+
async cachedRequest(url, mod, callstack = [], metadata, ignoreMock = false) {
|
|
661
|
+
if (ignoreMock) return this._cachedRequest(url, mod, callstack, metadata);
|
|
662
|
+
let mocked;
|
|
663
|
+
if (mod.meta && "mockedModule" in mod.meta) mocked = await this.mocker.requestWithMockedModule(url, mod, callstack, mod.meta.mockedModule);
|
|
664
|
+
else mocked = await this.mocker.mockedRequest(url, mod, callstack);
|
|
665
|
+
if (typeof mocked === "string") {
|
|
666
|
+
const node = await this.fetchModule(mocked);
|
|
667
|
+
return this._cachedRequest(mocked, node, callstack, metadata);
|
|
668
|
+
}
|
|
669
|
+
if (mocked != null && typeof mocked === "object") return mocked;
|
|
670
|
+
return this._cachedRequest(url, mod, callstack, metadata);
|
|
671
|
+
}
|
|
672
|
+
/** @internal */
|
|
673
|
+
_invalidateSubTreeById(ids, invalidated = /* @__PURE__ */ new Set()) {
|
|
674
|
+
for (const id of ids) {
|
|
675
|
+
if (invalidated.has(id)) continue;
|
|
676
|
+
const node = this.evaluatedModules.getModuleById(id);
|
|
677
|
+
if (!node) continue;
|
|
678
|
+
invalidated.add(id);
|
|
679
|
+
const subIds = Array.from(this.evaluatedModules.idToModuleMap).filter(([, mod]) => mod.importers.has(id)).map(([key]) => key);
|
|
680
|
+
if (subIds.length) this._invalidateSubTreeById(subIds, invalidated);
|
|
681
|
+
this.evaluatedModules.invalidateModule(node);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const bareVitestRegexp = /^@?vitest(?:\/|$)/;
|
|
687
|
+
const normalizedDistDir = normalize$1(distDir);
|
|
688
|
+
const relativeIds = {};
|
|
689
|
+
const externalizeMap = /* @__PURE__ */ new Map();
|
|
690
|
+
// all Vitest imports always need to be externalized
|
|
691
|
+
function getCachedVitestImport(id, state) {
|
|
692
|
+
if (id.startsWith("/@fs/") || id.startsWith("\\@fs\\")) id = id.slice(process.platform === "win32" ? 5 : 4);
|
|
693
|
+
if (externalizeMap.has(id)) return {
|
|
694
|
+
externalize: externalizeMap.get(id),
|
|
695
|
+
type: "module"
|
|
696
|
+
};
|
|
697
|
+
// always externalize Vitest because we import from there before running tests
|
|
698
|
+
// so we already have it cached by Node.js
|
|
699
|
+
const root = state().config.root;
|
|
700
|
+
const relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
|
|
701
|
+
if (id.includes(distDir) || id.includes(normalizedDistDir)) {
|
|
702
|
+
const externalize = id.startsWith("file://") ? id : pathToFileURL(id).toString();
|
|
703
|
+
externalizeMap.set(id, externalize);
|
|
704
|
+
return {
|
|
705
|
+
externalize,
|
|
706
|
+
type: "module"
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
if (relativeRoot && relativeRoot !== "/" && id.startsWith(relativeRoot)) {
|
|
710
|
+
const externalize = pathToFileURL(join$1(root, id)).toString();
|
|
711
|
+
externalizeMap.set(id, externalize);
|
|
712
|
+
return {
|
|
713
|
+
externalize,
|
|
714
|
+
type: "module"
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
if (bareVitestRegexp.test(id)) {
|
|
718
|
+
externalizeMap.set(id, id);
|
|
719
|
+
return {
|
|
720
|
+
externalize: id,
|
|
721
|
+
type: "module"
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// Store globals in case tests overwrite them
|
|
728
|
+
const processListeners = process.listeners.bind(process);
|
|
729
|
+
const processOn = process.on.bind(process);
|
|
730
|
+
const processOff = process.off.bind(process);
|
|
731
|
+
const dispose = [];
|
|
732
|
+
function listenForErrors(state) {
|
|
733
|
+
dispose.forEach((fn) => fn());
|
|
734
|
+
dispose.length = 0;
|
|
735
|
+
function catchError(err, type, event) {
|
|
736
|
+
const worker = state();
|
|
737
|
+
// if there is another listener, assume that it's handled by user code
|
|
738
|
+
// one is Vitest's own listener
|
|
739
|
+
if (processListeners(event).length > 1) return;
|
|
740
|
+
const error = serializeValue(err);
|
|
741
|
+
if (typeof error === "object" && error != null) {
|
|
742
|
+
error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
|
|
743
|
+
if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
|
|
744
|
+
}
|
|
745
|
+
state().rpc.onUnhandledError(error, type);
|
|
746
|
+
}
|
|
747
|
+
const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
|
|
748
|
+
const unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
|
|
749
|
+
processOn("uncaughtException", uncaughtException);
|
|
750
|
+
processOn("unhandledRejection", unhandledRejection);
|
|
751
|
+
dispose.push(() => {
|
|
752
|
+
processOff("uncaughtException", uncaughtException);
|
|
753
|
+
processOff("unhandledRejection", unhandledRejection);
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const { readFileSync } = fs;
|
|
758
|
+
const VITEST_VM_CONTEXT_SYMBOL = "__vitest_vm_context__";
|
|
759
|
+
const cwd = process.cwd();
|
|
760
|
+
const isWindows = process.platform === "win32";
|
|
761
|
+
function startVitestModuleRunner(options) {
|
|
762
|
+
const traces = options.traces;
|
|
763
|
+
const state = () => globalThis.__vitest_worker__ || options.state;
|
|
764
|
+
const rpc = () => state().rpc;
|
|
765
|
+
process.exit = (code = process.exitCode || 0) => {
|
|
766
|
+
throw new Error(`process.exit unexpectedly called with "${code}"`);
|
|
767
|
+
};
|
|
768
|
+
listenForErrors(state);
|
|
769
|
+
const environment = () => {
|
|
770
|
+
const environment = state().environment;
|
|
771
|
+
return environment.viteEnvironment || environment.name;
|
|
772
|
+
};
|
|
773
|
+
const vm = options.context && options.externalModulesExecutor ? {
|
|
774
|
+
context: options.context,
|
|
775
|
+
externalModulesExecutor: options.externalModulesExecutor
|
|
776
|
+
} : void 0;
|
|
777
|
+
const evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
|
|
778
|
+
traces,
|
|
779
|
+
evaluatedModules: options.evaluatedModules,
|
|
780
|
+
get moduleExecutionInfo() {
|
|
781
|
+
return state().moduleExecutionInfo;
|
|
782
|
+
},
|
|
783
|
+
get interopDefault() {
|
|
784
|
+
return state().config.deps.interopDefault;
|
|
785
|
+
},
|
|
786
|
+
getCurrentTestFilepath: () => state().filepath
|
|
787
|
+
});
|
|
788
|
+
const moduleRunner = new VitestModuleRunner({
|
|
789
|
+
spyModule: options.spyModule,
|
|
790
|
+
evaluatedModules: options.evaluatedModules,
|
|
791
|
+
evaluator,
|
|
792
|
+
traces,
|
|
793
|
+
mocker: options.mocker,
|
|
794
|
+
transport: {
|
|
795
|
+
async fetchModule(id, importer, options) {
|
|
796
|
+
const resolvingModules = state().resolvingModules;
|
|
797
|
+
if (isWindows) {
|
|
798
|
+
if (id[1] === ":") {
|
|
799
|
+
// The drive letter is different for whatever reason, we need to normalize it to CWD
|
|
800
|
+
if (id[0] !== cwd[0] && id[0].toUpperCase() === cwd[0].toUpperCase()) id = (cwd[0].toUpperCase() === cwd[0] ? id[0].toUpperCase() : id[0].toLowerCase()) + id.slice(1);
|
|
801
|
+
// always mark absolute windows paths, otherwise Vite will externalize it
|
|
802
|
+
id = `/@id/${id}`;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
const vitest = getCachedVitestImport(id, state);
|
|
806
|
+
if (vitest) return vitest;
|
|
807
|
+
const rawId = unwrapId(id);
|
|
808
|
+
resolvingModules.add(rawId);
|
|
809
|
+
try {
|
|
810
|
+
if (VitestMocker.pendingIds.length) await moduleRunner.mocker.resolveMocks();
|
|
811
|
+
const resolvedMock = moduleRunner.mocker.getDependencyMock(rawId);
|
|
812
|
+
if (resolvedMock?.type === "manual" || resolvedMock?.type === "redirect") return {
|
|
813
|
+
code: "",
|
|
814
|
+
file: null,
|
|
815
|
+
id,
|
|
816
|
+
url: id,
|
|
817
|
+
invalidate: false,
|
|
818
|
+
mockedModule: resolvedMock
|
|
819
|
+
};
|
|
820
|
+
if (isBuiltin(rawId)) return {
|
|
821
|
+
externalize: rawId,
|
|
822
|
+
type: "builtin"
|
|
823
|
+
};
|
|
824
|
+
if (isBrowserExternal(rawId)) return {
|
|
825
|
+
externalize: toBuiltin(rawId),
|
|
826
|
+
type: "builtin"
|
|
827
|
+
};
|
|
828
|
+
// if module is invalidated, the worker will be recreated,
|
|
829
|
+
// so cached is always true in a single worker
|
|
830
|
+
if (options?.cached) return { cache: true };
|
|
831
|
+
const otelCarrier = traces?.getContextCarrier();
|
|
832
|
+
const result = await rpc().fetch(id, importer, environment(), options, otelCarrier);
|
|
833
|
+
if ("cached" in result) return {
|
|
834
|
+
code: readFileSync(result.tmp, "utf-8"),
|
|
835
|
+
...result
|
|
836
|
+
};
|
|
837
|
+
return result;
|
|
838
|
+
} catch (cause) {
|
|
839
|
+
// rethrow vite error if it cannot load the module because it's not resolved
|
|
840
|
+
if (typeof cause === "object" && cause != null && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url") || typeof cause?.message === "string" && cause.message.startsWith("Cannot find module '")) {
|
|
841
|
+
const error = new Error(`Cannot find ${isBareImport(id) ? "package" : "module"} '${id}'${importer ? ` imported from '${importer}'` : ""}`, { cause });
|
|
842
|
+
error.code = "ERR_MODULE_NOT_FOUND";
|
|
843
|
+
throw error;
|
|
844
|
+
}
|
|
845
|
+
throw cause;
|
|
846
|
+
} finally {
|
|
847
|
+
resolvingModules.delete(rawId);
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
resolveId(id, importer) {
|
|
851
|
+
return rpc().resolve(id, importer, environment());
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
getWorkerState: state,
|
|
855
|
+
vm,
|
|
856
|
+
createImportMeta: options.createImportMeta
|
|
857
|
+
});
|
|
858
|
+
return moduleRunner;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
export { VitestModuleRunner as V, VITEST_VM_CONTEXT_SYMBOL as a, VitestTransport as b, createNodeImportMeta as c, startVitestModuleRunner as s };
|