@describe-me/vitest 0.5.4 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -8
- package/dist/browser-profile.d.ts +3 -0
- package/dist/browser-profile.js +27 -0
- package/dist/build-live.d.ts +26 -0
- package/dist/build-live.js +106 -0
- package/dist/check-live-enabled.d.ts +3 -0
- package/dist/check-live-enabled.js +10 -0
- package/dist/collect-live-suites.d.ts +7 -0
- package/dist/collect-live-suites.js +25 -0
- package/dist/create-live-server.d.ts +29 -0
- package/dist/create-live-server.js +55 -0
- package/dist/detect-environment.d.ts +4 -0
- package/dist/detect-environment.js +4 -0
- package/dist/dom-profile.d.ts +3 -0
- package/dist/dom-profile.js +38 -0
- package/dist/environment-profile.d.ts +41 -0
- package/dist/environment-profile.js +1 -0
- package/dist/find-live-config-file.d.ts +2 -0
- package/dist/find-live-config-file.js +16 -0
- package/dist/find-live-test.d.ts +13 -0
- package/dist/find-live-test.js +31 -0
- package/dist/free-live-port.d.ts +5 -0
- package/dist/free-live-port.js +16 -0
- package/dist/import-live-vite.d.ts +7 -0
- package/dist/import-live-vite.js +46 -0
- package/dist/install-live-globals.d.ts +5 -0
- package/dist/install-live-globals.js +33 -0
- package/dist/is-adapter-module.d.ts +6 -0
- package/dist/is-adapter-module.js +11 -0
- package/dist/live-arg-label.d.ts +5 -0
- package/dist/live-arg-label.js +38 -0
- package/dist/live-build-plugin.d.ts +18 -0
- package/dist/live-build-plugin.js +89 -0
- package/dist/live-each-name.d.ts +6 -0
- package/dist/live-each-name.js +146 -0
- package/dist/live-entry-source.d.ts +9 -0
- package/dist/live-entry-source.js +46 -0
- package/dist/live-env.d.ts +6 -0
- package/dist/live-env.js +6 -0
- package/dist/live-error-detail.d.ts +2 -0
- package/dist/live-error-detail.js +16 -0
- package/dist/live-export.d.ts +10 -0
- package/dist/live-export.js +48 -0
- package/dist/live-fixture-props.d.ts +12 -0
- package/dist/live-fixture-props.js +87 -0
- package/dist/live-fixture-registrations.d.ts +21 -0
- package/dist/live-fixture-registrations.js +69 -0
- package/dist/live-fixture-values.d.ts +9 -0
- package/dist/live-fixture-values.js +125 -0
- package/dist/live-format-placeholder.d.ts +6 -0
- package/dist/live-format-placeholder.js +70 -0
- package/dist/live-hook.d.ts +8 -0
- package/dist/live-hook.js +12 -0
- package/dist/live-inspect.d.ts +7 -0
- package/dist/live-inspect.js +240 -0
- package/dist/live-loupe-inspect.d.ts +6 -0
- package/dist/live-loupe-inspect.js +330 -0
- package/dist/live-mock.d.ts +18 -0
- package/dist/live-mock.js +105 -0
- package/dist/live-module-ids.d.ts +8 -0
- package/dist/live-module-ids.js +8 -0
- package/dist/live-optimize-deps.d.ts +13 -0
- package/dist/live-optimize-deps.js +67 -0
- package/dist/live-page-html.d.ts +5 -0
- package/dist/live-page-html.js +21 -0
- package/dist/live-page-middleware.d.ts +6 -0
- package/dist/live-page-middleware.js +28 -0
- package/dist/live-page-settings.d.ts +20 -0
- package/dist/live-page-settings.js +24 -0
- package/dist/live-plugin-protocol.d.ts +3 -0
- package/dist/live-plugin-protocol.js +13 -0
- package/dist/live-plugin.d.ts +13 -0
- package/dist/live-plugin.js +148 -0
- package/dist/live-project-plugins.d.ts +8 -0
- package/dist/live-project-plugins.js +23 -0
- package/dist/live-registrar.d.ts +10 -0
- package/dist/live-registrar.js +174 -0
- package/dist/live-registry.d.ts +14 -0
- package/dist/live-registry.js +14 -0
- package/dist/live-runtime.d.ts +2 -0
- package/dist/live-runtime.js +3 -0
- package/dist/live-setup-files.d.ts +15 -0
- package/dist/live-setup-files.js +56 -0
- package/dist/live-shim-source.d.ts +6 -0
- package/dist/live-shim-source.js +9 -0
- package/dist/live-spy-on.d.ts +7 -0
- package/dist/live-spy-on.js +27 -0
- package/dist/live-step.d.ts +2 -0
- package/dist/live-step.js +4 -0
- package/dist/live-string-literal.d.ts +2 -0
- package/dist/live-string-literal.js +7 -0
- package/dist/live-suite.d.ts +28 -0
- package/dist/live-suite.js +18 -0
- package/dist/live-test-context.d.ts +24 -0
- package/dist/live-test-context.js +26 -0
- package/dist/live-test-files-source.d.ts +6 -0
- package/dist/live-test-files-source.js +10 -0
- package/dist/live-vi.d.ts +7 -0
- package/dist/live-vi.js +50 -0
- package/dist/live.d.ts +2 -0
- package/dist/live.js +3 -0
- package/dist/load-live-config.d.ts +9 -0
- package/dist/load-live-config.js +25 -0
- package/dist/load-profile.d.ts +4 -0
- package/dist/load-profile.js +9 -0
- package/dist/notice-live-module-mock.d.ts +5 -0
- package/dist/notice-live-module-mock.js +25 -0
- package/dist/package-name-of.d.ts +5 -0
- package/dist/package-name-of.js +7 -0
- package/dist/plugin.d.ts +11 -2
- package/dist/plugin.js +40 -86
- package/dist/read-live-browser-names.d.ts +5 -0
- package/dist/read-live-browser-names.js +19 -0
- package/dist/read-live-params.d.ts +18 -0
- package/dist/read-live-params.js +63 -0
- package/dist/read-live-vitest-major.d.ts +6 -0
- package/dist/read-live-vitest-major.js +20 -0
- package/dist/read-live-vitest-names.d.ts +5 -0
- package/dist/read-live-vitest-names.js +40 -0
- package/dist/register-recording-hooks.d.ts +2 -1
- package/dist/register-recording-hooks.js +8 -7
- package/dist/report-live-errors.d.ts +5 -0
- package/dist/report-live-errors.js +24 -0
- package/dist/reporter.d.ts +3 -0
- package/dist/reporter.js +9 -0
- package/dist/run-live-test.d.ts +10 -0
- package/dist/run-live-test.js +118 -0
- package/dist/set-up-project.d.ts +12 -0
- package/dist/set-up-project.js +39 -0
- package/dist/start-live-page.d.ts +29 -0
- package/dist/start-live-page.js +62 -0
- package/dist/validate-live-option.d.ts +11 -0
- package/dist/validate-live-option.js +29 -0
- package/package.json +11 -3
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { liveFixtureProps } from './live-fixture-props.js';
|
|
2
|
+
/** Names of the test context that are never fixtures. */
|
|
3
|
+
const BUILT_IN = new Set([
|
|
4
|
+
'task',
|
|
5
|
+
'expect',
|
|
6
|
+
'skip',
|
|
7
|
+
'signal',
|
|
8
|
+
'onTestFinished',
|
|
9
|
+
'onTestFailed',
|
|
10
|
+
'annotate',
|
|
11
|
+
]);
|
|
12
|
+
function messageOf(error) {
|
|
13
|
+
return error instanceof Error ? error.message : String(error);
|
|
14
|
+
}
|
|
15
|
+
/** The error with the fixture's name in front, and the stack of the original. */
|
|
16
|
+
function namedError(name, error) {
|
|
17
|
+
const named = new Error(`fixture "${name}": ${messageOf(error)}`);
|
|
18
|
+
if (error instanceof Error && typeof error.stack === 'string') {
|
|
19
|
+
const heading = String(error);
|
|
20
|
+
const frames = error.stack.startsWith(heading)
|
|
21
|
+
? error.stack.slice(heading.length)
|
|
22
|
+
: `\n${error.stack}`;
|
|
23
|
+
named.stack = `${String(named)}${frames}`;
|
|
24
|
+
}
|
|
25
|
+
return named;
|
|
26
|
+
}
|
|
27
|
+
/** The fixtures a fixture function depends on. Its own name means the definition it redefines. */
|
|
28
|
+
function dependenciesOf(fixture, fixtures) {
|
|
29
|
+
let names;
|
|
30
|
+
try {
|
|
31
|
+
names =
|
|
32
|
+
fixture.source === undefined
|
|
33
|
+
? new Set()
|
|
34
|
+
: liveFixtureProps({ callback: fixture.source, index: 0 });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw namedError(fixture.name, error);
|
|
38
|
+
}
|
|
39
|
+
const dependencies = [];
|
|
40
|
+
for (const name of names) {
|
|
41
|
+
const dependency = name === fixture.name ? fixture.parent : fixtures.get(name);
|
|
42
|
+
if (dependency !== undefined) {
|
|
43
|
+
dependencies.push(dependency);
|
|
44
|
+
}
|
|
45
|
+
else if (name === fixture.name) {
|
|
46
|
+
throw new Error(`fixture "${name}" depends on itself but redefines no fixture`);
|
|
47
|
+
}
|
|
48
|
+
else if (!BUILT_IN.has(name)) {
|
|
49
|
+
throw new Error(`fixture "${fixture.name}" depends on unknown fixture "${name}"`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return dependencies;
|
|
53
|
+
}
|
|
54
|
+
/** The fixtures to compute in order, dependencies first, as Vitest's `resolveDeps` orders them. */
|
|
55
|
+
function pendingOf(used, fixtures, path = new Set(), pending = []) {
|
|
56
|
+
for (const usedFixture of used) {
|
|
57
|
+
let fixture = usedFixture;
|
|
58
|
+
if (pending.includes(fixture)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (typeof fixture.value !== 'function') {
|
|
62
|
+
pending.push(fixture);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (path.has(fixture)) {
|
|
66
|
+
if (fixture.parent === undefined) {
|
|
67
|
+
const cycle = [...path].reverse().map((step) => step.name);
|
|
68
|
+
throw new Error(`fixture "${fixture.name}" is part of a cycle: ${[fixture.name, ...cycle].join(' <- ')}`);
|
|
69
|
+
}
|
|
70
|
+
fixture = fixture.parent;
|
|
71
|
+
}
|
|
72
|
+
path.add(fixture);
|
|
73
|
+
pendingOf(dependenciesOf(fixture, fixtures), fixtures, path, pending);
|
|
74
|
+
pending.push(fixture);
|
|
75
|
+
path.clear();
|
|
76
|
+
}
|
|
77
|
+
return pending;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* One fixture's value. A fixture function gets a `use` that keeps the value
|
|
81
|
+
* and never settles, so the teardown after `await use(value)` never runs.
|
|
82
|
+
*/
|
|
83
|
+
function valueOf(fixture, context) {
|
|
84
|
+
if (typeof fixture.value !== 'function') {
|
|
85
|
+
return fixture.value;
|
|
86
|
+
}
|
|
87
|
+
const compute = fixture.value;
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
let used = false;
|
|
90
|
+
const use = (value) => {
|
|
91
|
+
used = true;
|
|
92
|
+
resolve(value);
|
|
93
|
+
return new Promise(() => undefined);
|
|
94
|
+
};
|
|
95
|
+
new Promise((settle) => settle(compute(context, use))).then(() => {
|
|
96
|
+
if (!used) {
|
|
97
|
+
reject(new Error(`fixture "${fixture.name}" settled without calling use()`));
|
|
98
|
+
}
|
|
99
|
+
}, (error) => {
|
|
100
|
+
if (!used) {
|
|
101
|
+
reject(namedError(fixture.name, error));
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Computes the fixtures that one test-scope callback uses before it runs:
|
|
108
|
+
* those its parameter destructures and every `auto` fixture, dependencies
|
|
109
|
+
* first. Each fixture runs once per page, and its value becomes a property of
|
|
110
|
+
* the context. A fixture that fails throws an error that names it.
|
|
111
|
+
*/
|
|
112
|
+
export async function liveFixtureValues(fixtures, use, context, computed) {
|
|
113
|
+
if (fixtures.size === 0) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const props = use === null ? new Set() : liveFixtureProps(use);
|
|
117
|
+
const used = [...fixtures.values()].filter((fixture) => !BUILT_IN.has(fixture.name) && (fixture.auto || props.has(fixture.name)));
|
|
118
|
+
for (const fixture of pendingOf(used, fixtures)) {
|
|
119
|
+
if (computed.has(fixture)) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
computed.add(fixture);
|
|
123
|
+
context[fixture.name] = await valueOf(fixture, context);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest's `format([placeholder, value])`, which `formatTitle` calls for each
|
|
3
|
+
* placeholder of an `each` or `for` name with the next row value. `%%` takes
|
|
4
|
+
* a value too, so it prints `%`, a space and that value.
|
|
5
|
+
*/
|
|
6
|
+
export declare function liveFormatPlaceholder(placeholder: string, value: unknown, inspect: (value: unknown) => string): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const CYCLE_MESSAGES = ['circular structure', 'cyclic structures', 'cyclic object'];
|
|
2
|
+
function formatString(value, inspect) {
|
|
3
|
+
if (typeof value === 'bigint') {
|
|
4
|
+
return `${value.toString()}n`;
|
|
5
|
+
}
|
|
6
|
+
if (typeof value === 'number' && value === 0 && 1 / value < 0) {
|
|
7
|
+
return '-0';
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === 'object' && value !== null) {
|
|
10
|
+
const { toString } = value;
|
|
11
|
+
if (typeof toString === 'function' && toString !== Object.prototype.toString) {
|
|
12
|
+
return String(toString.call(value));
|
|
13
|
+
}
|
|
14
|
+
return inspect(value);
|
|
15
|
+
}
|
|
16
|
+
return String(value);
|
|
17
|
+
}
|
|
18
|
+
function formatJson(value) {
|
|
19
|
+
try {
|
|
20
|
+
return String(JSON.stringify(value));
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : '';
|
|
24
|
+
if (CYCLE_MESSAGES.some((cycle) => message.includes(cycle))) {
|
|
25
|
+
return '[Circular]';
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** What `format` appends for an argument no placeholder took. */
|
|
31
|
+
function appended(value, inspect) {
|
|
32
|
+
if (value === null || typeof value !== 'object') {
|
|
33
|
+
return ` ${String(value)}`;
|
|
34
|
+
}
|
|
35
|
+
return ` ${inspect(value)}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Vitest's `format([placeholder, value])`, which `formatTitle` calls for each
|
|
39
|
+
* placeholder of an `each` or `for` name with the next row value. `%%` takes
|
|
40
|
+
* a value too, so it prints `%`, a space and that value.
|
|
41
|
+
*/
|
|
42
|
+
export function liveFormatPlaceholder(placeholder, value, inspect) {
|
|
43
|
+
switch (placeholder) {
|
|
44
|
+
case '%%':
|
|
45
|
+
return `%${appended(value, inspect)}`;
|
|
46
|
+
case '%s':
|
|
47
|
+
return formatString(value, inspect);
|
|
48
|
+
case '%d':
|
|
49
|
+
if (typeof value === 'bigint') {
|
|
50
|
+
return `${value.toString()}n`;
|
|
51
|
+
}
|
|
52
|
+
return typeof value === 'symbol' ? 'NaN' : Number(value).toString();
|
|
53
|
+
case '%i':
|
|
54
|
+
if (typeof value === 'bigint') {
|
|
55
|
+
return `${value.toString()}n`;
|
|
56
|
+
}
|
|
57
|
+
return Number.parseInt(String(value)).toString();
|
|
58
|
+
case '%f':
|
|
59
|
+
return Number.parseFloat(String(value)).toString();
|
|
60
|
+
case '%o':
|
|
61
|
+
case '%O':
|
|
62
|
+
return inspect(value);
|
|
63
|
+
case '%c':
|
|
64
|
+
return '';
|
|
65
|
+
case '%j':
|
|
66
|
+
return formatJson(value);
|
|
67
|
+
default:
|
|
68
|
+
return placeholder;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LiveCallback, LiveHookKind } from './live-suite.js';
|
|
2
|
+
/**
|
|
3
|
+
* `beforeAll`, `beforeEach`, `afterEach`, `afterAll`, `aroundEach` or
|
|
4
|
+
* `aroundAll` on the live page. The hook registers on the suite whose factory
|
|
5
|
+
* runs, or on the root during import. Its timeout is ignored, because the
|
|
6
|
+
* test's timeout covers the whole arrange phase.
|
|
7
|
+
*/
|
|
8
|
+
export declare function liveHook(kind: LiveHookKind): (hook: LiveCallback) => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { liveRegistry } from './live-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* `beforeAll`, `beforeEach`, `afterEach`, `afterAll`, `aroundEach` or
|
|
4
|
+
* `aroundAll` on the live page. The hook registers on the suite whose factory
|
|
5
|
+
* runs, or on the root during import. Its timeout is ignored, because the
|
|
6
|
+
* test's timeout covers the whole arrange phase.
|
|
7
|
+
*/
|
|
8
|
+
export function liveHook(kind) {
|
|
9
|
+
return (hook) => {
|
|
10
|
+
liveRegistry().current.hooks[kind].push(hook);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A port of `inspect` from Vitest 5's display utilities, which prints values
|
|
3
|
+
* in test names with pretty-format: `'x'`, `{ a: 1 }`, `[ 1, 2 ]`. Output
|
|
4
|
+
* longer than `truncate` is cut the way Vitest cuts it. DOM nodes and React
|
|
5
|
+
* elements, which Vitest prints with plugins, are printed as plain objects.
|
|
6
|
+
*/
|
|
7
|
+
export declare function liveInspect(value: unknown, truncate: number): string;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
const MAX_DEPTH = 10;
|
|
2
|
+
const UNQUOTED_KEY = /^[a-z_]\w*$/i;
|
|
3
|
+
const LIST_TAGS = new Set([
|
|
4
|
+
'[object Array]',
|
|
5
|
+
'[object ArrayBuffer]',
|
|
6
|
+
'[object DataView]',
|
|
7
|
+
'[object Float32Array]',
|
|
8
|
+
'[object Float64Array]',
|
|
9
|
+
'[object Int8Array]',
|
|
10
|
+
'[object Int16Array]',
|
|
11
|
+
'[object Int32Array]',
|
|
12
|
+
'[object Uint8Array]',
|
|
13
|
+
'[object Uint8ClampedArray]',
|
|
14
|
+
'[object Uint16Array]',
|
|
15
|
+
'[object Uint32Array]',
|
|
16
|
+
]);
|
|
17
|
+
const SHORTENED_TAGS = new Set([
|
|
18
|
+
'[object Array]',
|
|
19
|
+
'[object Object]',
|
|
20
|
+
'[object Set]',
|
|
21
|
+
'[object Map]',
|
|
22
|
+
]);
|
|
23
|
+
function tagOf(value) {
|
|
24
|
+
return Object.prototype.toString.call(value);
|
|
25
|
+
}
|
|
26
|
+
function constructorName(value) {
|
|
27
|
+
const { constructor } = value;
|
|
28
|
+
return (typeof constructor === 'function' && constructor.name) || 'Object';
|
|
29
|
+
}
|
|
30
|
+
function isHighSurrogate(character) {
|
|
31
|
+
return character !== undefined && character >= '\ud800' && character <= '\udbff';
|
|
32
|
+
}
|
|
33
|
+
/** pretty-format's `printBasicValue` with Vitest's options: single quotes, no escapes. */
|
|
34
|
+
function printBasic(value) {
|
|
35
|
+
if (value === true || value === false) {
|
|
36
|
+
return String(value);
|
|
37
|
+
}
|
|
38
|
+
if (value === undefined) {
|
|
39
|
+
return 'undefined';
|
|
40
|
+
}
|
|
41
|
+
if (value === null) {
|
|
42
|
+
return 'null';
|
|
43
|
+
}
|
|
44
|
+
if (typeof value === 'number') {
|
|
45
|
+
return Object.is(value, -0) ? '-0' : String(value);
|
|
46
|
+
}
|
|
47
|
+
if (typeof value === 'bigint') {
|
|
48
|
+
return `${value}n`;
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === 'string') {
|
|
51
|
+
return `'${value}'`;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === 'function') {
|
|
54
|
+
return `[Function ${value.name || 'anonymous'}]`;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value === 'symbol') {
|
|
57
|
+
return String(value);
|
|
58
|
+
}
|
|
59
|
+
return printBasicObject(value);
|
|
60
|
+
}
|
|
61
|
+
function printBasicObject(value) {
|
|
62
|
+
const tag = tagOf(value);
|
|
63
|
+
if (tag === '[object WeakMap]') {
|
|
64
|
+
return 'WeakMap {}';
|
|
65
|
+
}
|
|
66
|
+
if (tag === '[object WeakSet]') {
|
|
67
|
+
return 'WeakSet {}';
|
|
68
|
+
}
|
|
69
|
+
if (tag === '[object Date]') {
|
|
70
|
+
const date = value;
|
|
71
|
+
return Number.isNaN(+date) ? 'Date { NaN }' : date.toISOString();
|
|
72
|
+
}
|
|
73
|
+
if (tag === '[object Error]' || value instanceof Error) {
|
|
74
|
+
return `[${Error.prototype.toString.call(value)}]`;
|
|
75
|
+
}
|
|
76
|
+
if (tag === '[object RegExp]') {
|
|
77
|
+
return RegExp.prototype.toString.call(value);
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
function printList(list, limits, depth, refs) {
|
|
82
|
+
if (list.length === 0) {
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
let result = ' ';
|
|
86
|
+
for (let i = 0; i < list.length; i++) {
|
|
87
|
+
if (i === limits.maxWidth) {
|
|
88
|
+
result += `…(${list.length - i})`;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
if (i in list) {
|
|
92
|
+
result += print(list[i], limits, depth, refs);
|
|
93
|
+
}
|
|
94
|
+
if (i < list.length - 1) {
|
|
95
|
+
result += ', ';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return `${result} `;
|
|
99
|
+
}
|
|
100
|
+
/** Map entries as `key => value`, Set values alone. */
|
|
101
|
+
function printIterated(items, limits, depth, refs, entries) {
|
|
102
|
+
if (items.length === 0) {
|
|
103
|
+
return '';
|
|
104
|
+
}
|
|
105
|
+
let result = ' ';
|
|
106
|
+
for (let i = 0; i < items.length; i++) {
|
|
107
|
+
if (i === limits.maxWidth) {
|
|
108
|
+
result += `…(${items.length - i})`;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (entries) {
|
|
112
|
+
const [key, value] = items[i];
|
|
113
|
+
result += `${print(key, limits, depth, refs)} => ${print(value, limits, depth, refs)}`;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
result += print(items[i], limits, depth, refs);
|
|
117
|
+
}
|
|
118
|
+
if (i < items.length - 1) {
|
|
119
|
+
result += ', ';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return `${result} `;
|
|
123
|
+
}
|
|
124
|
+
function printProperties(value, limits, depth, refs) {
|
|
125
|
+
const keys = Object.keys(value);
|
|
126
|
+
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
|
127
|
+
if (Object.getOwnPropertyDescriptor(value, symbol)?.enumerable) {
|
|
128
|
+
keys.push(symbol);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (keys.length === 0) {
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
let result = ' ';
|
|
135
|
+
for (let i = 0; i < keys.length; i++) {
|
|
136
|
+
if (i === limits.maxWidth) {
|
|
137
|
+
result += `…(${keys.length - i})`;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
const key = keys[i];
|
|
141
|
+
const unquoted = typeof key === 'string' && key !== '__proto__' && UNQUOTED_KEY.test(key);
|
|
142
|
+
const name = unquoted ? key : print(key, limits, depth, refs);
|
|
143
|
+
result += `${name}: ${print(value[key], limits, depth, refs)}`;
|
|
144
|
+
if (i < keys.length - 1) {
|
|
145
|
+
result += ', ';
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return `${result} `;
|
|
149
|
+
}
|
|
150
|
+
/** pretty-format's `printComplexValue` with `min: true` and no basic prototype names. */
|
|
151
|
+
function printComplex(value, limits, depth, refs, calledToJSON) {
|
|
152
|
+
if (refs.includes(value)) {
|
|
153
|
+
return '[Circular]';
|
|
154
|
+
}
|
|
155
|
+
const nextRefs = [...refs, value];
|
|
156
|
+
const nextDepth = depth + 1;
|
|
157
|
+
const hitMaxDepth = nextDepth > limits.maxDepth;
|
|
158
|
+
const { toJSON } = value;
|
|
159
|
+
if (!hitMaxDepth && typeof toJSON === 'function' && !calledToJSON) {
|
|
160
|
+
return print(toJSON.call(value), limits, nextDepth, nextRefs, true);
|
|
161
|
+
}
|
|
162
|
+
const tag = tagOf(value);
|
|
163
|
+
const name = constructorName(value);
|
|
164
|
+
if (tag === '[object Arguments]') {
|
|
165
|
+
return hitMaxDepth
|
|
166
|
+
? '[Arguments]'
|
|
167
|
+
: `[${printList(value, limits, nextDepth, nextRefs)}]`;
|
|
168
|
+
}
|
|
169
|
+
if (LIST_TAGS.has(tag)) {
|
|
170
|
+
const prefix = name === 'Array' ? '' : `${name} `;
|
|
171
|
+
return hitMaxDepth
|
|
172
|
+
? `[${name}]`
|
|
173
|
+
: `${prefix}[${printList(value, limits, nextDepth, nextRefs)}]`;
|
|
174
|
+
}
|
|
175
|
+
if (tag === '[object Map]') {
|
|
176
|
+
const entries = [...value.entries()];
|
|
177
|
+
return hitMaxDepth
|
|
178
|
+
? '[Map]'
|
|
179
|
+
: `Map {${printIterated(entries, limits, nextDepth, nextRefs, true)}}`;
|
|
180
|
+
}
|
|
181
|
+
if (tag === '[object Set]') {
|
|
182
|
+
const values = [...value.values()];
|
|
183
|
+
return hitMaxDepth
|
|
184
|
+
? '[Set]'
|
|
185
|
+
: `Set {${printIterated(values, limits, nextDepth, nextRefs, false)}}`;
|
|
186
|
+
}
|
|
187
|
+
if (hitMaxDepth) {
|
|
188
|
+
return `[${name}]`;
|
|
189
|
+
}
|
|
190
|
+
return `${name === 'Object' ? '' : `${name} `}{${printProperties(value, limits, nextDepth, nextRefs)}}`;
|
|
191
|
+
}
|
|
192
|
+
function print(value, limits, depth = 0, refs = [], calledToJSON = false) {
|
|
193
|
+
return printBasic(value) ?? printComplex(value, limits, depth, refs, calledToJSON);
|
|
194
|
+
}
|
|
195
|
+
/** Vitest's `stringify`: it halves the depth until the output is shorter than `maxLength`. */
|
|
196
|
+
function stringify(value, maxDepth, maxLength) {
|
|
197
|
+
const result = print(value, { maxDepth, maxWidth: Number.POSITIVE_INFINITY });
|
|
198
|
+
return result.length >= maxLength && maxDepth > 1
|
|
199
|
+
? stringify(value, Math.floor(maxDepth / 2), maxLength)
|
|
200
|
+
: result;
|
|
201
|
+
}
|
|
202
|
+
/** The widest list at depth 1 whose output stays within `threshold`. */
|
|
203
|
+
function stringifyByMaxWidth(value, threshold) {
|
|
204
|
+
const evaluate = (maxWidth) => print(value, { maxDepth: 1, maxWidth });
|
|
205
|
+
let low = 0;
|
|
206
|
+
let high = threshold;
|
|
207
|
+
while (low + 1 < high) {
|
|
208
|
+
const middle = Math.floor((low + high) / 2);
|
|
209
|
+
if (evaluate(middle).length <= threshold) {
|
|
210
|
+
low = middle;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
high = middle;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return evaluate(low);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* A port of `inspect` from Vitest 5's display utilities, which prints values
|
|
220
|
+
* in test names with pretty-format: `'x'`, `{ a: 1 }`, `[ 1, 2 ]`. Output
|
|
221
|
+
* longer than `truncate` is cut the way Vitest cuts it. DOM nodes and React
|
|
222
|
+
* elements, which Vitest prints with plugins, are printed as plain objects.
|
|
223
|
+
*/
|
|
224
|
+
export function liveInspect(value, truncate) {
|
|
225
|
+
const formatted = stringify(value, MAX_DEPTH, truncate || 10_000);
|
|
226
|
+
if (truncate === 0 || formatted.length <= truncate) {
|
|
227
|
+
return formatted;
|
|
228
|
+
}
|
|
229
|
+
if (typeof value === 'string') {
|
|
230
|
+
let end = truncate - 1;
|
|
231
|
+
if (end > 0 && isHighSurrogate(formatted[end - 1])) {
|
|
232
|
+
end -= 1;
|
|
233
|
+
}
|
|
234
|
+
return `'${formatted.slice(1, end)}…'`;
|
|
235
|
+
}
|
|
236
|
+
if (SHORTENED_TAGS.has(tagOf(value))) {
|
|
237
|
+
return stringifyByMaxWidth(value, truncate);
|
|
238
|
+
}
|
|
239
|
+
return print(value, { maxDepth: 0, maxWidth: Number.POSITIVE_INFINITY });
|
|
240
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A port of `inspect` from Vitest 4's display utilities, which prints values
|
|
3
|
+
* in test names with loupe: `'x'`, `{ a: 1 }`, `[ 1, 2 ]`, and `+0` for zero.
|
|
4
|
+
* Custom inspectors, typed arrays and DOM nodes print as objects.
|
|
5
|
+
*/
|
|
6
|
+
export declare function liveLoupeInspect(value: unknown, truncateAt: number): string;
|