@vitest/browser 5.0.5 → 5.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/context.d.ts +83 -0
- package/dist/client/.vite/manifest.json +6 -6
- package/dist/client/__vitest_browser__/{defineProperty-DgkPJYVE.js → defineProperty-B-KFXNh3.js} +14 -1
- package/dist/client/__vitest_browser__/{orchestrator-C2U7TVD1.js → orchestrator-BGLAewVw.js} +2 -2
- package/dist/client/__vitest_browser__/{tester-BH7uPfyB.js → tester-DStcqUww.js} +58 -35
- package/dist/client/esm-client-injector.js +1 -5
- package/dist/client/orchestrator.html +2 -2
- package/dist/client/tester/tester.html +2 -2
- package/dist/client/tester/trace.d.ts +1 -0
- package/dist/context.js +102 -5
- package/dist/expect-element.js +1 -1
- package/dist/index.js +193 -72
- package/dist/locators-7Z9PPr-9.js +5 -0
- package/dist/locators.js +1 -1
- package/dist/types.d.ts +14 -2
- package/package.json +9 -9
- package/dist/locators-BHr21v4S.js +0 -5
package/context.d.ts
CHANGED
|
@@ -241,6 +241,33 @@ export interface UserEvent {
|
|
|
241
241
|
* await userEvent.wheel(container, { direction: 'up', times: 5 })
|
|
242
242
|
*/
|
|
243
243
|
wheel(element: Element | Locator, options: UserEventWheelOptions): Promise<void>
|
|
244
|
+
/**
|
|
245
|
+
* Performs one or more pointer actions.
|
|
246
|
+
*
|
|
247
|
+
* Pass a string to press or release a pointer button, an object to position the pointer and perform an action, or an array to perform actions in order.
|
|
248
|
+
* Key strings use the {@link https://testing-library.com/docs/user-event/pointer|`@testing-library/user-event` pointer syntax}.
|
|
249
|
+
*
|
|
250
|
+
* Unlike `@testing-library/user-event`, Vitest supports only `x` and `y` coordinates and does not support the `node` and `offset` selection fields.
|
|
251
|
+
*
|
|
252
|
+
* @param options - A pointer action or an ordered sequence of pointer actions.
|
|
253
|
+
* @returns A promise that resolves after all pointer actions finish.
|
|
254
|
+
*
|
|
255
|
+
* @since 5.1.0
|
|
256
|
+
* @experimental The Pointer API is experimental and not subject to semver.
|
|
257
|
+
* @see {@link https://vitest.dev/api/browser/interactivity#userevent-pointer}
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* // Click the left mouse button.
|
|
261
|
+
* await userEvent.pointer({ target: button, keys: '[MouseLeft]' })
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* // Drag from `source` to a point inside `target`.
|
|
265
|
+
* await userEvent.pointer([
|
|
266
|
+
* { target: source, keys: '[MouseLeft>]' },
|
|
267
|
+
* { target, coords: { x: 10, y: 10 }, keys: '[/MouseLeft]' },
|
|
268
|
+
* ])
|
|
269
|
+
*/
|
|
270
|
+
pointer(options: UserEventPointerInput): Promise<void>
|
|
244
271
|
/**
|
|
245
272
|
* Choose one or more values from a select element. Uses provider's API under the hood.
|
|
246
273
|
* If select doesn't have `multiple` attribute, only the first value will be selected.
|
|
@@ -439,6 +466,62 @@ export interface UserEventWheelDirectionOptions extends UserEventWheelBaseOption
|
|
|
439
466
|
*/
|
|
440
467
|
export type UserEventWheelOptions = UserEventWheelDeltaOptions | UserEventWheelDirectionOptions
|
|
441
468
|
|
|
469
|
+
/**
|
|
470
|
+
* Input accepted by {@link UserEvent.pointer}.
|
|
471
|
+
*
|
|
472
|
+
* - A string presses or releases a pointer button at the current position.
|
|
473
|
+
* - An object with `keys` positions the pointer and performs a button action.
|
|
474
|
+
* - An object without `keys` moves the pointer.
|
|
475
|
+
* - An array performs its actions in order.
|
|
476
|
+
*
|
|
477
|
+
* @since 5.1.0
|
|
478
|
+
* @experimental
|
|
479
|
+
*/
|
|
480
|
+
export type UserEventPointerInput = PointerActionInput | readonly PointerActionInput[]
|
|
481
|
+
/**
|
|
482
|
+
* Array form of pointer input after single-entry inputs and strings actions are expanded.
|
|
483
|
+
*
|
|
484
|
+
* @internal
|
|
485
|
+
*/
|
|
486
|
+
export type UserEventPointerInputNormalized = readonly (PointerActionInputObject & {
|
|
487
|
+
coords?: Required<PointerCoords>
|
|
488
|
+
})[]
|
|
489
|
+
|
|
490
|
+
type PointerActionInput = string | PointerActionInputObject
|
|
491
|
+
type PointerActionInputObject = PointerActionKeys | PointerMoveAction
|
|
492
|
+
|
|
493
|
+
interface PointerActionPosition {
|
|
494
|
+
/**
|
|
495
|
+
* Element to move the pointer to before performing the action.
|
|
496
|
+
*
|
|
497
|
+
* If `coords` is omitted, the browser provider chooses a position within the element.
|
|
498
|
+
* If both `target` and `coords` are omitted, the action uses the last known pointer position.
|
|
499
|
+
*/
|
|
500
|
+
target?: Element | Locator
|
|
501
|
+
/**
|
|
502
|
+
* Coordinates used to position the pointer.
|
|
503
|
+
*
|
|
504
|
+
* Without `target`, the values are viewport coordinates.
|
|
505
|
+
* With `target`, the values are pixel offsets from the target's top-left corner.
|
|
506
|
+
*
|
|
507
|
+
* This differs from `@testing-library/user-event`, where coordinates describe the final pointer position.
|
|
508
|
+
*
|
|
509
|
+
* Vitest also only supports `x` and `y`. Other coordinates, such as `clientX`, `offsetX`, `pageX`, and `screenX`, are not supported.
|
|
510
|
+
*/
|
|
511
|
+
coords?: PointerCoords
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
interface PointerActionKeys extends PointerActionPosition {
|
|
515
|
+
keys: string
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
interface PointerMoveAction extends PointerActionPosition {}
|
|
519
|
+
|
|
520
|
+
interface PointerCoords {
|
|
521
|
+
x?: number
|
|
522
|
+
y?: number
|
|
523
|
+
}
|
|
524
|
+
|
|
442
525
|
export interface LocatorOptions {
|
|
443
526
|
/**
|
|
444
527
|
* Whether to find an exact match: case-sensitive and whole-string. Defaults to `browser.locators.exact`, which is
|
|
@@ -5,29 +5,29 @@
|
|
|
5
5
|
"src": "../../../../node_modules/.pnpm/rrweb-snapshot@2.1.1_patch_hash=b66b30796877352a5f887f3f4115c4e7265ddc11772af2223da4bd92293716f6/node_modules/rrweb-snapshot/dist/rrweb-snapshot.js",
|
|
6
6
|
"isDynamicEntry": true
|
|
7
7
|
},
|
|
8
|
-
"_defineProperty-
|
|
9
|
-
"file": "__vitest_browser__/defineProperty-
|
|
8
|
+
"_defineProperty-B-KFXNh3.js": {
|
|
9
|
+
"file": "__vitest_browser__/defineProperty-B-KFXNh3.js",
|
|
10
10
|
"name": "defineProperty"
|
|
11
11
|
},
|
|
12
12
|
"orchestrator.html": {
|
|
13
|
-
"file": "__vitest_browser__/orchestrator-
|
|
13
|
+
"file": "__vitest_browser__/orchestrator-BGLAewVw.js",
|
|
14
14
|
"name": "orchestrator",
|
|
15
15
|
"src": "orchestrator.html",
|
|
16
16
|
"isEntry": true,
|
|
17
17
|
"imports": [
|
|
18
|
-
"_defineProperty-
|
|
18
|
+
"_defineProperty-B-KFXNh3.js"
|
|
19
19
|
],
|
|
20
20
|
"dynamicImports": [
|
|
21
21
|
"../../../../node_modules/.pnpm/rrweb-snapshot@2.1.1_patch_hash=b66b30796877352a5f887f3f4115c4e7265ddc11772af2223da4bd92293716f6/node_modules/rrweb-snapshot/dist/rrweb-snapshot.js"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
24
|
"tester/tester.html": {
|
|
25
|
-
"file": "__vitest_browser__/tester-
|
|
25
|
+
"file": "__vitest_browser__/tester-DStcqUww.js",
|
|
26
26
|
"name": "tester",
|
|
27
27
|
"src": "tester/tester.html",
|
|
28
28
|
"isEntry": true,
|
|
29
29
|
"imports": [
|
|
30
|
-
"_defineProperty-
|
|
30
|
+
"_defineProperty-B-KFXNh3.js"
|
|
31
31
|
]
|
|
32
32
|
}
|
|
33
33
|
}
|
package/dist/client/__vitest_browser__/{defineProperty-DgkPJYVE.js → defineProperty-B-KFXNh3.js}
RENAMED
|
@@ -261,6 +261,19 @@ var moduleRunner = {
|
|
|
261
261
|
return importId(id);
|
|
262
262
|
}
|
|
263
263
|
};
|
|
264
|
+
function supportsLateImportMaps() {
|
|
265
|
+
const specifier = "__vitest_import_map_probe__";
|
|
266
|
+
const script = document.createElement("script");
|
|
267
|
+
script.type = "importmap";
|
|
268
|
+
script.textContent = JSON.stringify({ imports: { [specifier]: `/${specifier}` } });
|
|
269
|
+
document.head.append(script);
|
|
270
|
+
try {
|
|
271
|
+
import.meta.resolve(specifier);
|
|
272
|
+
return true;
|
|
273
|
+
} catch {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
264
277
|
var now = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
|
|
265
278
|
function getConfig() {
|
|
266
279
|
return (/* @__PURE__ */ getBrowserState()).config;
|
|
@@ -323,4 +336,4 @@ function _defineProperty(e, r, t) {
|
|
|
323
336
|
}
|
|
324
337
|
|
|
325
338
|
//#endregion
|
|
326
|
-
export { getWorkerState as a,
|
|
339
|
+
export { getWorkerState as a, supportsLateImportMaps as c, getTestName as d, basename as f, getOrchestratorState as i, __vitePreload as l, resolve as m, getBrowserState as n, moduleRunner as o, relative as p, getConfig as r, now as s, _defineProperty as t, generateFileHash as u };
|
package/dist/client/__vitest_browser__/{orchestrator-C2U7TVD1.js → orchestrator-BGLAewVw.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as
|
|
1
|
+
import { c as supportsLateImportMaps, l as __vitePreload, n as getBrowserState, p as relative, r as getConfig, t as _defineProperty, u as generateFileHash } from "./defineProperty-B-KFXNh3.js";
|
|
2
2
|
import { channel, client, globalChannel } from "@vitest/browser/client";
|
|
3
3
|
import { Traces } from "vitest/internal/traces";
|
|
4
4
|
|
|
@@ -38,7 +38,7 @@ var IframeOrchestrator = class {
|
|
|
38
38
|
});
|
|
39
39
|
channel.addEventListener("message", (e) => this.onIframeEvent(e));
|
|
40
40
|
globalChannel.addEventListener("message", (e) => this.onGlobalChannelEvent(e));
|
|
41
|
-
client.waitForConnection().then(() => client.rpc.onOrchestratorReady()).catch((error) => {
|
|
41
|
+
client.waitForConnection().then(() => client.rpc.onOrchestratorReady({ lateImportMaps: supportsLateImportMaps() })).catch((error) => {
|
|
42
42
|
debug("failed to notify orchestrator readiness", error);
|
|
43
43
|
});
|
|
44
44
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as getWorkerState,
|
|
1
|
+
import { a as getWorkerState, d as getTestName, f as basename, i as getOrchestratorState, l as __vitePreload, m as resolve, n as getBrowserState, o as moduleRunner, r as getConfig, s as now$1, t as _defineProperty } from "./defineProperty-B-KFXNh3.js";
|
|
2
2
|
import { channel, client, globalChannel, onCancel, registerPageMarkHandler } from "@vitest/browser/client";
|
|
3
3
|
import { Traces } from "vitest/internal/traces";
|
|
4
4
|
import { page, server, userEvent } from "vitest/browser";
|
|
@@ -642,30 +642,38 @@ function parseStacktrace(stack, options = {}) {
|
|
|
642
642
|
let stacks = !CHROME_IE_STACK_REGEXP.test(stack) ? parseFFOrSafariStackTrace(stack) : parseV8Stacktrace(stack);
|
|
643
643
|
const helperIndex = stacks.findLastIndex((s) => s.method.includes("__VITEST_HELPER__"));
|
|
644
644
|
if (helperIndex >= 0) stacks = stacks.slice(helperIndex + 1);
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
645
|
+
if (options.firstOnly) {
|
|
646
|
+
for (const stack of stacks) {
|
|
647
|
+
const mapped = mapStackFrame(stack, options, ignoreStackEntries);
|
|
648
|
+
if (mapped) return [mapped];
|
|
649
|
+
}
|
|
650
|
+
return [];
|
|
651
|
+
}
|
|
652
|
+
return stacks.map((stack) => mapStackFrame(stack, options, ignoreStackEntries)).filter((s) => s != null);
|
|
653
|
+
}
|
|
654
|
+
function mapStackFrame(stack, options, ignoreStackEntries) {
|
|
655
|
+
var _options$getSourceMap;
|
|
656
|
+
if (options.getUrlId) stack.file = options.getUrlId(stack.file);
|
|
657
|
+
const map = (_options$getSourceMap = options.getSourceMap) === null || _options$getSourceMap === void 0 ? void 0 : _options$getSourceMap.call(options, stack.file);
|
|
658
|
+
if (!map || typeof map !== "object" || !map.version) return shouldFilter(ignoreStackEntries, stack.file) ? null : stack;
|
|
659
|
+
const traceMap = new DecodedMap$1(map, stack.file);
|
|
660
|
+
if (stack.line <= 0 || stack.column <= 0) return stack;
|
|
661
|
+
const position = getOriginalPosition$1(traceMap, {
|
|
662
|
+
line: stack.line,
|
|
663
|
+
column: stack.column - 1
|
|
664
|
+
});
|
|
665
|
+
if (!position) return stack;
|
|
666
|
+
const { line, column, source, name } = position;
|
|
667
|
+
let file = source || stack.file;
|
|
668
|
+
if (/\/\w:\//.test(file)) file = file.slice(1);
|
|
669
|
+
if (shouldFilter(ignoreStackEntries, file)) return null;
|
|
670
|
+
if (line != null && column != null) return {
|
|
671
|
+
line,
|
|
672
|
+
column: column + 1,
|
|
673
|
+
file,
|
|
674
|
+
method: name || stack.method
|
|
675
|
+
};
|
|
676
|
+
return stack;
|
|
669
677
|
}
|
|
670
678
|
function shouldFilter(ignoreStackEntries, file) {
|
|
671
679
|
return ignoreStackEntries.some((p) => file.match(p));
|
|
@@ -819,6 +827,10 @@ function takeSnapshot(serializedLocator) {
|
|
|
819
827
|
},
|
|
820
828
|
pseudoClassIds: {}
|
|
821
829
|
};
|
|
830
|
+
if (traceView.ariaSnapshot) {
|
|
831
|
+
const { generateAriaTree, renderAriaTree } = (/* @__PURE__ */ getBrowserState()).aria;
|
|
832
|
+
result.ariaSnapshot = renderAriaTree(generateAriaTree(document.body));
|
|
833
|
+
}
|
|
822
834
|
for (const className of PSEUDO_CLASS_NAMES) {
|
|
823
835
|
const elements = document.querySelectorAll(className);
|
|
824
836
|
const ids = Array.from(elements, (el) => mirror.getId(el)).filter((id) => id !== -1);
|
|
@@ -1797,7 +1809,7 @@ var ModuleMocker = class {
|
|
|
1797
1809
|
else if (mockType === "autospy") module = this.registry.register("autospy", rawId, resolvedId, mockUrl);
|
|
1798
1810
|
else if (mockType === "redirect") module = this.registry.register("redirect", rawId, resolvedId, mockUrl, mockRedirect);
|
|
1799
1811
|
else module = this.registry.register("automock", rawId, resolvedId, mockUrl);
|
|
1800
|
-
await this.interceptor.register(module);
|
|
1812
|
+
await this.interceptor.register(module, importer);
|
|
1801
1813
|
}).finally(() => {
|
|
1802
1814
|
this.queue.delete(promise);
|
|
1803
1815
|
});
|
|
@@ -1816,11 +1828,7 @@ var ModuleMocker = class {
|
|
|
1816
1828
|
this.queue.add(promise);
|
|
1817
1829
|
}
|
|
1818
1830
|
wrapDynamicImport(moduleFactory) {
|
|
1819
|
-
if (typeof moduleFactory === "function") return
|
|
1820
|
-
this.prepare().finally(() => {
|
|
1821
|
-
moduleFactory().then(resolve, reject);
|
|
1822
|
-
});
|
|
1823
|
-
});
|
|
1831
|
+
if (typeof moduleFactory === "function") return this.prepare().then(() => moduleFactory());
|
|
1824
1832
|
return moduleFactory;
|
|
1825
1833
|
}
|
|
1826
1834
|
getMockedModuleById(id) {
|
|
@@ -1859,9 +1867,13 @@ var VitestBrowserClientMocker = class extends ModuleMocker {
|
|
|
1859
1867
|
//#region src/client/tester/mocker-interceptor.ts
|
|
1860
1868
|
function createModuleMockerInterceptor() {
|
|
1861
1869
|
return {
|
|
1862
|
-
async register(module) {
|
|
1863
|
-
const
|
|
1864
|
-
await rpc().registerMock(
|
|
1870
|
+
async register(module, importer) {
|
|
1871
|
+
const { sessionId } = /* @__PURE__ */ getBrowserState();
|
|
1872
|
+
const importMap = await rpc().registerMock(sessionId, module.toJSON(), {
|
|
1873
|
+
importer,
|
|
1874
|
+
testFile: (/* @__PURE__ */ getWorkerState()).filepath
|
|
1875
|
+
});
|
|
1876
|
+
if (importMap) appendImportMap(importMap);
|
|
1865
1877
|
},
|
|
1866
1878
|
async delete(id) {
|
|
1867
1879
|
const state = /* @__PURE__ */ getBrowserState();
|
|
@@ -1873,6 +1885,16 @@ function createModuleMockerInterceptor() {
|
|
|
1873
1885
|
}
|
|
1874
1886
|
};
|
|
1875
1887
|
}
|
|
1888
|
+
function appendImportMap(importMap) {
|
|
1889
|
+
const script = document.createElement("script");
|
|
1890
|
+
script.type = "importmap";
|
|
1891
|
+
script.textContent = JSON.stringify(importMap);
|
|
1892
|
+
document.head.append(script);
|
|
1893
|
+
for (const [specifier, url] of Object.entries(importMap.imports)) {
|
|
1894
|
+
const expected = new URL(url, location.href).href;
|
|
1895
|
+
if (import.meta.resolve(specifier) !== expected) throw new Error(`Cannot mock "${specifier}" with an import map because the browser kept its original URL. The module was already imported before vi.mock was registered, for example by a setup file or by an earlier test file when "isolate" is false.`);
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1876
1898
|
function rpc() {
|
|
1877
1899
|
return (/* @__PURE__ */ getWorkerState()).rpc;
|
|
1878
1900
|
}
|
|
@@ -1893,7 +1915,8 @@ var ACTION_TRACE_COMMANDS = new Set([
|
|
|
1893
1915
|
"__vitest_upload",
|
|
1894
1916
|
"__vitest_tab",
|
|
1895
1917
|
"__vitest_keyboard",
|
|
1896
|
-
"__vitest_takeScreenshot"
|
|
1918
|
+
"__vitest_takeScreenshot",
|
|
1919
|
+
"__vitest_pointer"
|
|
1897
1920
|
]);
|
|
1898
1921
|
var CommandsManager = class {
|
|
1899
1922
|
constructor() {
|
|
@@ -13,11 +13,7 @@
|
|
|
13
13
|
const viteModule = evaluatedModules.ensureModule(moduleId, moduleId)
|
|
14
14
|
|
|
15
15
|
viteModule.evaluated = false
|
|
16
|
-
viteModule.promise =
|
|
17
|
-
__vitest_mocker__.prepare().finally(() => {
|
|
18
|
-
moduleCallback().then(resolve, reject)
|
|
19
|
-
});
|
|
20
|
-
});
|
|
16
|
+
viteModule.promise = __vitest_mocker__.prepare().then(() => moduleCallback())
|
|
21
17
|
return viteModule.promise.finally(() => {
|
|
22
18
|
viteModule.evaluated = true
|
|
23
19
|
viteModule.promise = undefined
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
}
|
|
28
28
|
</style>
|
|
29
29
|
{__VITEST_INJECTOR__} {__VITEST_ERROR_CATCHER__} {__VITEST_SCRIPTS__}
|
|
30
|
-
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-
|
|
31
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-
|
|
30
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-BGLAewVw.js"></script>
|
|
31
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-B-KFXNh3.js">
|
|
32
32
|
</head>
|
|
33
33
|
<body>
|
|
34
34
|
<div id="vitest-tester"></div>
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" href="{__VITEST_FAVICON__}" type="image/svg+xml" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Vitest Browser Tester</title>
|
|
8
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-
|
|
8
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-DStcqUww.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-B-KFXNh3.js">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
</body>
|
|
@@ -44,6 +44,7 @@ interface TraceSnapshot {
|
|
|
44
44
|
selectorResolution?: BrowserTraceSelectorResolution;
|
|
45
45
|
selectorError?: string;
|
|
46
46
|
pseudoClassIds: Record<PseudoClassName, number[]>;
|
|
47
|
+
ariaSnapshot?: string;
|
|
47
48
|
}
|
|
48
49
|
declare const PSEUDO_CLASS_NAMES: readonly [":hover", ":active", ":focus", ":focus-visible", ":focus-within", ":popover-open"];
|
|
49
50
|
type PseudoClassName = (typeof PSEUDO_CLASS_NAMES)[number];
|
package/dist/context.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { vi } from 'vitest';
|
|
2
|
-
import { __INTERNAL, stringify } from 'vitest/internal/browser';
|
|
2
|
+
import { getSafeTimers, __INTERNAL, stringify } from 'vitest/internal/browser';
|
|
3
3
|
|
|
4
4
|
const now = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
|
|
5
5
|
function ensureAwaited(promise) {
|
|
@@ -60,6 +60,24 @@ function resolveActionTimeout(options) {
|
|
|
60
60
|
}
|
|
61
61
|
return getBrowserState().runner._deadline?.derive();
|
|
62
62
|
}
|
|
63
|
+
const FAKE_TIMERS_TICK = 50;
|
|
64
|
+
/**
|
|
65
|
+
* Wraps provider commands that wait for an element. The provider waits in real time,
|
|
66
|
+
* so fake timers must keep moving for the page to render it. Commands that act right
|
|
67
|
+
* away, such as `keyboard` and `tab`, are not wrapped.
|
|
68
|
+
*/
|
|
69
|
+
function advanceFakeTimersWhilePending(promise) {
|
|
70
|
+
if (!vi.isFakeTimers()) {
|
|
71
|
+
return promise;
|
|
72
|
+
}
|
|
73
|
+
const { setInterval, clearInterval } = getSafeTimers();
|
|
74
|
+
const interval = setInterval(() => {
|
|
75
|
+
if (vi.isFakeTimers()) {
|
|
76
|
+
vi.advanceTimersByTime(FAKE_TIMERS_TICK);
|
|
77
|
+
}
|
|
78
|
+
}, FAKE_TIMERS_TICK);
|
|
79
|
+
return promise.finally(() => clearInterval(interval));
|
|
80
|
+
}
|
|
63
81
|
/**
|
|
64
82
|
* A browser command that the test awaits. The action derives its own timeout
|
|
65
83
|
* from the running task, so it fails with a descriptive error before the task does.
|
|
@@ -98,7 +116,7 @@ class Action {
|
|
|
98
116
|
timeout
|
|
99
117
|
};
|
|
100
118
|
const args = typeof this.#args === "function" ? await this.#args(options) : [...this.#args, options];
|
|
101
|
-
const promise = getBrowserState().commands.triggerCommand(this.#command, args, this.#errorSource);
|
|
119
|
+
const promise = advanceFakeTimersWhilePending(getBrowserState().commands.triggerCommand(this.#command, args, this.#errorSource));
|
|
102
120
|
const deadline = getBrowserState().runner._deadline;
|
|
103
121
|
return deadline && timeout != null ? deadline.track(this.#command.slice("__vitest_".length), promise, timeout, this.#errorSource) : promise;
|
|
104
122
|
}
|
|
@@ -202,6 +220,10 @@ function takeSnapshot(serializedLocator) {
|
|
|
202
220
|
},
|
|
203
221
|
pseudoClassIds: {}
|
|
204
222
|
};
|
|
223
|
+
if (traceView.ariaSnapshot) {
|
|
224
|
+
const { generateAriaTree, renderAriaTree } = getBrowserState().aria;
|
|
225
|
+
result.ariaSnapshot = renderAriaTree(generateAriaTree(document.body));
|
|
226
|
+
}
|
|
205
227
|
for (const className of PSEUDO_CLASS_NAMES) {
|
|
206
228
|
const elements = document.querySelectorAll(className);
|
|
207
229
|
const ids = Array.from(elements, (el) => mirror.getId(el)).filter((id) => id !== -1);
|
|
@@ -297,6 +319,24 @@ function getParent(el) {
|
|
|
297
319
|
}
|
|
298
320
|
return parent;
|
|
299
321
|
}
|
|
322
|
+
function getIframe() {
|
|
323
|
+
const iframe = window.frameElement;
|
|
324
|
+
if (!iframe) {
|
|
325
|
+
throw new Error(`Cannot find iframe element. This is a bug in Vitest. Please, open a new issue with reproduction.`);
|
|
326
|
+
}
|
|
327
|
+
return iframe;
|
|
328
|
+
}
|
|
329
|
+
function getIframeScale() {
|
|
330
|
+
const iframe = getIframe();
|
|
331
|
+
// DOMMatrix parses the computed 2D transform matrix [a, b, c, d, e, f]
|
|
332
|
+
// `a` and `d` are the x and y scale factors - since we only apply uniform scaling, `a === d`
|
|
333
|
+
const scale = new DOMMatrix(getComputedStyle(iframe).transform).a;
|
|
334
|
+
return scale;
|
|
335
|
+
}
|
|
336
|
+
function getIframeOffset() {
|
|
337
|
+
const iframe = getIframe();
|
|
338
|
+
return iframe.getBoundingClientRect();
|
|
339
|
+
}
|
|
300
340
|
const provider$1 = getBrowserState().provider;
|
|
301
341
|
const kElementLocator = Symbol.for("$$vitest:locator-resolved");
|
|
302
342
|
async function serializeElement(elementOrLocator, options) {
|
|
@@ -359,7 +399,6 @@ function resolveUserEventWheelOptions(options) {
|
|
|
359
399
|
};
|
|
360
400
|
}
|
|
361
401
|
|
|
362
|
-
// this file should not import anything directly, only types and utils
|
|
363
402
|
// @ts-expect-error not typed global
|
|
364
403
|
const provider = __vitest_browser_runner__.provider;
|
|
365
404
|
const sessionId = getBrowserState().sessionId;
|
|
@@ -372,6 +411,10 @@ function createUserEvent(__tl_user_event_base__, options) {
|
|
|
372
411
|
return createPreviewUserEvent(__tl_user_event_base__, options ?? {});
|
|
373
412
|
}
|
|
374
413
|
const keyboard = { unreleased: [] };
|
|
414
|
+
const pointerState = {
|
|
415
|
+
coords: undefined,
|
|
416
|
+
target: undefined
|
|
417
|
+
};
|
|
375
418
|
// https://playwright.dev/docs/api/class-keyboard
|
|
376
419
|
// https://webdriver.io/docs/api/browser/keys/
|
|
377
420
|
const modifier = provider === "playwright" ? "ControlOrMeta" : provider === "webdriverio" ? "Ctrl" : "Control";
|
|
@@ -401,6 +444,33 @@ function createUserEvent(__tl_user_event_base__, options) {
|
|
|
401
444
|
wheel(elementOrOptions, options) {
|
|
402
445
|
return convertToLocator(elementOrOptions).wheel(options);
|
|
403
446
|
},
|
|
447
|
+
pointer(input) {
|
|
448
|
+
return ensureAwaited(async () => {
|
|
449
|
+
const scale = getIframeScale();
|
|
450
|
+
const offset = getIframeOffset();
|
|
451
|
+
const inputArray = Array.isArray(input) ? input : [input];
|
|
452
|
+
const serializedInputArray = await Promise.all(inputArray.map(async (input) => {
|
|
453
|
+
if (typeof input === "string") {
|
|
454
|
+
return { keys: input };
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
...input,
|
|
458
|
+
target: input.target && await serializeElement(input.target),
|
|
459
|
+
coords: input.coords && {
|
|
460
|
+
x: input.coords.x ? input.coords.x * scale + (input.target ? 0 : offset.x) : 0,
|
|
461
|
+
y: input.coords.y ? input.coords.y * scale + (input.target ? 0 : offset.y) : 0
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
}));
|
|
465
|
+
const { coords, target, unreleased } = await advanceFakeTimersWhilePending(triggerCommand("__vitest_pointer", [serializedInputArray, {
|
|
466
|
+
...pointerState,
|
|
467
|
+
unreleased: keyboard.unreleased
|
|
468
|
+
}]));
|
|
469
|
+
pointerState.target = target;
|
|
470
|
+
pointerState.coords = coords;
|
|
471
|
+
keyboard.unreleased = unreleased;
|
|
472
|
+
});
|
|
473
|
+
},
|
|
404
474
|
selectOptions(element, value, options) {
|
|
405
475
|
return convertToLocator(element).selectOptions(value, options);
|
|
406
476
|
},
|
|
@@ -429,14 +499,14 @@ function createUserEvent(__tl_user_event_base__, options) {
|
|
|
429
499
|
type(element, text, options) {
|
|
430
500
|
return ensureAwaited(async (error) => {
|
|
431
501
|
const serializedElement = await serializeElement(element, options);
|
|
432
|
-
const { unreleased } = await triggerCommand("__vitest_type", [
|
|
502
|
+
const { unreleased } = await advanceFakeTimersWhilePending(triggerCommand("__vitest_type", [
|
|
433
503
|
serializedElement,
|
|
434
504
|
text,
|
|
435
505
|
{
|
|
436
506
|
...options,
|
|
437
507
|
unreleased: keyboard.unreleased
|
|
438
508
|
}
|
|
439
|
-
], error);
|
|
509
|
+
], error));
|
|
440
510
|
keyboard.unreleased = unreleased;
|
|
441
511
|
});
|
|
442
512
|
},
|
|
@@ -563,6 +633,33 @@ function createPreviewUserEvent(userEventBase, options) {
|
|
|
563
633
|
for (let count = 0; count < times; count += 1) {
|
|
564
634
|
resolvedElement.dispatchEvent(wheelEvent);
|
|
565
635
|
}
|
|
636
|
+
},
|
|
637
|
+
async pointer(input) {
|
|
638
|
+
const inputArray = Array.isArray(input) ? input : [input];
|
|
639
|
+
const normalizedInput = inputArray.map((input) => {
|
|
640
|
+
if (typeof input === "string") {
|
|
641
|
+
return { keys: input };
|
|
642
|
+
}
|
|
643
|
+
const target = input.target;
|
|
644
|
+
return {
|
|
645
|
+
...input,
|
|
646
|
+
get target() {
|
|
647
|
+
const value = isLocator(target) ? target.element() : target;
|
|
648
|
+
Reflect.defineProperty(this, "target", {
|
|
649
|
+
enumerable: true,
|
|
650
|
+
configurable: true,
|
|
651
|
+
writable: true,
|
|
652
|
+
value
|
|
653
|
+
});
|
|
654
|
+
return value;
|
|
655
|
+
},
|
|
656
|
+
coords: input.coords && {
|
|
657
|
+
x: input.coords.x ?? 0,
|
|
658
|
+
y: input.coords.y ?? 0
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
});
|
|
662
|
+
await userEvent.pointer(normalizedInput);
|
|
566
663
|
}
|
|
567
664
|
};
|
|
568
665
|
for (const [name, fn] of Object.entries(vitestUserEvent)) {
|
package/dist/expect-element.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Snapshots as e,recordArtifact as t,expect as n,chai as r}from"vitest";import{getType as i}from"vitest/internal/browser";import{i as a,g as o,n as s,a as c,k as l,b as u,c as d,d as f,e as ee,f as te,h as ne,j as re,l as ie,m as ae,o as oe,p as se,q as ce,r as p,_ as m,s as h,t as g,u as _,L as v,v as le,w as ue,x as de,y as fe,z as pe,A as me,B as he,C as ge,D as _e,E as ve}from"./locators-
|
|
1
|
+
import{Snapshots as e,recordArtifact as t,expect as n,chai as r}from"vitest";import{getType as i}from"vitest/internal/browser";import{i as a,g as o,n as s,a as c,k as l,b as u,c as d,d as f,e as ee,f as te,h as ne,j as re,l as ie,m as ae,o as oe,p as se,q as ce,r as p,_ as m,s as h,t as g,u as _,L as v,v as le,w as ue,x as de,y as fe,z as pe,A as me,B as he,C as ge,D as _e,E as ve}from"./locators-7Z9PPr-9.js";import{server as ye}from"vitest/browser";var be=Object.defineProperty,xe=(e,t)=>{let n={};for(var r in e)be(n,r,{get:e[r],enumerable:!0});return be(n,Symbol.toStringTag,{value:`Module`}),n};function Se(e,t,n={}){let r=Ce(e,t,n);if(r.errors.length)throw Error(r.errors[0].message);return r.fragment}function Ce(e,t,n={}){let r=new e.LineCounter,i={keepSourceTokens:!0,lineCounter:r,...n},a=e.parseDocument(t,i),o=[],s=e=>[r.linePos(e[0]),r.linePos(e[1])],c=e=>{o.push({message:e.message,range:[r.linePos(e.pos[0]),r.linePos(e.pos[1])]})},l=(t,n)=>{for(let r of n.items){if(r instanceof e.Scalar&&typeof r.value==`string`){let e=Ee.parse(r,i,o);e&&(t.children=t.children||[],t.children.push(e));continue}if(r instanceof e.YAMLMap){u(t,r);continue}o.push({message:`Sequence items should be strings or maps`,range:s(r.range||n.range)})}},u=(t,n)=>{for(let r of n.items){if(t.children=t.children||[],!(r.key instanceof e.Scalar&&typeof r.key.value==`string`)){o.push({message:`Only string keys are supported`,range:s(r.key.range||n.range)});continue}let a=r.key,c=r.value;if(a.value===`text`){if(!(c instanceof e.Scalar&&typeof c.value==`string`)){o.push({message:`Text value should be a string`,range:s(r.value.range||n.range)});continue}t.children.push({kind:`text`,text:y(c.value)});continue}if(a.value===`/children`){if(!(c instanceof e.Scalar&&typeof c.value==`string`)||c.value!==`contain`&&c.value!==`equal`&&c.value!==`deep-equal`){o.push({message:`Strict value should be "contain", "equal" or "deep-equal"`,range:s(r.value.range||n.range)});continue}t.containerMode=c.value;continue}if(a.value.startsWith(`/`)){if(!(c instanceof e.Scalar&&typeof c.value==`string`)){o.push({message:`Property value should be a string`,range:s(r.value.range||n.range)});continue}t.props=t.props??{},t.props[a.value.slice(1)]=y(c.value);continue}let u=Ee.parse(a,i,o);if(u){if(c instanceof e.Scalar){let e=typeof c.value;if(e!==`string`&&e!==`number`&&e!==`boolean`){o.push({message:`Node value should be a string or a sequence`,range:s(r.value.range||n.range)});continue}t.children.push({...u,children:[{kind:`text`,text:y(String(c.value))}]});continue}if(c instanceof e.YAMLSeq){t.children.push(u),l(u,c);continue}o.push({message:`Map values should be strings or sequences`,range:s(r.value.range||n.range)})}}},d={kind:`role`,role:`fragment`};return a.errors.forEach(c),o.length?{errors:o,fragment:d}:a.contents?(a.contents instanceof e.YAMLSeq||o.push({message:`Aria snapshot must be a YAML sequence, elements starting with " -"`,range:s(a.contents.range)}),o.length?{errors:o,fragment:d}:(l(d,a.contents),o.length?{errors:o,fragment:we}:d.children?.length===1&&(!d.containerMode||d.containerMode===`contain`)?{fragment:d.children[0],errors:[]}:{fragment:d,errors:[]})):{fragment:d,errors:[]}}const we={kind:`role`,role:`fragment`};function Te(e){return e.replace(/[\u200b\u00ad]/g,``).replace(/[\r\n\s\t]+/g,` `).trim()}function y(e){return{raw:e,normalized:Te(e)}}var Ee=class e{static parse(t,n,r){try{return new e(t.value)._parse()}catch(e){if(e instanceof b){let i=n.prettyErrors===!1?e.message:`${e.message}:\n\n${t.value}\n${` `.repeat(e.pos)}^\n`;return r.push({message:i,range:[n.lineCounter.linePos(t.range[0]),n.lineCounter.linePos(t.range[0]+e.pos)]}),null}throw e}}constructor(e){m(this,`_input`,void 0),m(this,`_pos`,void 0),m(this,`_length`,void 0),this._input=e,this._pos=0,this._length=e.length}_peek(){return this._input[this._pos]||``}_next(){return this._pos<this._length?this._input[this._pos++]:null}_eof(){return this._pos>=this._length}_isWhitespace(){return!this._eof()&&/\s/.test(this._peek())}_skipWhitespace(){for(;this._isWhitespace();)this._pos++}_readIdentifier(e){this._eof()&&this._throwError(`Unexpected end of input when expecting ${e}`);let t=this._pos;for(;!this._eof()&&/[a-zA-Z]/.test(this._peek());)this._pos++;return this._input.slice(t,this._pos)}_readString(){let e=``,t=!1;for(;!this._eof();){let n=this._next();if(t)e+=n,t=!1;else if(n===`\\`)t=!0;else if(n===`"`)return e;else e+=n}this._throwError(`Unterminated string`)}_throwError(e,t=0){throw new b(e,t||this._pos)}_readRegex(){let e=``,t=!1,n=!1;for(;!this._eof();){let r=this._next();if(t)e+=r,t=!1;else if(r===`\\`)t=!0,e+=r;else if(r===`/`&&!n)return{pattern:e};else r===`[`?(n=!0,e+=r):r===`]`&&n?(e+=r,n=!1):e+=r}this._throwError(`Unterminated regex`)}_readStringOrRegex(){let e=this._peek();return e===`"`?(this._next(),Te(this._readString())):e===`/`?(this._next(),this._readRegex()):null}_readAttributes(e){let t=this._pos;for(;this._skipWhitespace(),this._peek()===`[`;){this._next(),this._skipWhitespace(),t=this._pos;let n=this._readIdentifier(`attribute`);this._skipWhitespace();let r=``;if(this._peek()===`=`)for(this._next(),this._skipWhitespace(),t=this._pos;this._peek()!==`]`&&!this._isWhitespace()&&!this._eof();)r+=this._next();this._skipWhitespace(),this._peek()!==`]`&&this._throwError(`Expected ]`),this._next(),this._applyAttribute(e,n,r||`true`,t)}}_parse(){this._skipWhitespace();let e=this._readIdentifier(`role`);e===`fragment`&&this._throwError(`Invalid role "fragment"`),this._skipWhitespace();let t={kind:`role`,role:e,name:this._readStringOrRegex()||void 0};return this._readAttributes(t),this._skipWhitespace(),this._eof()||this._throwError(`Unexpected input`),t}_applyAttribute(e,t,n,r){if(t===`checked`){this._assert(n===`true`||n===`false`||n===`mixed`,`Value of "checked" attribute must be a boolean or "mixed"`,r),e.checked=n===`true`||n!==`false`&&`mixed`;return}if(t===`disabled`){this._assert(n===`true`||n===`false`,`Value of "disabled" attribute must be a boolean`,r),e.disabled=n===`true`;return}if(t===`expanded`){this._assert(n===`true`||n===`false`,`Value of "expanded" attribute must be a boolean`,r),e.expanded=n===`true`;return}if(t===`active`){this._assert(n===`true`||n===`false`,`Value of "active" attribute must be a boolean`,r),e.active=n===`true`;return}if(t===`level`){this._assert(!Number.isNaN(Number(n)),`Value of "level" attribute must be a number`,r),e.level=Number(n);return}if(t===`pressed`){this._assert(n===`true`||n===`false`||n===`mixed`,`Value of "pressed" attribute must be a boolean or "mixed"`,r),e.pressed=n===`true`||n!==`false`&&`mixed`;return}if(t===`selected`){this._assert(n===`true`||n===`false`,`Value of "selected" attribute must be a boolean`,r),e.selected=n===`true`;return}this._assert(!1,`Unsupported attribute [${t}]`,r)}_assert(e,t,n){e||this._throwError(t||`Assertion error`,n)}},b=class extends Error{constructor(e,t){super(e),m(this,`pos`,void 0),this.pos=t}};function x(e,t){return t?e?typeof t==`string`?e===t:!!e.match(new RegExp(t.pattern)):!1:!0}function S(e,t){if(!t?.normalized)return!0;if(!e)return!1;if(e===t.normalized||e===t.raw)return!0;let n=w(t);return n?!!e.match(n):!1}const C=Symbol(`cachedRegex`);function w(e){if(e[C]!==void 0)return e[C];let{raw:t}=e,n=t.startsWith(`/`)&&t.endsWith(`/`)&&t.length>1,r;try{r=n?new RegExp(t.slice(1,-1)):null}catch{r=null}return e[C]=r,r}function T(e,t,n){if(typeof e==`string`&&t.kind===`text`)return S(e,t.text);if(typeof e!=`object`||!e||t.kind!==`role`||t.role!==`fragment`&&t.role!==e.role||t.checked!==void 0&&t.checked!==e.checked||t.disabled!==void 0&&t.disabled!==e.disabled||t.expanded!==void 0&&t.expanded!==e.expanded||t.level!==void 0&&t.level!==e.level||t.pressed!==void 0&&t.pressed!==e.pressed||t.selected!==void 0&&t.selected!==e.selected||!x(e.name,t.name))return!1;if(t.props){for(let[n,r]of Object.entries(t.props))if(!S(e.props[n]||``,r))return!1}return t.containerMode===`contain`?D(e.children||[],t.children||[]):t.containerMode===`equal`?E(e.children||[],t.children||[],!1):t.containerMode===`deep-equal`||n?E(e.children||[],t.children||[],!0):D(e.children||[],t.children||[])}function E(e,t,n){if(t.length!==e.length)return!1;for(let r=0;r<t.length;++r)if(!T(e[r],t[r],n))return!1;return!0}function D(e,t){if(t.length>e.length)return!1;let n=e.slice(),r=t.slice();for(let e of r){let t=n.shift();for(;t&&!T(t,e,!1);)t=n.shift();if(!t)return!1}return!0}var De=xe({LineCounter:()=>Oe,Scalar:()=>O,YAMLError:()=>j,YAMLMap:()=>k,YAMLSeq:()=>A,parseDocument:()=>ke}),O=class{constructor(e,t=[0,0,0]){m(this,`value`,void 0),m(this,`range`,void 0),this.value=e,this.range=t}},k=class{constructor(e=[0,0,0]){m(this,`items`,void 0),m(this,`range`,void 0),this.items=[],this.range=e}},A=class{constructor(e=[0,0,0]){m(this,`items`,void 0),m(this,`range`,void 0),this.items=[],this.range=e}},Oe=class{constructor(){m(this,`lineStarts`,[0])}addNewLine(e){e>this.lineStarts[this.lineStarts.length-1]&&this.lineStarts.push(e)}linePos(e){let t=0,n=this.lineStarts.length-1;for(;t<n;){let r=t+n+1>>1;this.lineStarts[r]<=e?t=r:n=r-1}return{line:t+1,col:e-this.lineStarts[t]+1}}},j=class extends Error{constructor(e,t){super(e),m(this,`pos`,void 0),this.pos=t}};function ke(e,t={}){let n=t.lineCounter,r=[];if(n)for(let t=0;t<e.length;t++)e[t]===`
|
|
2
2
|
`&&n.addNewLine(t+1);try{return{contents:new Ae(e,r).parseRoot(),errors:r}}catch(e){if(e instanceof j)return r.push(e),{contents:null,errors:r};throw e}}var Ae=class{constructor(e,t){m(this,`lines`,void 0),m(this,`pos`,void 0),m(this,`text`,void 0),m(this,`errors`,void 0),this.text=e,this.errors=t,this.lines=[],this.pos=0;let n=0,r=e.split(`
|
|
3
3
|
`);for(let e of r){let t=e.replace(/\r$/,``),r=t.replace(/^\s+/,``),i=t.length-r.length;this.lines.push({indent:i,content:r,offset:n+i,lineOffset:n,raw:t}),n+=e.length+1}for(;this.lines.length>0&&this.lines[this.lines.length-1].content===``;)this.lines.pop()}parseRoot(){if(this.lines.length===0)return null;let e=this.parseNode(0);if(this.skipEmpty(),this.pos<this.lines.length){let e=this.currentLine();this.addError(`Unexpected scalar at node end`,e.offset)}return e}currentLine(){return this.lines[this.pos]}parseNode(e){this.skipEmpty();let t=this.currentLine();return!t||t.indent<e?null:t.content.startsWith(`- `)||t.content===`-`?this.parseSequence(t.indent):this.isMapEntry(t.content)?this.parseMap(t.indent):(this.pos++,this.parseScalarValue(t.content,t.offset,t))}parseSequence(e){let t=this.currentLine(),n=new A([t.offset-t.indent,0,0]),r=t.offset;for(;this.pos<this.lines.length;){this.skipEmpty();let t=this.currentLine();if(!t||t.indent<e)break;if(t.indent>e){this.addError(`Bad indentation of a sequence entry`,t.offset);break}if(!t.content.startsWith(`- `)&&t.content!==`-`)break;let i=t.content===`-`?1:2,a=t.content.slice(i),o=t.offset+i;if(this.pos++,a===``||a.trim()===``){let t=this.parseNode(e+1);t&&(n.items.push(t),r=this.peekLastOffset())}else if(this.isMapEntry(a)){let s=this.parseInlineMap(a,o,e+i,t);n.items.push(s),r=s.range[2]}else{let e=this.parseScalarValue(a,o,t);n.items.push(e),r=e.range[2]}}return n.range[1]=r,n.range[2]=r,n}parseMap(e){let t=this.currentLine(),n=new k([t.offset-t.indent,0,0]),r=t.offset;for(;this.pos<this.lines.length;){this.skipEmpty();let t=this.currentLine();if(!t||t.indent<e)break;if(t.indent>e){this.addError(`Bad indentation of a mapping entry`,t.offset);break}if(!this.isMapEntry(t.content))break;let{key:i,valueStr:a,colonOffset:o,valueOffset:s}=this.splitMapEntry(t.content,t.offset),c=new O(i,[t.offset,t.offset+i.length,o]);this.pos++;let l;l=a===``?this.parseMapValue(e,o):this.parseScalarValue(a.trim(),s,t),n.items.push({key:c,value:l}),r=l?this.getNodeEnd(l):o+1}return n.range[1]=r,n.range[2]=r,n}parseInlineMap(e,t,n,r){let i=new k([t,0,0]),a=t,{key:o,valueStr:s,colonOffset:c,valueOffset:l}=this.splitMapEntry(e,t),u=new O(o,[t,t+o.length,c]),d;for(d=s===``?this.parseMapValue(n,c):this.parseScalarValue(s.trim(),l,r),i.items.push({key:u,value:d}),a=d?this.getNodeEnd(d):c+1;this.pos<this.lines.length;){this.skipEmpty();let e=this.currentLine();if(!e||e.indent<n||e.indent>n||!this.isMapEntry(e.content)||e.content.startsWith(`- `))break;let t=this.splitMapEntry(e.content,e.offset),r=new O(t.key,[e.offset,e.offset+t.key.length,t.colonOffset]);this.pos++;let o;o=t.valueStr===``?this.parseMapValue(n,t.colonOffset):this.parseScalarValue(t.valueStr.trim(),t.valueOffset,e),i.items.push({key:r,value:o}),a=o?this.getNodeEnd(o):t.colonOffset+1}return i.range[1]=a,i.range[2]=a,i}parseMapValue(e,t){this.skipEmpty();let n=this.currentLine();return!n||n.indent<e?new O(null,[t+1,t+1,t+1]):n.indent===e&&(n.content.startsWith(`- `)||n.content===`-`)?this.parseNode(e):n.indent>e?this.parseNode(e+1):new O(null,[t+1,t+1,t+1])}getNodeEnd(e){return e.range[2]}peekLastOffset(){if(this.pos>0&&this.pos<=this.lines.length){let e=this.lines[this.pos-1];return e.lineOffset+e.raw.length}return this.text.length}parseScalarValue(e,t,n){let r=e.trim(),i=t+e.indexOf(r),a=i+r.length,o=n.lineOffset+n.raw.length;return r.startsWith(`"`)?this.parseQuotedScalar(r,i,o):r===`true`||r===`false`?new O(r===`true`,[i,a,o]):r===`null`||r===`~`?new O(null,[i,a,o]):r!==``&&je(r)?new O(Number(r),[i,a,o]):new O(r,[i,a,o])}parseQuotedScalar(e,t,n){let r=``,i=1;for(;i<e.length;){let a=e[i];if(a===`\\`){if(i++,i>=e.length){this.addError(`Unterminated double-quoted string`,t+i);break}let n=e[i];switch(n){case`n`:r+=`
|
|
4
4
|
`;break;case`t`:r+=` `;break;case`r`:r+=`\r`;break;case`"`:r+=`"`;break;case`\\`:r+=`\\`;break;case`/`:r+=`/`;break;default:r+=n}}else if(a===`"`){let e=t+i+1;return new O(r,[t,e,n])}else r+=a;i++}return this.addError(`Unterminated double-quoted string`,t),new O(r,[t,t+e.length,n])}skipEmpty(){for(;this.pos<this.lines.length&&this.lines[this.pos].content===``;)this.pos++}isMapEntry(e){return this.findMapColon(e)>=0}findMapColon(e){let t=!1,n=!1;for(let r=0;r<e.length;r++){let i=e[r];if(n){n=!1;continue}if(i===`\\`&&t){n=!0;continue}if(i===`"`){t=!t;continue}if(!t&&i===`:`&&(r+1>=e.length||e[r+1]===` `))return r}return-1}splitMapEntry(e,t){let n=this.findMapColon(e),r=e.slice(0,n).trim(),i=t+n,a=e.slice(n+1),o=a.trimStart(),s=i+1+(a.length-a.trimStart().length);return r.startsWith(`"`)&&r.endsWith(`"`)?{key:r.slice(1,-1),valueStr:o,colonOffset:i,valueOffset:s}:{key:r,valueStr:o,colonOffset:i,valueOffset:s}}addError(e,t){this.errors.push(new j(e,[t,t+1]))}};function je(e){return e===``||e===`-`||e===`+`?!1:/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(e)}function M(e){return Me(e)?`"`+e.replace(/[\\"\x00-\x1f\x7f-\x9f]/g,e=>{switch(e){case`\\`:return`\\\\`;case`"`:return`\\"`;case`\b`:return`\\b`;case`\f`:return`\\f`;case`
|