@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,1437 @@
|
|
|
1
|
+
import { resolve } from '../../vendor/pathe.mjs';
|
|
2
|
+
import { plugins, format } from '../pretty-format/index.js';
|
|
3
|
+
|
|
4
|
+
// src/vlq.ts
|
|
5
|
+
var comma = ",".charCodeAt(0);
|
|
6
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
7
|
+
var intToChar = new Uint8Array(64);
|
|
8
|
+
var charToInt = new Uint8Array(128);
|
|
9
|
+
for (let i = 0; i < chars.length; i++) {
|
|
10
|
+
const c = chars.charCodeAt(i);
|
|
11
|
+
intToChar[i] = c;
|
|
12
|
+
charToInt[c] = i;
|
|
13
|
+
}
|
|
14
|
+
function decodeInteger(reader, relative) {
|
|
15
|
+
let value = 0;
|
|
16
|
+
let shift = 0;
|
|
17
|
+
let integer = 0;
|
|
18
|
+
do {
|
|
19
|
+
const c = reader.next();
|
|
20
|
+
integer = charToInt[c];
|
|
21
|
+
value |= (integer & 31) << shift;
|
|
22
|
+
shift += 5;
|
|
23
|
+
} while (integer & 32);
|
|
24
|
+
const shouldNegate = value & 1;
|
|
25
|
+
value >>>= 1;
|
|
26
|
+
if (shouldNegate) {
|
|
27
|
+
value = -2147483648 | -value;
|
|
28
|
+
}
|
|
29
|
+
return relative + value;
|
|
30
|
+
}
|
|
31
|
+
function hasMoreVlq(reader, max) {
|
|
32
|
+
if (reader.pos >= max) return false;
|
|
33
|
+
return reader.peek() !== comma;
|
|
34
|
+
}
|
|
35
|
+
var StringReader = class {
|
|
36
|
+
constructor(buffer) {
|
|
37
|
+
this.pos = 0;
|
|
38
|
+
this.buffer = buffer;
|
|
39
|
+
}
|
|
40
|
+
next() {
|
|
41
|
+
return this.buffer.charCodeAt(this.pos++);
|
|
42
|
+
}
|
|
43
|
+
peek() {
|
|
44
|
+
return this.buffer.charCodeAt(this.pos);
|
|
45
|
+
}
|
|
46
|
+
indexOf(char) {
|
|
47
|
+
const { buffer, pos } = this;
|
|
48
|
+
const idx = buffer.indexOf(char, pos);
|
|
49
|
+
return idx === -1 ? buffer.length : idx;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// src/sourcemap-codec.ts
|
|
54
|
+
function decode(mappings) {
|
|
55
|
+
const { length } = mappings;
|
|
56
|
+
const reader = new StringReader(mappings);
|
|
57
|
+
const decoded = [];
|
|
58
|
+
let genColumn = 0;
|
|
59
|
+
let sourcesIndex = 0;
|
|
60
|
+
let sourceLine = 0;
|
|
61
|
+
let sourceColumn = 0;
|
|
62
|
+
let namesIndex = 0;
|
|
63
|
+
do {
|
|
64
|
+
const semi = reader.indexOf(";");
|
|
65
|
+
const line = [];
|
|
66
|
+
let sorted = true;
|
|
67
|
+
let lastCol = 0;
|
|
68
|
+
genColumn = 0;
|
|
69
|
+
while (reader.pos < semi) {
|
|
70
|
+
let seg;
|
|
71
|
+
genColumn = decodeInteger(reader, genColumn);
|
|
72
|
+
if (genColumn < lastCol) sorted = false;
|
|
73
|
+
lastCol = genColumn;
|
|
74
|
+
if (hasMoreVlq(reader, semi)) {
|
|
75
|
+
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
|
76
|
+
sourceLine = decodeInteger(reader, sourceLine);
|
|
77
|
+
sourceColumn = decodeInteger(reader, sourceColumn);
|
|
78
|
+
if (hasMoreVlq(reader, semi)) {
|
|
79
|
+
namesIndex = decodeInteger(reader, namesIndex);
|
|
80
|
+
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
|
|
81
|
+
} else {
|
|
82
|
+
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
seg = [genColumn];
|
|
86
|
+
}
|
|
87
|
+
line.push(seg);
|
|
88
|
+
reader.pos++;
|
|
89
|
+
}
|
|
90
|
+
if (!sorted) sort(line);
|
|
91
|
+
decoded.push(line);
|
|
92
|
+
reader.pos = semi + 1;
|
|
93
|
+
} while (reader.pos <= length);
|
|
94
|
+
return decoded;
|
|
95
|
+
}
|
|
96
|
+
function sort(line) {
|
|
97
|
+
line.sort(sortComparator);
|
|
98
|
+
}
|
|
99
|
+
function sortComparator(a, b) {
|
|
100
|
+
return a[0] - b[0];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/trace-mapping.ts
|
|
104
|
+
|
|
105
|
+
// src/sourcemap-segment.ts
|
|
106
|
+
var COLUMN = 0;
|
|
107
|
+
var SOURCES_INDEX = 1;
|
|
108
|
+
var SOURCE_LINE = 2;
|
|
109
|
+
var SOURCE_COLUMN = 3;
|
|
110
|
+
var NAMES_INDEX = 4;
|
|
111
|
+
|
|
112
|
+
// src/binary-search.ts
|
|
113
|
+
var found = false;
|
|
114
|
+
function binarySearch(haystack, needle, low, high) {
|
|
115
|
+
while (low <= high) {
|
|
116
|
+
const mid = low + (high - low >> 1);
|
|
117
|
+
const cmp = haystack[mid][COLUMN] - needle;
|
|
118
|
+
if (cmp === 0) {
|
|
119
|
+
found = true;
|
|
120
|
+
return mid;
|
|
121
|
+
}
|
|
122
|
+
if (cmp < 0) {
|
|
123
|
+
low = mid + 1;
|
|
124
|
+
} else {
|
|
125
|
+
high = mid - 1;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
found = false;
|
|
129
|
+
return low - 1;
|
|
130
|
+
}
|
|
131
|
+
function upperBound(haystack, needle, index) {
|
|
132
|
+
for (let i = index + 1; i < haystack.length; index = i++) {
|
|
133
|
+
if (haystack[i][COLUMN] !== needle) break;
|
|
134
|
+
}
|
|
135
|
+
return index;
|
|
136
|
+
}
|
|
137
|
+
function lowerBound(haystack, needle, index) {
|
|
138
|
+
for (let i = index - 1; i >= 0; index = i--) {
|
|
139
|
+
if (haystack[i][COLUMN] !== needle) break;
|
|
140
|
+
}
|
|
141
|
+
return index;
|
|
142
|
+
}
|
|
143
|
+
function memoizedBinarySearch(haystack, needle, state, key) {
|
|
144
|
+
const { lastKey, lastNeedle, lastIndex } = state;
|
|
145
|
+
let low = 0;
|
|
146
|
+
let high = haystack.length - 1;
|
|
147
|
+
if (key === lastKey) {
|
|
148
|
+
if (needle === lastNeedle) {
|
|
149
|
+
found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
|
|
150
|
+
return lastIndex;
|
|
151
|
+
}
|
|
152
|
+
if (needle >= lastNeedle) {
|
|
153
|
+
low = lastIndex === -1 ? 0 : lastIndex;
|
|
154
|
+
} else {
|
|
155
|
+
high = lastIndex;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
state.lastKey = key;
|
|
159
|
+
state.lastNeedle = needle;
|
|
160
|
+
return state.lastIndex = binarySearch(haystack, needle, low, high);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/trace-mapping.ts
|
|
164
|
+
var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
|
|
165
|
+
var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
|
|
166
|
+
var LEAST_UPPER_BOUND = -1;
|
|
167
|
+
var GREATEST_LOWER_BOUND = 1;
|
|
168
|
+
function cast(map) {
|
|
169
|
+
return map;
|
|
170
|
+
}
|
|
171
|
+
function decodedMappings(map) {
|
|
172
|
+
var _a;
|
|
173
|
+
return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
|
|
174
|
+
}
|
|
175
|
+
function originalPositionFor(map, needle) {
|
|
176
|
+
let { line, column, bias } = needle;
|
|
177
|
+
line--;
|
|
178
|
+
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
179
|
+
if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
|
|
180
|
+
const decoded = decodedMappings(map);
|
|
181
|
+
if (line >= decoded.length) return OMapping(null, null, null, null);
|
|
182
|
+
const segments = decoded[line];
|
|
183
|
+
const index = traceSegmentInternal(
|
|
184
|
+
segments,
|
|
185
|
+
cast(map)._decodedMemo,
|
|
186
|
+
line,
|
|
187
|
+
column,
|
|
188
|
+
bias || GREATEST_LOWER_BOUND
|
|
189
|
+
);
|
|
190
|
+
if (index === -1) return OMapping(null, null, null, null);
|
|
191
|
+
const segment = segments[index];
|
|
192
|
+
if (segment.length === 1) return OMapping(null, null, null, null);
|
|
193
|
+
const { names, resolvedSources } = map;
|
|
194
|
+
return OMapping(
|
|
195
|
+
resolvedSources[segment[SOURCES_INDEX]],
|
|
196
|
+
segment[SOURCE_LINE] + 1,
|
|
197
|
+
segment[SOURCE_COLUMN],
|
|
198
|
+
segment.length === 5 ? names[segment[NAMES_INDEX]] : null
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
function OMapping(source, line, column, name) {
|
|
202
|
+
return { source, line, column, name };
|
|
203
|
+
}
|
|
204
|
+
function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
205
|
+
let index = memoizedBinarySearch(segments, column, memo, line);
|
|
206
|
+
if (found) {
|
|
207
|
+
index = (bias === LEAST_UPPER_BOUND ? upperBound : lowerBound)(segments, column, index);
|
|
208
|
+
} else if (bias === LEAST_UPPER_BOUND) index++;
|
|
209
|
+
if (index === -1 || index === segments.length) return -1;
|
|
210
|
+
return index;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function notNullish(v) {
|
|
214
|
+
return v != null;
|
|
215
|
+
}
|
|
216
|
+
function isPrimitive(value) {
|
|
217
|
+
return value === null || typeof value !== "function" && typeof value !== "object";
|
|
218
|
+
}
|
|
219
|
+
function isObject(item) {
|
|
220
|
+
return item != null && typeof item === "object" && !Array.isArray(item);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* If code starts with a function call, will return its last index, respecting arguments.
|
|
224
|
+
* This will return 25 - last ending character of toMatch ")"
|
|
225
|
+
* Also works with callbacks
|
|
226
|
+
* ```
|
|
227
|
+
* toMatch({ test: '123' });
|
|
228
|
+
* toBeAliased('123')
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
function getCallLastIndex(code) {
|
|
232
|
+
let charIndex = -1;
|
|
233
|
+
let inString = null;
|
|
234
|
+
let startedBracers = 0;
|
|
235
|
+
let endedBracers = 0;
|
|
236
|
+
let beforeChar = null;
|
|
237
|
+
while (charIndex <= code.length) {
|
|
238
|
+
beforeChar = code[charIndex];
|
|
239
|
+
charIndex++;
|
|
240
|
+
const char = code[charIndex];
|
|
241
|
+
const isCharString = char === "\"" || char === "'" || char === "`";
|
|
242
|
+
if (isCharString && beforeChar !== "\\") {
|
|
243
|
+
if (inString === char) {
|
|
244
|
+
inString = null;
|
|
245
|
+
} else if (!inString) {
|
|
246
|
+
inString = char;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (!inString) {
|
|
250
|
+
if (char === "(") {
|
|
251
|
+
startedBracers++;
|
|
252
|
+
}
|
|
253
|
+
if (char === ")") {
|
|
254
|
+
endedBracers++;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (startedBracers && endedBracers && startedBracers === endedBracers) {
|
|
258
|
+
return charIndex;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const CHROME_IE_STACK_REGEXP = /^\s*at .*(?:\S:\d+|\(native\))/m;
|
|
265
|
+
const SAFARI_NATIVE_CODE_REGEXP = /^(?:eval@)?(?:\[native code\])?$/;
|
|
266
|
+
const stackIgnorePatterns = [
|
|
267
|
+
"node:internal",
|
|
268
|
+
/\/packages\/\w+\/dist\//,
|
|
269
|
+
/\/@vitest\/\w+\/dist\//,
|
|
270
|
+
"/vitest/dist/",
|
|
271
|
+
"/vitest/src/",
|
|
272
|
+
"/node_modules/chai/",
|
|
273
|
+
"/node_modules/tinyspy/",
|
|
274
|
+
"/vite/dist/node/module-runner",
|
|
275
|
+
"/rolldown-vite/dist/node/module-runner",
|
|
276
|
+
"/deps/chunk-",
|
|
277
|
+
"/deps/@vitest",
|
|
278
|
+
"/deps/loupe",
|
|
279
|
+
"/deps/chai",
|
|
280
|
+
"/browser-playwright/dist/locators.js",
|
|
281
|
+
"/browser-webdriverio/dist/locators.js",
|
|
282
|
+
"/browser-preview/dist/locators.js",
|
|
283
|
+
/node:\w+/,
|
|
284
|
+
/__vitest_test__/,
|
|
285
|
+
/__vitest_browser__/,
|
|
286
|
+
/\/deps\/vitest_/
|
|
287
|
+
];
|
|
288
|
+
function extractLocation(urlLike) {
|
|
289
|
+
// Fail-fast but return locations like "(native)"
|
|
290
|
+
if (!urlLike.includes(":")) {
|
|
291
|
+
return [urlLike];
|
|
292
|
+
}
|
|
293
|
+
const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
|
|
294
|
+
const parts = regExp.exec(urlLike.replace(/^\(|\)$/g, ""));
|
|
295
|
+
if (!parts) {
|
|
296
|
+
return [urlLike];
|
|
297
|
+
}
|
|
298
|
+
let url = parts[1];
|
|
299
|
+
if (url.startsWith("async ")) {
|
|
300
|
+
url = url.slice(6);
|
|
301
|
+
}
|
|
302
|
+
if (url.startsWith("http:") || url.startsWith("https:")) {
|
|
303
|
+
const urlObj = new URL(url);
|
|
304
|
+
urlObj.searchParams.delete("import");
|
|
305
|
+
urlObj.searchParams.delete("browserv");
|
|
306
|
+
url = urlObj.pathname + urlObj.hash + urlObj.search;
|
|
307
|
+
}
|
|
308
|
+
if (url.startsWith("/@fs/")) {
|
|
309
|
+
const isWindows = /^\/@fs\/[a-zA-Z]:\//.test(url);
|
|
310
|
+
url = url.slice(isWindows ? 5 : 4);
|
|
311
|
+
}
|
|
312
|
+
return [
|
|
313
|
+
url,
|
|
314
|
+
parts[2] || undefined,
|
|
315
|
+
parts[3] || undefined
|
|
316
|
+
];
|
|
317
|
+
}
|
|
318
|
+
function parseSingleFFOrSafariStack(raw) {
|
|
319
|
+
let line = raw.trim();
|
|
320
|
+
if (SAFARI_NATIVE_CODE_REGEXP.test(line)) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
if (line.includes(" > eval")) {
|
|
324
|
+
line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
|
|
325
|
+
}
|
|
326
|
+
// Early return for lines that don't look like Firefox/Safari stack traces
|
|
327
|
+
// Firefox/Safari stack traces must contain '@' and should have location info after it
|
|
328
|
+
if (!line.includes("@")) {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
// Find the correct @ that separates function name from location
|
|
332
|
+
// For cases like '@https://@fs/path' or 'functionName@https://@fs/path'
|
|
333
|
+
// we need to find the first @ that precedes a valid location (containing :)
|
|
334
|
+
let atIndex = -1;
|
|
335
|
+
let locationPart = "";
|
|
336
|
+
let functionName;
|
|
337
|
+
// Try each @ from left to right to find the one that gives us a valid location
|
|
338
|
+
for (let i = 0; i < line.length; i++) {
|
|
339
|
+
if (line[i] === "@") {
|
|
340
|
+
const candidateLocation = line.slice(i + 1);
|
|
341
|
+
// Minimum length 3 for valid location: 1 for filename + 1 for colon + 1 for line number (e.g., "a:1")
|
|
342
|
+
if (candidateLocation.includes(":") && candidateLocation.length >= 3) {
|
|
343
|
+
atIndex = i;
|
|
344
|
+
locationPart = candidateLocation;
|
|
345
|
+
functionName = i > 0 ? line.slice(0, i) : undefined;
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Validate we found a valid location with minimum length (filename:line format)
|
|
351
|
+
if (atIndex === -1 || !locationPart.includes(":") || locationPart.length < 3) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
const [url, lineNumber, columnNumber] = extractLocation(locationPart);
|
|
355
|
+
if (!url || !lineNumber || !columnNumber) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
file: url,
|
|
360
|
+
method: functionName || "",
|
|
361
|
+
line: Number.parseInt(lineNumber),
|
|
362
|
+
column: Number.parseInt(columnNumber)
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
// Based on https://github.com/stacktracejs/error-stack-parser
|
|
366
|
+
// Credit to stacktracejs
|
|
367
|
+
function parseSingleV8Stack(raw) {
|
|
368
|
+
let line = raw.trim();
|
|
369
|
+
if (!CHROME_IE_STACK_REGEXP.test(line)) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
if (line.includes("(eval ")) {
|
|
373
|
+
line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
|
374
|
+
}
|
|
375
|
+
let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
|
376
|
+
// capture and preserve the parenthesized location "(/foo/my bar.js:12:87)" in
|
|
377
|
+
// case it has spaces in it, as the string is split on \s+ later on
|
|
378
|
+
const location = sanitizedLine.match(/ (\(.+\)$)/);
|
|
379
|
+
// remove the parenthesized location from the line, if it was matched
|
|
380
|
+
sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
|
|
381
|
+
// if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine
|
|
382
|
+
// because this line doesn't have function name
|
|
383
|
+
const [url, lineNumber, columnNumber] = extractLocation(location ? location[1] : sanitizedLine);
|
|
384
|
+
let method = location && sanitizedLine || "";
|
|
385
|
+
let file = url && ["eval", "<anonymous>"].includes(url) ? undefined : url;
|
|
386
|
+
if (!file || !lineNumber || !columnNumber) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
if (method.startsWith("async ")) {
|
|
390
|
+
method = method.slice(6);
|
|
391
|
+
}
|
|
392
|
+
if (file.startsWith("file://")) {
|
|
393
|
+
file = file.slice(7);
|
|
394
|
+
}
|
|
395
|
+
// normalize Windows path (\ -> /)
|
|
396
|
+
file = file.startsWith("node:") || file.startsWith("internal:") ? file : resolve(file);
|
|
397
|
+
if (method) {
|
|
398
|
+
method = method.replace(/__vite_ssr_import_\d+__\./g, "").replace(/(Object\.)?__vite_ssr_export_default__\s?/g, "");
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
method,
|
|
402
|
+
file,
|
|
403
|
+
line: Number.parseInt(lineNumber),
|
|
404
|
+
column: Number.parseInt(columnNumber)
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function parseStacktrace(stack, options = {}) {
|
|
408
|
+
const { ignoreStackEntries = stackIgnorePatterns } = options;
|
|
409
|
+
const stacks = !CHROME_IE_STACK_REGEXP.test(stack) ? parseFFOrSafariStackTrace(stack) : parseV8Stacktrace(stack);
|
|
410
|
+
return stacks.map((stack) => {
|
|
411
|
+
var _options$getSourceMap;
|
|
412
|
+
if (options.getUrlId) {
|
|
413
|
+
stack.file = options.getUrlId(stack.file);
|
|
414
|
+
}
|
|
415
|
+
const map = (_options$getSourceMap = options.getSourceMap) === null || _options$getSourceMap === void 0 ? void 0 : _options$getSourceMap.call(options, stack.file);
|
|
416
|
+
if (!map || typeof map !== "object" || !map.version) {
|
|
417
|
+
return shouldFilter(ignoreStackEntries, stack.file) ? null : stack;
|
|
418
|
+
}
|
|
419
|
+
const traceMap = new DecodedMap(map, stack.file);
|
|
420
|
+
const position = getOriginalPosition(traceMap, stack);
|
|
421
|
+
if (!position) {
|
|
422
|
+
return stack;
|
|
423
|
+
}
|
|
424
|
+
const { line, column, source, name } = position;
|
|
425
|
+
let file = source || stack.file;
|
|
426
|
+
if (file.match(/\/\w:\//)) {
|
|
427
|
+
file = file.slice(1);
|
|
428
|
+
}
|
|
429
|
+
if (shouldFilter(ignoreStackEntries, file)) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
if (line != null && column != null) {
|
|
433
|
+
return {
|
|
434
|
+
line,
|
|
435
|
+
column,
|
|
436
|
+
file,
|
|
437
|
+
method: name || stack.method
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
return stack;
|
|
441
|
+
}).filter((s) => s != null);
|
|
442
|
+
}
|
|
443
|
+
function shouldFilter(ignoreStackEntries, file) {
|
|
444
|
+
return ignoreStackEntries.some((p) => file.match(p));
|
|
445
|
+
}
|
|
446
|
+
function parseFFOrSafariStackTrace(stack) {
|
|
447
|
+
return stack.split("\n").map((line) => parseSingleFFOrSafariStack(line)).filter(notNullish);
|
|
448
|
+
}
|
|
449
|
+
function parseV8Stacktrace(stack) {
|
|
450
|
+
return stack.split("\n").map((line) => parseSingleV8Stack(line)).filter(notNullish);
|
|
451
|
+
}
|
|
452
|
+
function parseErrorStacktrace(e, options = {}) {
|
|
453
|
+
if (!e || isPrimitive(e)) {
|
|
454
|
+
return [];
|
|
455
|
+
}
|
|
456
|
+
if ("stacks" in e && e.stacks) {
|
|
457
|
+
return e.stacks;
|
|
458
|
+
}
|
|
459
|
+
const stackStr = e.stack || "";
|
|
460
|
+
// if "stack" property was overwritten at runtime to be something else,
|
|
461
|
+
// ignore the value because we don't know how to process it
|
|
462
|
+
let stackFrames = typeof stackStr === "string" ? parseStacktrace(stackStr, options) : [];
|
|
463
|
+
if (!stackFrames.length) {
|
|
464
|
+
const e_ = e;
|
|
465
|
+
if (e_.fileName != null && e_.lineNumber != null && e_.columnNumber != null) {
|
|
466
|
+
stackFrames = parseStacktrace(`${e_.fileName}:${e_.lineNumber}:${e_.columnNumber}`, options);
|
|
467
|
+
}
|
|
468
|
+
if (e_.sourceURL != null && e_.line != null && e_._column != null) {
|
|
469
|
+
stackFrames = parseStacktrace(`${e_.sourceURL}:${e_.line}:${e_.column}`, options);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (options.frameFilter) {
|
|
473
|
+
stackFrames = stackFrames.filter((f) => options.frameFilter(e, f) !== false);
|
|
474
|
+
}
|
|
475
|
+
e.stacks = stackFrames;
|
|
476
|
+
return stackFrames;
|
|
477
|
+
}
|
|
478
|
+
class DecodedMap {
|
|
479
|
+
_encoded;
|
|
480
|
+
_decoded;
|
|
481
|
+
_decodedMemo;
|
|
482
|
+
url;
|
|
483
|
+
version;
|
|
484
|
+
names = [];
|
|
485
|
+
resolvedSources;
|
|
486
|
+
constructor(map, from) {
|
|
487
|
+
this.map = map;
|
|
488
|
+
const { mappings, names, sources } = map;
|
|
489
|
+
this.version = map.version;
|
|
490
|
+
this.names = names || [];
|
|
491
|
+
this._encoded = mappings || "";
|
|
492
|
+
this._decodedMemo = memoizedState();
|
|
493
|
+
this.url = from;
|
|
494
|
+
this.resolvedSources = (sources || []).map((s) => resolve(s || "", from));
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
function memoizedState() {
|
|
498
|
+
return {
|
|
499
|
+
lastKey: -1,
|
|
500
|
+
lastNeedle: -1,
|
|
501
|
+
lastIndex: -1
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
function getOriginalPosition(map, needle) {
|
|
505
|
+
const result = originalPositionFor(map, needle);
|
|
506
|
+
if (result.column == null) {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
return result;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const lineSplitRE = /\r?\n/;
|
|
513
|
+
function positionToOffset(source, lineNumber, columnNumber) {
|
|
514
|
+
const lines = source.split(lineSplitRE);
|
|
515
|
+
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
516
|
+
let start = 0;
|
|
517
|
+
if (lineNumber > lines.length) {
|
|
518
|
+
return source.length;
|
|
519
|
+
}
|
|
520
|
+
for (let i = 0; i < lineNumber - 1; i++) {
|
|
521
|
+
start += lines[i].length + nl;
|
|
522
|
+
}
|
|
523
|
+
return start + columnNumber;
|
|
524
|
+
}
|
|
525
|
+
function offsetToLineNumber(source, offset) {
|
|
526
|
+
if (offset > source.length) {
|
|
527
|
+
throw new Error(`offset is longer than source length! offset ${offset} > length ${source.length}`);
|
|
528
|
+
}
|
|
529
|
+
const lines = source.split(lineSplitRE);
|
|
530
|
+
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
531
|
+
let counted = 0;
|
|
532
|
+
let line = 0;
|
|
533
|
+
for (; line < lines.length; line++) {
|
|
534
|
+
const lineLength = lines[line].length + nl;
|
|
535
|
+
if (counted + lineLength >= offset) {
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
counted += lineLength;
|
|
539
|
+
}
|
|
540
|
+
return line + 1;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
async function saveInlineSnapshots(environment, snapshots) {
|
|
544
|
+
const MagicString = (await import('../../vendor/magic-string.mjs')).default;
|
|
545
|
+
const files = new Set(snapshots.map((i) => i.file));
|
|
546
|
+
await Promise.all(Array.from(files).map(async (file) => {
|
|
547
|
+
const snaps = snapshots.filter((i) => i.file === file);
|
|
548
|
+
const code = await environment.readSnapshotFile(file);
|
|
549
|
+
const s = new MagicString(code);
|
|
550
|
+
for (const snap of snaps) {
|
|
551
|
+
const index = positionToOffset(code, snap.line, snap.column);
|
|
552
|
+
replaceInlineSnap(code, s, index, snap.snapshot);
|
|
553
|
+
}
|
|
554
|
+
const transformed = s.toString();
|
|
555
|
+
if (transformed !== code) {
|
|
556
|
+
await environment.saveSnapshotFile(file, transformed);
|
|
557
|
+
}
|
|
558
|
+
}));
|
|
559
|
+
}
|
|
560
|
+
const startObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*\{/;
|
|
561
|
+
function replaceObjectSnap(code, s, index, newSnap) {
|
|
562
|
+
let _code = code.slice(index);
|
|
563
|
+
const startMatch = startObjectRegex.exec(_code);
|
|
564
|
+
if (!startMatch) {
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
_code = _code.slice(startMatch.index);
|
|
568
|
+
let callEnd = getCallLastIndex(_code);
|
|
569
|
+
if (callEnd === null) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
callEnd += index + startMatch.index;
|
|
573
|
+
const shapeStart = index + startMatch.index + startMatch[0].length;
|
|
574
|
+
const shapeEnd = getObjectShapeEndIndex(code, shapeStart);
|
|
575
|
+
const snap = `, ${prepareSnapString(newSnap, code, index)}`;
|
|
576
|
+
if (shapeEnd === callEnd) {
|
|
577
|
+
// toMatchInlineSnapshot({ foo: expect.any(String) })
|
|
578
|
+
s.appendLeft(callEnd, snap);
|
|
579
|
+
} else {
|
|
580
|
+
// toMatchInlineSnapshot({ foo: expect.any(String) }, ``)
|
|
581
|
+
s.overwrite(shapeEnd, callEnd, snap);
|
|
582
|
+
}
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
function getObjectShapeEndIndex(code, index) {
|
|
586
|
+
let startBraces = 1;
|
|
587
|
+
let endBraces = 0;
|
|
588
|
+
while (startBraces !== endBraces && index < code.length) {
|
|
589
|
+
const s = code[index++];
|
|
590
|
+
if (s === "{") {
|
|
591
|
+
startBraces++;
|
|
592
|
+
} else if (s === "}") {
|
|
593
|
+
endBraces++;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return index;
|
|
597
|
+
}
|
|
598
|
+
function prepareSnapString(snap, source, index) {
|
|
599
|
+
const lineNumber = offsetToLineNumber(source, index);
|
|
600
|
+
const line = source.split(lineSplitRE)[lineNumber - 1];
|
|
601
|
+
const indent = line.match(/^\s*/)[0] || "";
|
|
602
|
+
const indentNext = indent.includes(" ") ? `${indent}\t` : `${indent} `;
|
|
603
|
+
const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
|
|
604
|
+
const isOneline = lines.length <= 1;
|
|
605
|
+
const quote = "`";
|
|
606
|
+
if (isOneline) {
|
|
607
|
+
return `${quote}${lines.join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}${quote}`;
|
|
608
|
+
}
|
|
609
|
+
return `${quote}\n${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}\n${indent}${quote}`;
|
|
610
|
+
}
|
|
611
|
+
const toMatchInlineName = "toMatchInlineSnapshot";
|
|
612
|
+
const toThrowErrorMatchingInlineName = "toThrowErrorMatchingInlineSnapshot";
|
|
613
|
+
// on webkit, the line number is at the end of the method, not at the start
|
|
614
|
+
function getCodeStartingAtIndex(code, index) {
|
|
615
|
+
const indexInline = index - toMatchInlineName.length;
|
|
616
|
+
if (code.slice(indexInline, index) === toMatchInlineName) {
|
|
617
|
+
return {
|
|
618
|
+
code: code.slice(indexInline),
|
|
619
|
+
index: indexInline
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
const indexThrowInline = index - toThrowErrorMatchingInlineName.length;
|
|
623
|
+
if (code.slice(index - indexThrowInline, index) === toThrowErrorMatchingInlineName) {
|
|
624
|
+
return {
|
|
625
|
+
code: code.slice(index - indexThrowInline),
|
|
626
|
+
index: index - indexThrowInline
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
return {
|
|
630
|
+
code: code.slice(index),
|
|
631
|
+
index
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
const startRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*[\w$]*(['"`)])/;
|
|
635
|
+
function replaceInlineSnap(code, s, currentIndex, newSnap) {
|
|
636
|
+
const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex);
|
|
637
|
+
const startMatch = startRegex.exec(codeStartingAtIndex);
|
|
638
|
+
const firstKeywordMatch = /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/.exec(codeStartingAtIndex);
|
|
639
|
+
if (!startMatch || startMatch.index !== (firstKeywordMatch === null || firstKeywordMatch === void 0 ? void 0 : firstKeywordMatch.index)) {
|
|
640
|
+
return replaceObjectSnap(code, s, index, newSnap);
|
|
641
|
+
}
|
|
642
|
+
const quote = startMatch[1];
|
|
643
|
+
const startIndex = index + startMatch.index + startMatch[0].length;
|
|
644
|
+
const snapString = prepareSnapString(newSnap, code, index);
|
|
645
|
+
if (quote === ")") {
|
|
646
|
+
s.appendRight(startIndex - 1, snapString);
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
const quoteEndRE = new RegExp(`(?:^|[^\\\\])${quote}`);
|
|
650
|
+
const endMatch = quoteEndRE.exec(code.slice(startIndex));
|
|
651
|
+
if (!endMatch) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
const endIndex = startIndex + endMatch.index + endMatch[0].length;
|
|
655
|
+
s.overwrite(startIndex - 1, endIndex, snapString);
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
const INDENTATION_REGEX = /^([^\S\n]*)\S/m;
|
|
659
|
+
function stripSnapshotIndentation(inlineSnapshot) {
|
|
660
|
+
var _lines$at;
|
|
661
|
+
// Find indentation if exists.
|
|
662
|
+
const match = inlineSnapshot.match(INDENTATION_REGEX);
|
|
663
|
+
if (!match || !match[1]) {
|
|
664
|
+
// No indentation.
|
|
665
|
+
return inlineSnapshot;
|
|
666
|
+
}
|
|
667
|
+
const indentation = match[1];
|
|
668
|
+
const lines = inlineSnapshot.split(/\n/g);
|
|
669
|
+
if (lines.length <= 2) {
|
|
670
|
+
// Must be at least 3 lines.
|
|
671
|
+
return inlineSnapshot;
|
|
672
|
+
}
|
|
673
|
+
if (lines[0].trim() !== "" || ((_lines$at = lines.at(-1)) === null || _lines$at === void 0 ? void 0 : _lines$at.trim()) !== "") {
|
|
674
|
+
// If not blank first and last lines, abort.
|
|
675
|
+
return inlineSnapshot;
|
|
676
|
+
}
|
|
677
|
+
for (let i = 1; i < lines.length - 1; i++) {
|
|
678
|
+
if (lines[i] !== "") {
|
|
679
|
+
if (lines[i].indexOf(indentation) !== 0) {
|
|
680
|
+
// All lines except first and last should either be blank or have the same
|
|
681
|
+
// indent as the first line (or more). If this isn't the case we don't
|
|
682
|
+
// want to touch the snapshot at all.
|
|
683
|
+
return inlineSnapshot;
|
|
684
|
+
}
|
|
685
|
+
lines[i] = lines[i].substring(indentation.length);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
// Last line is a special case because it won't have the same indent as others
|
|
689
|
+
// but may still have been given some indent to line up.
|
|
690
|
+
lines[lines.length - 1] = "";
|
|
691
|
+
// Return inline snapshot, now at indent 0.
|
|
692
|
+
inlineSnapshot = lines.join("\n");
|
|
693
|
+
return inlineSnapshot;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
async function saveRawSnapshots(environment, snapshots) {
|
|
697
|
+
await Promise.all(snapshots.map(async (snap) => {
|
|
698
|
+
if (!snap.readonly) {
|
|
699
|
+
await environment.saveSnapshotFile(snap.file, snap.snapshot);
|
|
700
|
+
}
|
|
701
|
+
}));
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function getDefaultExportFromCjs(x) {
|
|
705
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
var naturalCompare$1 = {exports: {}};
|
|
709
|
+
|
|
710
|
+
var hasRequiredNaturalCompare;
|
|
711
|
+
|
|
712
|
+
function requireNaturalCompare () {
|
|
713
|
+
if (hasRequiredNaturalCompare) return naturalCompare$1.exports;
|
|
714
|
+
hasRequiredNaturalCompare = 1;
|
|
715
|
+
/*
|
|
716
|
+
* @version 1.4.0
|
|
717
|
+
* @date 2015-10-26
|
|
718
|
+
* @stability 3 - Stable
|
|
719
|
+
* @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
|
|
720
|
+
* @license MIT License
|
|
721
|
+
*/
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
var naturalCompare = function(a, b) {
|
|
725
|
+
var i, codeA
|
|
726
|
+
, codeB = 1
|
|
727
|
+
, posA = 0
|
|
728
|
+
, posB = 0
|
|
729
|
+
, alphabet = String.alphabet;
|
|
730
|
+
|
|
731
|
+
function getCode(str, pos, code) {
|
|
732
|
+
if (code) {
|
|
733
|
+
for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
|
|
734
|
+
return +str.slice(pos - 1, i)
|
|
735
|
+
}
|
|
736
|
+
code = alphabet && alphabet.indexOf(str.charAt(pos));
|
|
737
|
+
return code > -1 ? code + 76 : ((code = str.charCodeAt(pos) || 0), code < 45 || code > 127) ? code
|
|
738
|
+
: code < 46 ? 65 // -
|
|
739
|
+
: code < 48 ? code - 1
|
|
740
|
+
: code < 58 ? code + 18 // 0-9
|
|
741
|
+
: code < 65 ? code - 11
|
|
742
|
+
: code < 91 ? code + 11 // A-Z
|
|
743
|
+
: code < 97 ? code - 37
|
|
744
|
+
: code < 123 ? code + 5 // a-z
|
|
745
|
+
: code - 63
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
if ((a+="") != (b+="")) for (;codeB;) {
|
|
750
|
+
codeA = getCode(a, posA++);
|
|
751
|
+
codeB = getCode(b, posB++);
|
|
752
|
+
|
|
753
|
+
if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
|
|
754
|
+
codeA = getCode(a, posA, posA);
|
|
755
|
+
codeB = getCode(b, posB, posA = i);
|
|
756
|
+
posB = i;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (codeA != codeB) return (codeA < codeB) ? -1 : 1
|
|
760
|
+
}
|
|
761
|
+
return 0
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
try {
|
|
765
|
+
naturalCompare$1.exports = naturalCompare;
|
|
766
|
+
} catch (e) {
|
|
767
|
+
String.naturalCompare = naturalCompare;
|
|
768
|
+
}
|
|
769
|
+
return naturalCompare$1.exports;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
var naturalCompareExports = requireNaturalCompare();
|
|
773
|
+
var naturalCompare = /*@__PURE__*/getDefaultExportFromCjs(naturalCompareExports);
|
|
774
|
+
|
|
775
|
+
const serialize$1 = (val, config, indentation, depth, refs, printer) => {
|
|
776
|
+
// Serialize a non-default name, even if config.printFunctionName is false.
|
|
777
|
+
const name = val.getMockName();
|
|
778
|
+
const nameString = name === "vi.fn()" ? "" : ` ${name}`;
|
|
779
|
+
let callsString = "";
|
|
780
|
+
if (val.mock.calls.length !== 0) {
|
|
781
|
+
const indentationNext = indentation + config.indent;
|
|
782
|
+
callsString = ` {${config.spacingOuter}${indentationNext}"calls": ${printer(val.mock.calls, config, indentationNext, depth, refs)}${config.min ? ", " : ","}${config.spacingOuter}${indentationNext}"results": ${printer(val.mock.results, config, indentationNext, depth, refs)}${config.min ? "" : ","}${config.spacingOuter}${indentation}}`;
|
|
783
|
+
}
|
|
784
|
+
return `[MockFunction${nameString}]${callsString}`;
|
|
785
|
+
};
|
|
786
|
+
const test = (val) => val && !!val._isMockFunction;
|
|
787
|
+
const plugin = {
|
|
788
|
+
serialize: serialize$1,
|
|
789
|
+
test
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
const { DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent, AsymmetricMatcher } = plugins;
|
|
793
|
+
let PLUGINS = [
|
|
794
|
+
ReactTestComponent,
|
|
795
|
+
ReactElement,
|
|
796
|
+
DOMElement,
|
|
797
|
+
DOMCollection,
|
|
798
|
+
Immutable,
|
|
799
|
+
AsymmetricMatcher,
|
|
800
|
+
plugin
|
|
801
|
+
];
|
|
802
|
+
function addSerializer(plugin) {
|
|
803
|
+
PLUGINS = [plugin].concat(PLUGINS);
|
|
804
|
+
}
|
|
805
|
+
function getSerializers() {
|
|
806
|
+
return PLUGINS;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// TODO: rewrite and clean up
|
|
810
|
+
function testNameToKey(testName, count) {
|
|
811
|
+
return `${testName} ${count}`;
|
|
812
|
+
}
|
|
813
|
+
function keyToTestName(key) {
|
|
814
|
+
if (!/ \d+$/.test(key)) {
|
|
815
|
+
throw new Error("Snapshot keys must end with a number.");
|
|
816
|
+
}
|
|
817
|
+
return key.replace(/ \d+$/, "");
|
|
818
|
+
}
|
|
819
|
+
function getSnapshotData(content, options) {
|
|
820
|
+
const update = options.updateSnapshot;
|
|
821
|
+
const data = Object.create(null);
|
|
822
|
+
let snapshotContents = "";
|
|
823
|
+
let dirty = false;
|
|
824
|
+
if (content != null) {
|
|
825
|
+
try {
|
|
826
|
+
snapshotContents = content;
|
|
827
|
+
// eslint-disable-next-line no-new-func
|
|
828
|
+
const populate = new Function("exports", snapshotContents);
|
|
829
|
+
populate(data);
|
|
830
|
+
} catch {}
|
|
831
|
+
}
|
|
832
|
+
// const validationResult = validateSnapshotVersion(snapshotContents)
|
|
833
|
+
const isInvalid = snapshotContents;
|
|
834
|
+
// if (update === 'none' && isInvalid)
|
|
835
|
+
// throw validationResult
|
|
836
|
+
if ((update === "all" || update === "new") && isInvalid) {
|
|
837
|
+
dirty = true;
|
|
838
|
+
}
|
|
839
|
+
return {
|
|
840
|
+
data,
|
|
841
|
+
dirty
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
// Add extra line breaks at beginning and end of multiline snapshot
|
|
845
|
+
// to make the content easier to read.
|
|
846
|
+
function addExtraLineBreaks(string) {
|
|
847
|
+
return string.includes("\n") ? `\n${string}\n` : string;
|
|
848
|
+
}
|
|
849
|
+
// Remove extra line breaks at beginning and end of multiline snapshot.
|
|
850
|
+
// Instead of trim, which can remove additional newlines or spaces
|
|
851
|
+
// at beginning or end of the content from a custom serializer.
|
|
852
|
+
function removeExtraLineBreaks(string) {
|
|
853
|
+
return string.length > 2 && string[0] === "\n" && string.endsWith("\n") ? string.slice(1, -1) : string;
|
|
854
|
+
}
|
|
855
|
+
// export const removeLinesBeforeExternalMatcherTrap = (stack: string): string => {
|
|
856
|
+
// const lines = stack.split('\n')
|
|
857
|
+
// for (let i = 0; i < lines.length; i += 1) {
|
|
858
|
+
// // It's a function name specified in `packages/expect/src/index.ts`
|
|
859
|
+
// // for external custom matchers.
|
|
860
|
+
// if (lines[i].includes('__EXTERNAL_MATCHER_TRAP__'))
|
|
861
|
+
// return lines.slice(i + 1).join('\n')
|
|
862
|
+
// }
|
|
863
|
+
// return stack
|
|
864
|
+
// }
|
|
865
|
+
const escapeRegex = true;
|
|
866
|
+
const printFunctionName = false;
|
|
867
|
+
function serialize(val, indent = 2, formatOverrides = {}) {
|
|
868
|
+
return normalizeNewlines(format(val, {
|
|
869
|
+
escapeRegex,
|
|
870
|
+
indent,
|
|
871
|
+
plugins: getSerializers(),
|
|
872
|
+
printFunctionName,
|
|
873
|
+
...formatOverrides
|
|
874
|
+
}));
|
|
875
|
+
}
|
|
876
|
+
function escapeBacktickString(str) {
|
|
877
|
+
return str.replace(/`|\\|\$\{/g, "\\$&");
|
|
878
|
+
}
|
|
879
|
+
function printBacktickString(str) {
|
|
880
|
+
return `\`${escapeBacktickString(str)}\``;
|
|
881
|
+
}
|
|
882
|
+
function normalizeNewlines(string) {
|
|
883
|
+
return string.replace(/\r\n|\r/g, "\n");
|
|
884
|
+
}
|
|
885
|
+
async function saveSnapshotFile(environment, snapshotData, snapshotPath) {
|
|
886
|
+
const snapshots = Object.keys(snapshotData).sort(naturalCompare).map((key) => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`);
|
|
887
|
+
const content = `${environment.getHeader()}\n\n${snapshots.join("\n\n")}\n`;
|
|
888
|
+
const oldContent = await environment.readSnapshotFile(snapshotPath);
|
|
889
|
+
const skipWriting = oldContent != null && oldContent === content;
|
|
890
|
+
if (skipWriting) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
await environment.saveSnapshotFile(snapshotPath, content);
|
|
894
|
+
}
|
|
895
|
+
function deepMergeArray(target = [], source = []) {
|
|
896
|
+
const mergedOutput = Array.from(target);
|
|
897
|
+
source.forEach((sourceElement, index) => {
|
|
898
|
+
const targetElement = mergedOutput[index];
|
|
899
|
+
if (Array.isArray(target[index])) {
|
|
900
|
+
mergedOutput[index] = deepMergeArray(target[index], sourceElement);
|
|
901
|
+
} else if (isObject(targetElement)) {
|
|
902
|
+
mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
|
|
903
|
+
} else {
|
|
904
|
+
// Source does not exist in target or target is primitive and cannot be deep merged
|
|
905
|
+
mergedOutput[index] = sourceElement;
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
return mergedOutput;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Deep merge, but considers asymmetric matchers. Unlike base util's deep merge,
|
|
912
|
+
* will merge any object-like instance.
|
|
913
|
+
* Compatible with Jest's snapshot matcher. Should not be used outside of snapshot.
|
|
914
|
+
*
|
|
915
|
+
* @example
|
|
916
|
+
* ```ts
|
|
917
|
+
* toMatchSnapshot({
|
|
918
|
+
* name: expect.stringContaining('text')
|
|
919
|
+
* })
|
|
920
|
+
* ```
|
|
921
|
+
*/
|
|
922
|
+
function deepMergeSnapshot(target, source) {
|
|
923
|
+
if (isObject(target) && isObject(source)) {
|
|
924
|
+
const mergedOutput = { ...target };
|
|
925
|
+
Object.keys(source).forEach((key) => {
|
|
926
|
+
if (isObject(source[key]) && !source[key].$$typeof) {
|
|
927
|
+
if (!(key in target)) {
|
|
928
|
+
Object.assign(mergedOutput, { [key]: source[key] });
|
|
929
|
+
} else {
|
|
930
|
+
mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
|
|
931
|
+
}
|
|
932
|
+
} else if (Array.isArray(source[key])) {
|
|
933
|
+
mergedOutput[key] = deepMergeArray(target[key], source[key]);
|
|
934
|
+
} else {
|
|
935
|
+
Object.assign(mergedOutput, { [key]: source[key] });
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
return mergedOutput;
|
|
939
|
+
} else if (Array.isArray(target) && Array.isArray(source)) {
|
|
940
|
+
return deepMergeArray(target, source);
|
|
941
|
+
}
|
|
942
|
+
return target;
|
|
943
|
+
}
|
|
944
|
+
class DefaultMap extends Map {
|
|
945
|
+
constructor(defaultFn, entries) {
|
|
946
|
+
super(entries);
|
|
947
|
+
this.defaultFn = defaultFn;
|
|
948
|
+
}
|
|
949
|
+
get(key) {
|
|
950
|
+
if (!this.has(key)) {
|
|
951
|
+
this.set(key, this.defaultFn(key));
|
|
952
|
+
}
|
|
953
|
+
return super.get(key);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
class CounterMap extends DefaultMap {
|
|
957
|
+
constructor() {
|
|
958
|
+
super(() => 0);
|
|
959
|
+
}
|
|
960
|
+
// compat for jest-image-snapshot https://github.com/vitest-dev/vitest/issues/7322
|
|
961
|
+
// `valueOf` and `Snapshot.added` setter allows
|
|
962
|
+
// snapshotState.added = snapshotState.added + 1
|
|
963
|
+
// to function as
|
|
964
|
+
// snapshotState.added.total_ = snapshotState.added.total() + 1
|
|
965
|
+
_total;
|
|
966
|
+
valueOf() {
|
|
967
|
+
return this._total = this.total();
|
|
968
|
+
}
|
|
969
|
+
increment(key) {
|
|
970
|
+
if (typeof this._total !== "undefined") {
|
|
971
|
+
this._total++;
|
|
972
|
+
}
|
|
973
|
+
this.set(key, this.get(key) + 1);
|
|
974
|
+
}
|
|
975
|
+
total() {
|
|
976
|
+
if (typeof this._total !== "undefined") {
|
|
977
|
+
return this._total;
|
|
978
|
+
}
|
|
979
|
+
let total = 0;
|
|
980
|
+
for (const x of this.values()) {
|
|
981
|
+
total += x;
|
|
982
|
+
}
|
|
983
|
+
return total;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function isSameStackPosition(x, y) {
|
|
988
|
+
return x.file === y.file && x.column === y.column && x.line === y.line;
|
|
989
|
+
}
|
|
990
|
+
class SnapshotState {
|
|
991
|
+
_counters = new CounterMap();
|
|
992
|
+
_dirty;
|
|
993
|
+
_updateSnapshot;
|
|
994
|
+
_snapshotData;
|
|
995
|
+
_initialData;
|
|
996
|
+
_inlineSnapshots;
|
|
997
|
+
_inlineSnapshotStacks;
|
|
998
|
+
_testIdToKeys = new DefaultMap(() => []);
|
|
999
|
+
_rawSnapshots;
|
|
1000
|
+
_uncheckedKeys;
|
|
1001
|
+
_snapshotFormat;
|
|
1002
|
+
_environment;
|
|
1003
|
+
_fileExists;
|
|
1004
|
+
expand;
|
|
1005
|
+
// getter/setter for jest-image-snapshot compat
|
|
1006
|
+
// https://github.com/vitest-dev/vitest/issues/7322
|
|
1007
|
+
_added = new CounterMap();
|
|
1008
|
+
_matched = new CounterMap();
|
|
1009
|
+
_unmatched = new CounterMap();
|
|
1010
|
+
_updated = new CounterMap();
|
|
1011
|
+
get added() {
|
|
1012
|
+
return this._added;
|
|
1013
|
+
}
|
|
1014
|
+
set added(value) {
|
|
1015
|
+
this._added._total = value;
|
|
1016
|
+
}
|
|
1017
|
+
get matched() {
|
|
1018
|
+
return this._matched;
|
|
1019
|
+
}
|
|
1020
|
+
set matched(value) {
|
|
1021
|
+
this._matched._total = value;
|
|
1022
|
+
}
|
|
1023
|
+
get unmatched() {
|
|
1024
|
+
return this._unmatched;
|
|
1025
|
+
}
|
|
1026
|
+
set unmatched(value) {
|
|
1027
|
+
this._unmatched._total = value;
|
|
1028
|
+
}
|
|
1029
|
+
get updated() {
|
|
1030
|
+
return this._updated;
|
|
1031
|
+
}
|
|
1032
|
+
set updated(value) {
|
|
1033
|
+
this._updated._total = value;
|
|
1034
|
+
}
|
|
1035
|
+
constructor(testFilePath, snapshotPath, snapshotContent, options) {
|
|
1036
|
+
this.testFilePath = testFilePath;
|
|
1037
|
+
this.snapshotPath = snapshotPath;
|
|
1038
|
+
const { data, dirty } = getSnapshotData(snapshotContent, options);
|
|
1039
|
+
this._fileExists = snapshotContent != null;
|
|
1040
|
+
this._initialData = { ...data };
|
|
1041
|
+
this._snapshotData = { ...data };
|
|
1042
|
+
this._dirty = dirty;
|
|
1043
|
+
this._inlineSnapshots = [];
|
|
1044
|
+
this._inlineSnapshotStacks = [];
|
|
1045
|
+
this._rawSnapshots = [];
|
|
1046
|
+
this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
|
|
1047
|
+
this.expand = options.expand || false;
|
|
1048
|
+
this._updateSnapshot = options.updateSnapshot;
|
|
1049
|
+
this._snapshotFormat = {
|
|
1050
|
+
printBasicPrototype: false,
|
|
1051
|
+
escapeString: false,
|
|
1052
|
+
...options.snapshotFormat
|
|
1053
|
+
};
|
|
1054
|
+
this._environment = options.snapshotEnvironment;
|
|
1055
|
+
}
|
|
1056
|
+
static async create(testFilePath, options) {
|
|
1057
|
+
const snapshotPath = await options.snapshotEnvironment.resolvePath(testFilePath);
|
|
1058
|
+
const content = await options.snapshotEnvironment.readSnapshotFile(snapshotPath);
|
|
1059
|
+
return new SnapshotState(testFilePath, snapshotPath, content, options);
|
|
1060
|
+
}
|
|
1061
|
+
get environment() {
|
|
1062
|
+
return this._environment;
|
|
1063
|
+
}
|
|
1064
|
+
markSnapshotsAsCheckedForTest(testName) {
|
|
1065
|
+
this._uncheckedKeys.forEach((uncheckedKey) => {
|
|
1066
|
+
// skip snapshots with following keys
|
|
1067
|
+
// testName n
|
|
1068
|
+
// testName > xxx n (this is for toMatchSnapshot("xxx") API)
|
|
1069
|
+
if (/ \d+$| > /.test(uncheckedKey.slice(testName.length))) {
|
|
1070
|
+
this._uncheckedKeys.delete(uncheckedKey);
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
clearTest(testId) {
|
|
1075
|
+
// clear inline
|
|
1076
|
+
this._inlineSnapshots = this._inlineSnapshots.filter((s) => s.testId !== testId);
|
|
1077
|
+
this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter((s) => s.testId !== testId);
|
|
1078
|
+
// clear file
|
|
1079
|
+
for (const key of this._testIdToKeys.get(testId)) {
|
|
1080
|
+
const name = keyToTestName(key);
|
|
1081
|
+
const count = this._counters.get(name);
|
|
1082
|
+
if (count > 0) {
|
|
1083
|
+
if (key in this._snapshotData || key in this._initialData) {
|
|
1084
|
+
this._snapshotData[key] = this._initialData[key];
|
|
1085
|
+
}
|
|
1086
|
+
this._counters.set(name, count - 1);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
this._testIdToKeys.delete(testId);
|
|
1090
|
+
// clear stats
|
|
1091
|
+
this.added.delete(testId);
|
|
1092
|
+
this.updated.delete(testId);
|
|
1093
|
+
this.matched.delete(testId);
|
|
1094
|
+
this.unmatched.delete(testId);
|
|
1095
|
+
}
|
|
1096
|
+
_inferInlineSnapshotStack(stacks) {
|
|
1097
|
+
// if called inside resolves/rejects, stacktrace is different
|
|
1098
|
+
const promiseIndex = stacks.findIndex((i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/));
|
|
1099
|
+
if (promiseIndex !== -1) {
|
|
1100
|
+
return stacks[promiseIndex + 3];
|
|
1101
|
+
}
|
|
1102
|
+
// inline snapshot function is called __INLINE_SNAPSHOT__
|
|
1103
|
+
// in integrations/snapshot/chai.ts
|
|
1104
|
+
const stackIndex = stacks.findIndex((i) => i.method.includes("__INLINE_SNAPSHOT__"));
|
|
1105
|
+
return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
|
|
1106
|
+
}
|
|
1107
|
+
_addSnapshot(key, receivedSerialized, options) {
|
|
1108
|
+
this._dirty = true;
|
|
1109
|
+
if (options.stack) {
|
|
1110
|
+
this._inlineSnapshots.push({
|
|
1111
|
+
snapshot: receivedSerialized,
|
|
1112
|
+
testId: options.testId,
|
|
1113
|
+
...options.stack
|
|
1114
|
+
});
|
|
1115
|
+
} else if (options.rawSnapshot) {
|
|
1116
|
+
this._rawSnapshots.push({
|
|
1117
|
+
...options.rawSnapshot,
|
|
1118
|
+
snapshot: receivedSerialized
|
|
1119
|
+
});
|
|
1120
|
+
} else {
|
|
1121
|
+
this._snapshotData[key] = receivedSerialized;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
async save() {
|
|
1125
|
+
const hasExternalSnapshots = Object.keys(this._snapshotData).length;
|
|
1126
|
+
const hasInlineSnapshots = this._inlineSnapshots.length;
|
|
1127
|
+
const hasRawSnapshots = this._rawSnapshots.length;
|
|
1128
|
+
const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
|
|
1129
|
+
const status = {
|
|
1130
|
+
deleted: false,
|
|
1131
|
+
saved: false
|
|
1132
|
+
};
|
|
1133
|
+
if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
|
|
1134
|
+
if (hasExternalSnapshots) {
|
|
1135
|
+
await saveSnapshotFile(this._environment, this._snapshotData, this.snapshotPath);
|
|
1136
|
+
this._fileExists = true;
|
|
1137
|
+
}
|
|
1138
|
+
if (hasInlineSnapshots) {
|
|
1139
|
+
await saveInlineSnapshots(this._environment, this._inlineSnapshots);
|
|
1140
|
+
}
|
|
1141
|
+
if (hasRawSnapshots) {
|
|
1142
|
+
await saveRawSnapshots(this._environment, this._rawSnapshots);
|
|
1143
|
+
}
|
|
1144
|
+
status.saved = true;
|
|
1145
|
+
} else if (!hasExternalSnapshots && this._fileExists) {
|
|
1146
|
+
if (this._updateSnapshot === "all") {
|
|
1147
|
+
await this._environment.removeSnapshotFile(this.snapshotPath);
|
|
1148
|
+
this._fileExists = false;
|
|
1149
|
+
}
|
|
1150
|
+
status.deleted = true;
|
|
1151
|
+
}
|
|
1152
|
+
return status;
|
|
1153
|
+
}
|
|
1154
|
+
getUncheckedCount() {
|
|
1155
|
+
return this._uncheckedKeys.size || 0;
|
|
1156
|
+
}
|
|
1157
|
+
getUncheckedKeys() {
|
|
1158
|
+
return Array.from(this._uncheckedKeys);
|
|
1159
|
+
}
|
|
1160
|
+
removeUncheckedKeys() {
|
|
1161
|
+
if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
|
|
1162
|
+
this._dirty = true;
|
|
1163
|
+
this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
|
|
1164
|
+
this._uncheckedKeys.clear();
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
match({ testId, testName, received, key, inlineSnapshot, isInline, error, rawSnapshot }) {
|
|
1168
|
+
// this also increments counter for inline snapshots. maybe we shouldn't?
|
|
1169
|
+
this._counters.increment(testName);
|
|
1170
|
+
const count = this._counters.get(testName);
|
|
1171
|
+
if (!key) {
|
|
1172
|
+
key = testNameToKey(testName, count);
|
|
1173
|
+
}
|
|
1174
|
+
this._testIdToKeys.get(testId).push(key);
|
|
1175
|
+
// Do not mark the snapshot as "checked" if the snapshot is inline and
|
|
1176
|
+
// there's an external snapshot. This way the external snapshot can be
|
|
1177
|
+
// removed with `--updateSnapshot`.
|
|
1178
|
+
if (!(isInline && this._snapshotData[key] !== undefined)) {
|
|
1179
|
+
this._uncheckedKeys.delete(key);
|
|
1180
|
+
}
|
|
1181
|
+
let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, undefined, this._snapshotFormat);
|
|
1182
|
+
if (!rawSnapshot) {
|
|
1183
|
+
receivedSerialized = addExtraLineBreaks(receivedSerialized);
|
|
1184
|
+
}
|
|
1185
|
+
if (rawSnapshot) {
|
|
1186
|
+
// normalize EOL when snapshot contains CRLF but received is LF
|
|
1187
|
+
if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) {
|
|
1188
|
+
rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
|
|
1192
|
+
const expectedTrimmed = rawSnapshot ? expected : expected === null || expected === void 0 ? void 0 : expected.trim();
|
|
1193
|
+
const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : receivedSerialized.trim());
|
|
1194
|
+
const hasSnapshot = expected !== undefined;
|
|
1195
|
+
const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
|
|
1196
|
+
if (pass && !isInline && !rawSnapshot) {
|
|
1197
|
+
// Executing a snapshot file as JavaScript and writing the strings back
|
|
1198
|
+
// when other snapshots have changed loses the proper escaping for some
|
|
1199
|
+
// characters. Since we check every snapshot in every test, use the newly
|
|
1200
|
+
// generated formatted string.
|
|
1201
|
+
// Note that this is only relevant when a snapshot is added and the dirty
|
|
1202
|
+
// flag is set.
|
|
1203
|
+
this._snapshotData[key] = receivedSerialized;
|
|
1204
|
+
}
|
|
1205
|
+
// find call site of toMatchInlineSnapshot
|
|
1206
|
+
let stack;
|
|
1207
|
+
if (isInline) {
|
|
1208
|
+
var _this$environment$pro, _this$environment;
|
|
1209
|
+
const stacks = parseErrorStacktrace(error || new Error("snapshot"), { ignoreStackEntries: [] });
|
|
1210
|
+
const _stack = this._inferInlineSnapshotStack(stacks);
|
|
1211
|
+
if (!_stack) {
|
|
1212
|
+
throw new Error(`@vitest/snapshot: Couldn't infer stack frame for inline snapshot.\n${JSON.stringify(stacks)}`);
|
|
1213
|
+
}
|
|
1214
|
+
stack = ((_this$environment$pro = (_this$environment = this.environment).processStackTrace) === null || _this$environment$pro === void 0 ? void 0 : _this$environment$pro.call(_this$environment, _stack)) || _stack;
|
|
1215
|
+
// removing 1 column, because source map points to the wrong
|
|
1216
|
+
// location for js files, but `column-1` points to the same in both js/ts
|
|
1217
|
+
// https://github.com/vitejs/vite/issues/8657
|
|
1218
|
+
stack.column--;
|
|
1219
|
+
// reject multiple inline snapshots at the same location if snapshot is different
|
|
1220
|
+
const snapshotsWithSameStack = this._inlineSnapshotStacks.filter((s) => isSameStackPosition(s, stack));
|
|
1221
|
+
if (snapshotsWithSameStack.length > 0) {
|
|
1222
|
+
// ensure only one snapshot will be written at the same location
|
|
1223
|
+
this._inlineSnapshots = this._inlineSnapshots.filter((s) => !isSameStackPosition(s, stack));
|
|
1224
|
+
const differentSnapshot = snapshotsWithSameStack.find((s) => s.snapshot !== receivedSerialized);
|
|
1225
|
+
if (differentSnapshot) {
|
|
1226
|
+
throw Object.assign(new Error("toMatchInlineSnapshot with different snapshots cannot be called at the same location"), {
|
|
1227
|
+
actual: receivedSerialized,
|
|
1228
|
+
expected: differentSnapshot.snapshot
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
this._inlineSnapshotStacks.push({
|
|
1233
|
+
...stack,
|
|
1234
|
+
testId,
|
|
1235
|
+
snapshot: receivedSerialized
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
// These are the conditions on when to write snapshots:
|
|
1239
|
+
// * There's no snapshot file in a non-CI environment.
|
|
1240
|
+
// * There is a snapshot file and we decided to update the snapshot.
|
|
1241
|
+
// * There is a snapshot file, but it doesn't have this snapshot.
|
|
1242
|
+
// These are the conditions on when not to write snapshots:
|
|
1243
|
+
// * The update flag is set to 'none'.
|
|
1244
|
+
// * There's no snapshot file or a file without this snapshot on a CI environment.
|
|
1245
|
+
if (hasSnapshot && this._updateSnapshot === "all" || (!hasSnapshot || !snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
|
|
1246
|
+
if (this._updateSnapshot === "all") {
|
|
1247
|
+
if (!pass) {
|
|
1248
|
+
if (hasSnapshot) {
|
|
1249
|
+
this.updated.increment(testId);
|
|
1250
|
+
} else {
|
|
1251
|
+
this.added.increment(testId);
|
|
1252
|
+
}
|
|
1253
|
+
this._addSnapshot(key, receivedSerialized, {
|
|
1254
|
+
stack,
|
|
1255
|
+
testId,
|
|
1256
|
+
rawSnapshot
|
|
1257
|
+
});
|
|
1258
|
+
} else {
|
|
1259
|
+
this.matched.increment(testId);
|
|
1260
|
+
}
|
|
1261
|
+
} else {
|
|
1262
|
+
this._addSnapshot(key, receivedSerialized, {
|
|
1263
|
+
stack,
|
|
1264
|
+
testId,
|
|
1265
|
+
rawSnapshot
|
|
1266
|
+
});
|
|
1267
|
+
this.added.increment(testId);
|
|
1268
|
+
}
|
|
1269
|
+
return {
|
|
1270
|
+
actual: "",
|
|
1271
|
+
count,
|
|
1272
|
+
expected: "",
|
|
1273
|
+
key,
|
|
1274
|
+
pass: true
|
|
1275
|
+
};
|
|
1276
|
+
} else {
|
|
1277
|
+
if (!pass) {
|
|
1278
|
+
this.unmatched.increment(testId);
|
|
1279
|
+
return {
|
|
1280
|
+
actual: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
|
|
1281
|
+
count,
|
|
1282
|
+
expected: expectedTrimmed !== undefined ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed) : undefined,
|
|
1283
|
+
key,
|
|
1284
|
+
pass: false
|
|
1285
|
+
};
|
|
1286
|
+
} else {
|
|
1287
|
+
this.matched.increment(testId);
|
|
1288
|
+
return {
|
|
1289
|
+
actual: "",
|
|
1290
|
+
count,
|
|
1291
|
+
expected: "",
|
|
1292
|
+
key,
|
|
1293
|
+
pass: true
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
async pack() {
|
|
1299
|
+
const snapshot = {
|
|
1300
|
+
filepath: this.testFilePath,
|
|
1301
|
+
added: 0,
|
|
1302
|
+
fileDeleted: false,
|
|
1303
|
+
matched: 0,
|
|
1304
|
+
unchecked: 0,
|
|
1305
|
+
uncheckedKeys: [],
|
|
1306
|
+
unmatched: 0,
|
|
1307
|
+
updated: 0
|
|
1308
|
+
};
|
|
1309
|
+
const uncheckedCount = this.getUncheckedCount();
|
|
1310
|
+
const uncheckedKeys = this.getUncheckedKeys();
|
|
1311
|
+
if (uncheckedCount) {
|
|
1312
|
+
this.removeUncheckedKeys();
|
|
1313
|
+
}
|
|
1314
|
+
const status = await this.save();
|
|
1315
|
+
snapshot.fileDeleted = status.deleted;
|
|
1316
|
+
snapshot.added = this.added.total();
|
|
1317
|
+
snapshot.matched = this.matched.total();
|
|
1318
|
+
snapshot.unmatched = this.unmatched.total();
|
|
1319
|
+
snapshot.updated = this.updated.total();
|
|
1320
|
+
snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
|
|
1321
|
+
snapshot.uncheckedKeys = Array.from(uncheckedKeys);
|
|
1322
|
+
return snapshot;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function createMismatchError(message, expand, actual, expected) {
|
|
1327
|
+
const error = new Error(message);
|
|
1328
|
+
Object.defineProperty(error, "actual", {
|
|
1329
|
+
value: actual,
|
|
1330
|
+
enumerable: true,
|
|
1331
|
+
configurable: true,
|
|
1332
|
+
writable: true
|
|
1333
|
+
});
|
|
1334
|
+
Object.defineProperty(error, "expected", {
|
|
1335
|
+
value: expected,
|
|
1336
|
+
enumerable: true,
|
|
1337
|
+
configurable: true,
|
|
1338
|
+
writable: true
|
|
1339
|
+
});
|
|
1340
|
+
Object.defineProperty(error, "diffOptions", { value: { expand } });
|
|
1341
|
+
return error;
|
|
1342
|
+
}
|
|
1343
|
+
class SnapshotClient {
|
|
1344
|
+
snapshotStateMap = new Map();
|
|
1345
|
+
constructor(options = {}) {
|
|
1346
|
+
this.options = options;
|
|
1347
|
+
}
|
|
1348
|
+
async setup(filepath, options) {
|
|
1349
|
+
if (this.snapshotStateMap.has(filepath)) {
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
this.snapshotStateMap.set(filepath, await SnapshotState.create(filepath, options));
|
|
1353
|
+
}
|
|
1354
|
+
async finish(filepath) {
|
|
1355
|
+
const state = this.getSnapshotState(filepath);
|
|
1356
|
+
const result = await state.pack();
|
|
1357
|
+
this.snapshotStateMap.delete(filepath);
|
|
1358
|
+
return result;
|
|
1359
|
+
}
|
|
1360
|
+
skipTest(filepath, testName) {
|
|
1361
|
+
const state = this.getSnapshotState(filepath);
|
|
1362
|
+
state.markSnapshotsAsCheckedForTest(testName);
|
|
1363
|
+
}
|
|
1364
|
+
clearTest(filepath, testId) {
|
|
1365
|
+
const state = this.getSnapshotState(filepath);
|
|
1366
|
+
state.clearTest(testId);
|
|
1367
|
+
}
|
|
1368
|
+
getSnapshotState(filepath) {
|
|
1369
|
+
const state = this.snapshotStateMap.get(filepath);
|
|
1370
|
+
if (!state) {
|
|
1371
|
+
throw new Error(`The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`);
|
|
1372
|
+
}
|
|
1373
|
+
return state;
|
|
1374
|
+
}
|
|
1375
|
+
assert(options) {
|
|
1376
|
+
const { filepath, name, testId = name, message, isInline = false, properties, inlineSnapshot, error, errorMessage, rawSnapshot } = options;
|
|
1377
|
+
let { received } = options;
|
|
1378
|
+
if (!filepath) {
|
|
1379
|
+
throw new Error("Snapshot cannot be used outside of test");
|
|
1380
|
+
}
|
|
1381
|
+
const snapshotState = this.getSnapshotState(filepath);
|
|
1382
|
+
if (typeof properties === "object") {
|
|
1383
|
+
if (typeof received !== "object" || !received) {
|
|
1384
|
+
throw new Error("Received value must be an object when the matcher has properties");
|
|
1385
|
+
}
|
|
1386
|
+
try {
|
|
1387
|
+
var _this$options$isEqual, _this$options;
|
|
1388
|
+
const pass = ((_this$options$isEqual = (_this$options = this.options).isEqual) === null || _this$options$isEqual === void 0 ? void 0 : _this$options$isEqual.call(_this$options, received, properties)) ?? false;
|
|
1389
|
+
// const pass = equals(received, properties, [iterableEquality, subsetEquality])
|
|
1390
|
+
if (!pass) {
|
|
1391
|
+
throw createMismatchError("Snapshot properties mismatched", snapshotState.expand, received, properties);
|
|
1392
|
+
} else {
|
|
1393
|
+
received = deepMergeSnapshot(received, properties);
|
|
1394
|
+
}
|
|
1395
|
+
} catch (err) {
|
|
1396
|
+
err.message = errorMessage || "Snapshot mismatched";
|
|
1397
|
+
throw err;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
const testName = [name, ...message ? [message] : []].join(" > ");
|
|
1401
|
+
const { actual, expected, key, pass } = snapshotState.match({
|
|
1402
|
+
testId,
|
|
1403
|
+
testName,
|
|
1404
|
+
received,
|
|
1405
|
+
isInline,
|
|
1406
|
+
error,
|
|
1407
|
+
inlineSnapshot,
|
|
1408
|
+
rawSnapshot
|
|
1409
|
+
});
|
|
1410
|
+
if (!pass) {
|
|
1411
|
+
throw createMismatchError(`Snapshot \`${key || "unknown"}\` mismatched`, snapshotState.expand, rawSnapshot ? actual : actual === null || actual === void 0 ? void 0 : actual.trim(), rawSnapshot ? expected : expected === null || expected === void 0 ? void 0 : expected.trim());
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
async assertRaw(options) {
|
|
1415
|
+
if (!options.rawSnapshot) {
|
|
1416
|
+
throw new Error("Raw snapshot is required");
|
|
1417
|
+
}
|
|
1418
|
+
const { filepath, rawSnapshot } = options;
|
|
1419
|
+
if (rawSnapshot.content == null) {
|
|
1420
|
+
if (!filepath) {
|
|
1421
|
+
throw new Error("Snapshot cannot be used outside of test");
|
|
1422
|
+
}
|
|
1423
|
+
const snapshotState = this.getSnapshotState(filepath);
|
|
1424
|
+
// save the filepath, so it don't lose even if the await make it out-of-context
|
|
1425
|
+
options.filepath || (options.filepath = filepath);
|
|
1426
|
+
// resolve and read the raw snapshot file
|
|
1427
|
+
rawSnapshot.file = await snapshotState.environment.resolveRawPath(filepath, rawSnapshot.file);
|
|
1428
|
+
rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) ?? undefined;
|
|
1429
|
+
}
|
|
1430
|
+
return this.assert(options);
|
|
1431
|
+
}
|
|
1432
|
+
clear() {
|
|
1433
|
+
this.snapshotStateMap.clear();
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
export { SnapshotClient, SnapshotState, addSerializer, getSerializers, stripSnapshotIndentation };
|