@enekesabel/playwright-lite 0.1.0 → 0.2.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 +87 -87
- package/dist/index.mjs +328 -145
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -14754,6 +14754,27 @@ function validateString(value, name) {
|
|
|
14754
14754
|
if (typeof value === "string") return value;
|
|
14755
14755
|
throw new Error(`${name}: expected string, got ${typeof value}`);
|
|
14756
14756
|
}
|
|
14757
|
+
/**
|
|
14758
|
+
* `delay` is `float?` in the pinned protocol for press, type and the pointer
|
|
14759
|
+
* actions. Like the pointer options, a non-finite value is rejected instead of
|
|
14760
|
+
* reaching the input path as NaN, and a boxed `Number` is unwrapped for the
|
|
14761
|
+
* caller to forward instead of leaking an object into the input path.
|
|
14762
|
+
*/
|
|
14763
|
+
function validateDelay(value) {
|
|
14764
|
+
if (value === void 0) return void 0;
|
|
14765
|
+
const delay = value instanceof Number ? value.valueOf() : value;
|
|
14766
|
+
if (typeof delay !== "number" || !Number.isFinite(delay)) throw new TypeError("delay: expected number");
|
|
14767
|
+
return delay;
|
|
14768
|
+
}
|
|
14769
|
+
/**
|
|
14770
|
+
* `signal` is a client-side option in the pinned API: it never reaches the
|
|
14771
|
+
* protocol, so the adapter checks the value itself. `name` is the API member
|
|
14772
|
+
* or option group the message speaks for, such as `click` or `Query`.
|
|
14773
|
+
*/
|
|
14774
|
+
function validateSignal(name, value) {
|
|
14775
|
+
if (value === void 0 || value instanceof AbortSignal) return;
|
|
14776
|
+
throw new TypeError(`${name} signal must be an AbortSignal`);
|
|
14777
|
+
}
|
|
14757
14778
|
function validateNoWaitAfter(method, value) {
|
|
14758
14779
|
if (method !== "click" && method !== "press") return;
|
|
14759
14780
|
if (value === void 0 || typeof value === "boolean" || value instanceof Boolean) return;
|
|
@@ -15571,16 +15592,16 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15571
15592
|
return this.ownerPage.resolveAll(this.selector).map((element) => this.ownerPage.elementHandleFor(element));
|
|
15572
15593
|
}
|
|
15573
15594
|
async getAttribute(name, options) {
|
|
15574
|
-
return this.ownerPage.locatorGetAttribute(this.selector, this.label, name, options);
|
|
15595
|
+
return withAbortPrefix("locator.getAttribute", () => this.ownerPage.locatorGetAttribute(this.selector, this.label, name, options));
|
|
15575
15596
|
}
|
|
15576
15597
|
async textContent(options) {
|
|
15577
|
-
return this.ownerPage.locatorTextContent(this.selector, this.label, options);
|
|
15598
|
+
return withAbortPrefix("locator.textContent", () => this.ownerPage.locatorTextContent(this.selector, this.label, options));
|
|
15578
15599
|
}
|
|
15579
15600
|
async innerText(options) {
|
|
15580
|
-
return this.ownerPage.locatorInnerText(this.selector, this.label, options);
|
|
15601
|
+
return withAbortPrefix("locator.innerText", () => this.ownerPage.locatorInnerText(this.selector, this.label, options));
|
|
15581
15602
|
}
|
|
15582
15603
|
async innerHTML(options) {
|
|
15583
|
-
return this.ownerPage.locatorInnerHTML(this.selector, this.label, options);
|
|
15604
|
+
return withAbortPrefix("locator.innerHTML", () => this.ownerPage.locatorInnerHTML(this.selector, this.label, options));
|
|
15584
15605
|
}
|
|
15585
15606
|
async allInnerTexts() {
|
|
15586
15607
|
return this.ownerPage.locatorAllInnerTexts(this.selector);
|
|
@@ -15589,19 +15610,19 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15589
15610
|
return this.ownerPage.locatorAllTextContents(this.selector);
|
|
15590
15611
|
}
|
|
15591
15612
|
async inputValue(options) {
|
|
15592
|
-
return this.ownerPage.locatorInputValue(this.selector, this.label, options);
|
|
15613
|
+
return withAbortPrefix("locator.inputValue", () => this.ownerPage.locatorInputValue(this.selector, this.label, options));
|
|
15593
15614
|
}
|
|
15594
15615
|
async isEnabled(options) {
|
|
15595
|
-
return this.ownerPage.locatorIsEnabled(this.selector, this.label, options);
|
|
15616
|
+
return withAbortPrefix("locator.isEnabled", () => this.ownerPage.locatorIsEnabled(this.selector, this.label, options));
|
|
15596
15617
|
}
|
|
15597
15618
|
async isDisabled(options) {
|
|
15598
|
-
return this.ownerPage.locatorIsDisabled(this.selector, this.label, options);
|
|
15619
|
+
return withAbortPrefix("locator.isDisabled", () => this.ownerPage.locatorIsDisabled(this.selector, this.label, options));
|
|
15599
15620
|
}
|
|
15600
15621
|
async isChecked(options) {
|
|
15601
|
-
return this.ownerPage.locatorIsChecked(this.selector, this.label, options);
|
|
15622
|
+
return withAbortPrefix("locator.isChecked", () => this.ownerPage.locatorIsChecked(this.selector, this.label, options));
|
|
15602
15623
|
}
|
|
15603
15624
|
async isEditable(options) {
|
|
15604
|
-
return this.ownerPage.locatorIsEditable(this.selector, this.label, options);
|
|
15625
|
+
return withAbortPrefix("locator.isEditable", () => this.ownerPage.locatorIsEditable(this.selector, this.label, options));
|
|
15605
15626
|
}
|
|
15606
15627
|
async isVisible(options) {
|
|
15607
15628
|
return this.ownerPage.locatorIsVisible(this.selector, this.label, options);
|
|
@@ -15610,7 +15631,7 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15610
15631
|
return !this.ownerPage.locatorIsVisible(this.selector, this.label, options);
|
|
15611
15632
|
}
|
|
15612
15633
|
async boundingBox(options) {
|
|
15613
|
-
return this.ownerPage.locatorBoundingBox(this.selector, this.label, options);
|
|
15634
|
+
return withAbortPrefix("locator.boundingBox", () => this.ownerPage.locatorBoundingBox(this.selector, this.label, options));
|
|
15614
15635
|
}
|
|
15615
15636
|
/**
|
|
15616
15637
|
* Captures the accessibility snapshot rooted at this locator's sole element.
|
|
@@ -15620,7 +15641,7 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15620
15641
|
* not add frame traversal or browser-process behavior.
|
|
15621
15642
|
*/
|
|
15622
15643
|
async ariaSnapshot(options = {}) {
|
|
15623
|
-
return this.ownerPage.locatorAriaSnapshot(this.selector, this.label, options);
|
|
15644
|
+
return withAbortPrefix("locator.ariaSnapshot", () => this.ownerPage.locatorAriaSnapshot(this.selector, this.label, options));
|
|
15624
15645
|
}
|
|
15625
15646
|
/**
|
|
15626
15647
|
* The public Playwright matcher implementation calls this private-shaped
|
|
@@ -15641,7 +15662,7 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15641
15662
|
}
|
|
15642
15663
|
async evaluate(pageFunction, arg, options) {
|
|
15643
15664
|
assertMaxArguments(arguments.length, 3);
|
|
15644
|
-
return this.ownerPage.locatorEvaluate(this.selector, this.label, pageFunction, arg, options);
|
|
15665
|
+
return withAbortPrefix("locator.evaluate", () => this.ownerPage.locatorEvaluate(this.selector, this.label, pageFunction, arg, options));
|
|
15645
15666
|
}
|
|
15646
15667
|
async evaluateAll(pageFunction, arg) {
|
|
15647
15668
|
assertMaxArguments(arguments.length, 2);
|
|
@@ -15654,26 +15675,45 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15654
15675
|
});
|
|
15655
15676
|
}
|
|
15656
15677
|
async fill(value, options) {
|
|
15657
|
-
rejectUnsupportedOptions("fill", options, [
|
|
15658
|
-
|
|
15678
|
+
rejectUnsupportedOptions("fill", options, [
|
|
15679
|
+
"noWaitAfter",
|
|
15680
|
+
"signal",
|
|
15681
|
+
"timeout"
|
|
15682
|
+
]);
|
|
15683
|
+
await withAbortPrefix("locator.fill", () => this.ownerPage.fillSelector(this.selector, value, this.label, options?.timeout, void 0, true, options?.signal));
|
|
15659
15684
|
}
|
|
15660
15685
|
async setInputFiles(files, options) {
|
|
15661
|
-
rejectUnsupportedOptions("setInputFiles", options, [
|
|
15662
|
-
|
|
15686
|
+
rejectUnsupportedOptions("setInputFiles", options, [
|
|
15687
|
+
"noWaitAfter",
|
|
15688
|
+
"signal",
|
|
15689
|
+
"timeout"
|
|
15690
|
+
]);
|
|
15691
|
+
await withAbortPrefix("locator.setInputFiles", () => this.ownerPage.setInputFilesSelector(this.selector, files, options, true));
|
|
15663
15692
|
}
|
|
15664
15693
|
async press(key, options) {
|
|
15665
|
-
rejectUnsupportedOptions("press", options, [
|
|
15666
|
-
|
|
15694
|
+
const delay = rejectUnsupportedOptions("press", options, [
|
|
15695
|
+
"delay",
|
|
15696
|
+
"noWaitAfter",
|
|
15697
|
+
"signal",
|
|
15698
|
+
"timeout"
|
|
15699
|
+
]);
|
|
15700
|
+
await withAbortPrefix("locator.press", () => this.ownerPage.pressSelector(this.selector, key, this.label, options?.timeout, void 0, true, options?.signal, delay));
|
|
15667
15701
|
}
|
|
15668
15702
|
async focus(options) {
|
|
15669
|
-
|
|
15703
|
+
rejectUnsupportedOptions("focus", options, ["signal", "timeout"]);
|
|
15704
|
+
await withAbortPrefix("locator.focus", () => this.ownerPage.focusSelector(this.selector, this.label, options));
|
|
15670
15705
|
}
|
|
15671
15706
|
async blur(options) {
|
|
15672
|
-
|
|
15707
|
+
rejectUnsupportedOptions("blur", options, ["signal", "timeout"]);
|
|
15708
|
+
await withAbortPrefix("locator.blur", () => this.ownerPage.blurSelector(this.selector, this.label, options));
|
|
15673
15709
|
}
|
|
15674
15710
|
async clear(options) {
|
|
15675
|
-
rejectUnsupportedOptions("clear", options, [
|
|
15676
|
-
|
|
15711
|
+
rejectUnsupportedOptions("clear", options, [
|
|
15712
|
+
"noWaitAfter",
|
|
15713
|
+
"signal",
|
|
15714
|
+
"timeout"
|
|
15715
|
+
]);
|
|
15716
|
+
await withAbortPrefix("locator.clear", () => this.ownerPage.fillSelector(this.selector, "", this.label, options?.timeout, void 0, true, options?.signal));
|
|
15677
15717
|
}
|
|
15678
15718
|
async hover(options) {
|
|
15679
15719
|
await this.ownerPage.hoverSelector(this.selector, this.label, options?.timeout, void 0, {
|
|
@@ -15706,39 +15746,52 @@ var LocatorImpl = class LocatorImpl {
|
|
|
15706
15746
|
});
|
|
15707
15747
|
}
|
|
15708
15748
|
async dispatchEvent(type, eventInit = {}, options) {
|
|
15709
|
-
rejectUnsupportedOptions("dispatchEvent", options, ["timeout"]);
|
|
15710
|
-
await this.ownerPage.dispatchEventSelector(this.selector, type, eventInit, this.label, options?.timeout);
|
|
15749
|
+
rejectUnsupportedOptions("dispatchEvent", options, ["signal", "timeout"]);
|
|
15750
|
+
await withAbortPrefix("locator.dispatchEvent", () => this.ownerPage.dispatchEventSelector(this.selector, type, eventInit, this.label, options?.timeout, void 0, true, options?.signal));
|
|
15711
15751
|
}
|
|
15712
15752
|
async selectOption(values, options) {
|
|
15713
|
-
rejectUnsupportedOptions("selectOption", options, [
|
|
15714
|
-
|
|
15753
|
+
rejectUnsupportedOptions("selectOption", options, [
|
|
15754
|
+
"noWaitAfter",
|
|
15755
|
+
"signal",
|
|
15756
|
+
"timeout"
|
|
15757
|
+
]);
|
|
15758
|
+
return withAbortPrefix("locator.selectOption", () => this.ownerPage.selectOptionSelector(this.selector, values, this.label, options?.timeout, void 0, true, options?.signal));
|
|
15715
15759
|
}
|
|
15716
15760
|
async selectText(options) {
|
|
15717
|
-
rejectUnsupportedOptions("selectText", options, ["timeout"]);
|
|
15718
|
-
await this.ownerPage.selectText(this.selector, this.label, options?.timeout);
|
|
15761
|
+
rejectUnsupportedOptions("selectText", options, ["signal", "timeout"]);
|
|
15762
|
+
await withAbortPrefix("locator.selectText", () => this.ownerPage.selectText(this.selector, this.label, options?.timeout, void 0, options?.signal));
|
|
15719
15763
|
}
|
|
15720
15764
|
async scrollIntoViewIfNeeded(options) {
|
|
15721
|
-
rejectUnsupportedOptions("scrollIntoViewIfNeeded", options, ["timeout"]);
|
|
15722
|
-
await this.ownerPage.scrollLocatorIntoView(this.selector, this.label, options?.timeout);
|
|
15765
|
+
rejectUnsupportedOptions("scrollIntoViewIfNeeded", options, ["signal", "timeout"]);
|
|
15766
|
+
await withAbortPrefix("locator.scrollIntoViewIfNeeded", () => this.ownerPage.scrollLocatorIntoView(this.selector, this.label, options?.timeout, void 0, options?.signal));
|
|
15723
15767
|
}
|
|
15724
15768
|
async type(text, options = {}) {
|
|
15769
|
+
await withAbortPrefix("locator.type", () => this.typeText(text, options));
|
|
15770
|
+
}
|
|
15771
|
+
async pressSequentially(text, options = {}) {
|
|
15772
|
+
await withAbortPrefix("locator.pressSequentially", () => this.typeText(text, options));
|
|
15773
|
+
}
|
|
15774
|
+
async typeText(text, options) {
|
|
15725
15775
|
rejectUnsupportedOptions("type", options, [
|
|
15726
15776
|
"delay",
|
|
15727
15777
|
"noWaitAfter",
|
|
15778
|
+
"signal",
|
|
15728
15779
|
"timeout"
|
|
15729
15780
|
]);
|
|
15730
|
-
await this.ownerPage.
|
|
15731
|
-
}
|
|
15732
|
-
async pressSequentially(text, options = {}) {
|
|
15733
|
-
await this.type(text, options);
|
|
15781
|
+
await this.ownerPage.typeSelector(this.selector, text, options, this.label, true);
|
|
15734
15782
|
}
|
|
15735
15783
|
async waitFor(options = {}) {
|
|
15736
15784
|
const state = options.state ?? "visible";
|
|
15737
|
-
rejectUnsupportedOptions("waitFor", options, [
|
|
15738
|
-
|
|
15785
|
+
rejectUnsupportedOptions("waitFor", options, [
|
|
15786
|
+
"signal",
|
|
15787
|
+
"state",
|
|
15788
|
+
"timeout"
|
|
15789
|
+
]);
|
|
15790
|
+
await withAbortPrefix("locator.waitFor", () => this.ownerPage.waitForState(this.selector, {
|
|
15791
|
+
signal: options.signal,
|
|
15739
15792
|
state,
|
|
15740
15793
|
timeout: options.timeout
|
|
15741
|
-
}, this.label);
|
|
15794
|
+
}, this.label));
|
|
15742
15795
|
}
|
|
15743
15796
|
};
|
|
15744
15797
|
/**
|
|
@@ -15752,11 +15805,14 @@ function requireBrand(value, context) {
|
|
|
15752
15805
|
if (typeof payload !== "object" || payload === null || typeof payload.getSelector !== "function" || typeof payload.resolveElements !== "function") throw new TypeError(`${context}: expected an PlaywrightLite Locator, got incompatible branded object`);
|
|
15753
15806
|
return payload;
|
|
15754
15807
|
}
|
|
15808
|
+
/** Returns the normalized `delay`, unwrapped like the pointer options. */
|
|
15755
15809
|
function rejectUnsupportedOptions(method, options, supported = []) {
|
|
15756
|
-
if (!options) return;
|
|
15810
|
+
if (!options) return void 0;
|
|
15757
15811
|
const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && !supported.includes(key));
|
|
15758
15812
|
if (unsupported.length > 0) throw new Error(`${method}(): unsupported Playwright option(s): ${unsupported.join(", ")}.`);
|
|
15813
|
+
validateSignal(method, options.signal);
|
|
15759
15814
|
if (supported.includes("noWaitAfter")) validateNoWaitAfter(method, options.noWaitAfter);
|
|
15815
|
+
return supported.includes("delay") ? validateDelay(options.delay) : void 0;
|
|
15760
15816
|
}
|
|
15761
15817
|
function cssObjectToString(style) {
|
|
15762
15818
|
return Object.entries(style).map(([key, value]) => {
|
|
@@ -15880,22 +15936,22 @@ var PageImpl = class PageImpl {
|
|
|
15880
15936
|
this.injected.hideHighlight();
|
|
15881
15937
|
}
|
|
15882
15938
|
async getAttribute(selector, name, options) {
|
|
15883
|
-
return this.query(selector, `page.getAttribute(${JSON.stringify(selector)}, ${JSON.stringify(name)})`, options, false, (element) => element.getAttribute(name));
|
|
15939
|
+
return withAbortPrefix("page.getAttribute", () => this.query(selector, `page.getAttribute(${JSON.stringify(selector)}, ${JSON.stringify(name)})`, options, false, (element) => element.getAttribute(name)));
|
|
15884
15940
|
}
|
|
15885
15941
|
async textContent(selector, options) {
|
|
15886
|
-
return this.query(selector, `page.textContent(${JSON.stringify(selector)})`, options, false, (element) => element.textContent);
|
|
15942
|
+
return withAbortPrefix("page.textContent", () => this.query(selector, `page.textContent(${JSON.stringify(selector)})`, options, false, (element) => element.textContent));
|
|
15887
15943
|
}
|
|
15888
15944
|
async inputValue(selector, options) {
|
|
15889
|
-
return this.query(selector, `page.inputValue(${JSON.stringify(selector)})`, options, false, (element) => this.inputValueForElement(element));
|
|
15945
|
+
return withAbortPrefix("page.inputValue", () => this.query(selector, `page.inputValue(${JSON.stringify(selector)})`, options, false, (element) => this.inputValueForElement(element)));
|
|
15890
15946
|
}
|
|
15891
15947
|
async isEnabled(selector, options) {
|
|
15892
|
-
return this.queryState(selector, "enabled", options, false);
|
|
15948
|
+
return withAbortPrefix("page.isEnabled", () => this.queryState(selector, "enabled", options, false));
|
|
15893
15949
|
}
|
|
15894
15950
|
async isDisabled(selector, options) {
|
|
15895
|
-
return this.queryState(selector, "disabled", options, false);
|
|
15951
|
+
return withAbortPrefix("page.isDisabled", () => this.queryState(selector, "disabled", options, false));
|
|
15896
15952
|
}
|
|
15897
15953
|
async isChecked(selector, options) {
|
|
15898
|
-
return this.queryState(selector, "checked", options, false);
|
|
15954
|
+
return withAbortPrefix("page.isChecked", () => this.queryState(selector, "checked", options, false));
|
|
15899
15955
|
}
|
|
15900
15956
|
async $(selector, options = {}) {
|
|
15901
15957
|
assertDollarOptions(options);
|
|
@@ -15905,7 +15961,7 @@ var PageImpl = class PageImpl {
|
|
|
15905
15961
|
return this.resolveAll(selector).map((element) => this.elementHandleFor(element));
|
|
15906
15962
|
}
|
|
15907
15963
|
async waitForSelector(selector, options = {}) {
|
|
15908
|
-
return await this.waitForSelectorInRoot(this.document, selector, options);
|
|
15964
|
+
return await withAbortPrefix("page.waitForSelector", () => this.waitForSelectorInRoot(this.document, selector, options));
|
|
15909
15965
|
}
|
|
15910
15966
|
async waitForSelectorWithinElement(root, selector, options = {}) {
|
|
15911
15967
|
return await this.waitForSelectorInRoot(root, selector, options, false);
|
|
@@ -15950,7 +16006,7 @@ var PageImpl = class PageImpl {
|
|
|
15950
16006
|
const isArray = expression === "to.have.count" || expression.endsWith(".array");
|
|
15951
16007
|
const elements = this.resolveAll(selector);
|
|
15952
16008
|
if (!elements.length) return missingExpectationAttempt(expression, expectOptions);
|
|
15953
|
-
if (!isArray && elements.length > 1) throw
|
|
16009
|
+
if (!isArray && elements.length > 1) throw presentOriginalXPath(this.injected.strictModeViolationError(this.injected.parseSelector(selector), elements), selector);
|
|
15954
16010
|
const injectedOptions = Object.fromEntries(Object.entries(options).filter(([key]) => key !== "timeout" && key !== "signal"));
|
|
15955
16011
|
if (expression === "to.match.aria" && typeof injectedOptions.expectedValue === "string") injectedOptions.expectedValue = parseAriaExpectation(injectedOptions.expectedValue);
|
|
15956
16012
|
const result = await this.injected.expect(elements[0], {
|
|
@@ -15976,6 +16032,7 @@ var PageImpl = class PageImpl {
|
|
|
15976
16032
|
*/
|
|
15977
16033
|
async performPointerAction(selector, label, action, options, deadline, checked, apiMethod = action) {
|
|
15978
16034
|
try {
|
|
16035
|
+
this.attachActionSignal(deadline, options.signal);
|
|
15979
16036
|
while (true) {
|
|
15980
16037
|
this.assertActionDeadline(deadline, action);
|
|
15981
16038
|
try {
|
|
@@ -16035,12 +16092,13 @@ var PageImpl = class PageImpl {
|
|
|
16035
16092
|
if (!checked && "isRadio" in state && state.isRadio) throw new Error("Cannot uncheck radio button. Radio buttons can only be unchecked by selecting another radio button in the same group.");
|
|
16036
16093
|
return state.matches === checked;
|
|
16037
16094
|
}
|
|
16038
|
-
async fillSelector(selector, value, label, timeout, deadline = this.createActionDeadline(timeout)) {
|
|
16095
|
+
async fillSelector(selector, value, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
|
|
16096
|
+
this.attachActionSignal(deadline, signal);
|
|
16039
16097
|
const { element } = await this.retryActionability(selector, label, "fill", [
|
|
16040
16098
|
"visible",
|
|
16041
16099
|
"enabled",
|
|
16042
16100
|
"editable"
|
|
16043
|
-
], false, deadline);
|
|
16101
|
+
], false, deadline, void 0, void 0, strict);
|
|
16044
16102
|
this.assertActionDeadline(deadline, "fill");
|
|
16045
16103
|
const result = this.actionableInjected.fill(element, value);
|
|
16046
16104
|
if (result === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
|
|
@@ -16050,14 +16108,18 @@ var PageImpl = class PageImpl {
|
|
|
16050
16108
|
if (!inputTarget) throw new Error(`Element is not connected for locator ${label}`);
|
|
16051
16109
|
this.insertFilledText(inputTarget, value, deadline, "fill");
|
|
16052
16110
|
}
|
|
16053
|
-
async pressSelector(selector, key, label, timeout, deadline = this.createActionDeadline(timeout)) {
|
|
16054
|
-
|
|
16111
|
+
async pressSelector(selector, key, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal, delay) {
|
|
16112
|
+
this.attachActionSignal(deadline, signal);
|
|
16113
|
+
const element = await this.query(selector, label, {
|
|
16114
|
+
signal,
|
|
16115
|
+
timeout
|
|
16116
|
+
}, strict, (candidate) => candidate, deadline);
|
|
16055
16117
|
this.assertActionDeadline(deadline, "press");
|
|
16056
16118
|
this.focusElement(element);
|
|
16057
|
-
await this.keyboard.press(key, {}, deadline);
|
|
16119
|
+
await this.keyboard.press(key, { delay }, deadline);
|
|
16058
16120
|
}
|
|
16059
|
-
async focusSelector(selector, label, options) {
|
|
16060
|
-
await this.query(selector, label, options,
|
|
16121
|
+
async focusSelector(selector, label, options, strict = true) {
|
|
16122
|
+
await this.query(selector, label, options, strict, (element) => {
|
|
16061
16123
|
if (this.actionableInjected.focusNode(element) === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
|
|
16062
16124
|
});
|
|
16063
16125
|
}
|
|
@@ -16075,27 +16137,35 @@ var PageImpl = class PageImpl {
|
|
|
16075
16137
|
if (typeof checked !== "boolean") throw new TypeError("checked must be a boolean");
|
|
16076
16138
|
await this.performPointerAction(selector, label, "click", options, deadline, checked, apiMethod);
|
|
16077
16139
|
}
|
|
16078
|
-
async selectOptionSelector(selector, values, label, timeout, deadline = this.createActionDeadline(timeout)) {
|
|
16140
|
+
async selectOptionSelector(selector, values, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
|
|
16141
|
+
this.attachActionSignal(deadline, signal);
|
|
16079
16142
|
const options = (values === null ? [] : Array.isArray(values) ? values : [values]).map((value) => typeof value === "string" ? { valueOrLabel: value } : value);
|
|
16080
16143
|
let lastError;
|
|
16081
16144
|
while (true) {
|
|
16082
16145
|
if (Date.now() >= deadline.expiresAt) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded.${lastError ? ` ${lastError.message}` : ""}`, { cause: lastError });
|
|
16083
|
-
const { element } = await this.retryActionability(selector, label, "select option", ["visible", "enabled"], false, deadline);
|
|
16146
|
+
const { element } = await this.retryActionability(selector, label, "select option", ["visible", "enabled"], false, deadline, void 0, void 0, strict);
|
|
16084
16147
|
this.assertActionDeadline(deadline, "select option");
|
|
16085
16148
|
const result = this.actionableInjected.selectOptions(element, options);
|
|
16086
16149
|
if (Array.isArray(result)) return result;
|
|
16087
16150
|
lastError = result === "error:optionnotenabled" ? /* @__PURE__ */ new Error("Element is not enabled") : result === "error:notconnected" ? /* @__PURE__ */ new Error(`Element is not connected for locator ${label}`) : /* @__PURE__ */ new Error("Options not found");
|
|
16088
16151
|
const remaining = deadline.expiresAt - Date.now();
|
|
16089
16152
|
if (remaining <= 0) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded. ${lastError.message}`, { cause: lastError });
|
|
16090
|
-
|
|
16153
|
+
try {
|
|
16154
|
+
await this.waitWithinActionDeadline(Math.min(ACTION_RETRY_DELAY, remaining), deadline, "select option");
|
|
16155
|
+
} catch (error) {
|
|
16156
|
+
if (error instanceof AdapterTimeoutError) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded. ${lastError.message}`, { cause: lastError });
|
|
16157
|
+
throw error;
|
|
16158
|
+
}
|
|
16091
16159
|
}
|
|
16092
16160
|
}
|
|
16093
|
-
async selectText(selector, label, timeout, deadline = this.createActionDeadline(timeout)) {
|
|
16161
|
+
async selectText(selector, label, timeout, deadline = this.createActionDeadline(timeout), signal) {
|
|
16162
|
+
this.attachActionSignal(deadline, signal);
|
|
16094
16163
|
const { element } = await this.retryActionability(selector, label, "select text", ["visible"], false, deadline);
|
|
16095
16164
|
this.assertActionDeadline(deadline, "select text");
|
|
16096
16165
|
if (this.actionableInjected.selectText(element) === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
|
|
16097
16166
|
}
|
|
16098
|
-
async scrollLocatorIntoView(selector, label, timeout, deadline = this.createActionDeadline(timeout)) {
|
|
16167
|
+
async scrollLocatorIntoView(selector, label, timeout, deadline = this.createActionDeadline(timeout), signal) {
|
|
16168
|
+
this.attachActionSignal(deadline, signal);
|
|
16099
16169
|
const { element } = await this.retryActionability(selector, label, "scroll into view", ["stable"], false, deadline);
|
|
16100
16170
|
this.assertActionDeadline(deadline, "scroll into view");
|
|
16101
16171
|
this.scrollIntoViewIfNeeded(element);
|
|
@@ -16105,6 +16175,7 @@ var PageImpl = class PageImpl {
|
|
|
16105
16175
|
try {
|
|
16106
16176
|
await this.waitForSelectorInRoot(this.document, selector, {
|
|
16107
16177
|
state: options.state,
|
|
16178
|
+
signal: options.signal,
|
|
16108
16179
|
strict: true,
|
|
16109
16180
|
timeout: options.timeout
|
|
16110
16181
|
});
|
|
@@ -16118,7 +16189,11 @@ var PageImpl = class PageImpl {
|
|
|
16118
16189
|
if (options.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError("setInputFiles strict must be a boolean");
|
|
16119
16190
|
const payloads = inputFilePayloads(files);
|
|
16120
16191
|
const deadline = this.createActionDeadline(options.timeout);
|
|
16121
|
-
|
|
16192
|
+
this.attachActionSignal(deadline, options.signal);
|
|
16193
|
+
await this.query(selector, selector, {
|
|
16194
|
+
signal: options.signal,
|
|
16195
|
+
timeout: options.timeout
|
|
16196
|
+
}, strict || options.strict === true, (element) => {
|
|
16122
16197
|
this.assertActionDeadline(deadline, "setInputFiles");
|
|
16123
16198
|
const input = this.injected.retarget(element, "follow-label");
|
|
16124
16199
|
if (!input || !input.isConnected) throw new Error("Element is not connected");
|
|
@@ -16161,28 +16236,30 @@ var PageImpl = class PageImpl {
|
|
|
16161
16236
|
this.defaultNavigationTimeout = validateTimeout(timeout, "Default navigation timeout");
|
|
16162
16237
|
}
|
|
16163
16238
|
async innerText(selector, options) {
|
|
16164
|
-
return this.query(selector, `page.innerText(${JSON.stringify(selector)})`, options, false, (element) => {
|
|
16239
|
+
return withAbortPrefix("page.innerText", () => this.query(selector, `page.innerText(${JSON.stringify(selector)})`, options, false, (element) => {
|
|
16165
16240
|
if (element.namespaceURI !== "http://www.w3.org/1999/xhtml") throw new Error("Node is not an HTMLElement");
|
|
16166
16241
|
return element.innerText;
|
|
16167
|
-
});
|
|
16242
|
+
}));
|
|
16168
16243
|
}
|
|
16169
16244
|
async innerHTML(selector, options) {
|
|
16170
|
-
return this.query(selector, `page.innerHTML(${JSON.stringify(selector)})`, options, false, (element) => element.innerHTML);
|
|
16245
|
+
return withAbortPrefix("page.innerHTML", () => this.query(selector, `page.innerHTML(${JSON.stringify(selector)})`, options, false, (element) => element.innerHTML));
|
|
16171
16246
|
}
|
|
16172
16247
|
async isEditable(selector, options) {
|
|
16173
|
-
return this.queryState(selector, "editable", options, false);
|
|
16248
|
+
return withAbortPrefix("page.isEditable", () => this.queryState(selector, "editable", options, false));
|
|
16174
16249
|
}
|
|
16175
16250
|
async isVisible(selector, options) {
|
|
16176
|
-
|
|
16177
|
-
|
|
16178
|
-
|
|
16251
|
+
return this.selectorIsVisible("isVisible", selector, options);
|
|
16252
|
+
}
|
|
16253
|
+
async isHidden(selector, options) {
|
|
16254
|
+
return !this.selectorIsVisible("isHidden", selector, options);
|
|
16255
|
+
}
|
|
16256
|
+
selectorIsVisible(method, selector, options) {
|
|
16257
|
+
assertQueryOptions(options, ["strict", "timeout"]);
|
|
16258
|
+
if (options?.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError(`${method} strict must be a boolean`);
|
|
16179
16259
|
const element = options?.strict ? this.resolveLocatorElement(selector, true) : this.resolveAll(selector)[0];
|
|
16180
16260
|
if (!element) return false;
|
|
16181
16261
|
return this.elementState(element, "visible").matches;
|
|
16182
16262
|
}
|
|
16183
|
-
async isHidden(selector, options) {
|
|
16184
|
-
return !await this.isVisible(selector, options);
|
|
16185
|
-
}
|
|
16186
16263
|
async click(selector, options) {
|
|
16187
16264
|
assertPointerActionOptions("click", options);
|
|
16188
16265
|
await this.clickSelector(selector, `page.click(${JSON.stringify(selector)})`, options?.timeout, void 0, {
|
|
@@ -16191,28 +16268,45 @@ var PageImpl = class PageImpl {
|
|
|
16191
16268
|
});
|
|
16192
16269
|
}
|
|
16193
16270
|
async fill(selector, value, options) {
|
|
16194
|
-
assertPageActionOptions("fill", options, ["noWaitAfter"]);
|
|
16195
|
-
await this.fillSelector(selector, value, `page.fill(${JSON.stringify(selector)})`, options?.timeout);
|
|
16271
|
+
assertPageActionOptions("fill", options, ["noWaitAfter", "strict"]);
|
|
16272
|
+
await withAbortPrefix("page.fill", () => this.fillSelector(selector, value, `page.fill(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
|
|
16196
16273
|
}
|
|
16197
16274
|
async setInputFiles(selector, files, options) {
|
|
16198
|
-
await this.setInputFilesSelector(selector, files, options);
|
|
16275
|
+
await withAbortPrefix("page.setInputFiles", () => this.setInputFilesSelector(selector, files, options));
|
|
16199
16276
|
}
|
|
16200
16277
|
async press(selector, key, options) {
|
|
16201
|
-
assertPageActionOptions("press", options, [
|
|
16202
|
-
|
|
16278
|
+
const delay = assertPageActionOptions("press", options, [
|
|
16279
|
+
"delay",
|
|
16280
|
+
"noWaitAfter",
|
|
16281
|
+
"strict"
|
|
16282
|
+
]);
|
|
16283
|
+
await withAbortPrefix("page.press", () => this.pressSelector(selector, key, `page.press(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal, delay));
|
|
16284
|
+
}
|
|
16285
|
+
async type(selector, text, options) {
|
|
16286
|
+
await withAbortPrefix("page.type", () => this.typeSelector(selector, text, options, `page.type(${JSON.stringify(selector)})`, options?.strict === true));
|
|
16203
16287
|
}
|
|
16204
|
-
async
|
|
16205
|
-
assertPageActionOptions("type", options, [
|
|
16288
|
+
async typeSelector(selector, text, options, label, strict) {
|
|
16289
|
+
const delay = assertPageActionOptions("type", options, [
|
|
16290
|
+
"delay",
|
|
16291
|
+
"noWaitAfter",
|
|
16292
|
+
"strict"
|
|
16293
|
+
]);
|
|
16206
16294
|
const deadline = this.createActionDeadline(options?.timeout);
|
|
16207
|
-
|
|
16208
|
-
|
|
16209
|
-
|
|
16210
|
-
|
|
16211
|
-
}
|
|
16295
|
+
this.attachActionSignal(deadline, options?.signal);
|
|
16296
|
+
await this.query(selector, label, {
|
|
16297
|
+
signal: options?.signal,
|
|
16298
|
+
timeout: options?.timeout
|
|
16299
|
+
}, strict, (element) => {
|
|
16300
|
+
if (this.actionableInjected.focusNode(element, true) === "error:notconnected") throw new Error("Element is not connected");
|
|
16301
|
+
}, deadline);
|
|
16302
|
+
await this.keyboard.type(text, { delay }, deadline);
|
|
16212
16303
|
}
|
|
16213
16304
|
async focus(selector, options) {
|
|
16214
|
-
assertPageActionOptions("focus", options);
|
|
16215
|
-
await this.focusSelector(selector, `page.focus(${JSON.stringify(selector)})`,
|
|
16305
|
+
assertPageActionOptions("focus", options, ["strict"]);
|
|
16306
|
+
await withAbortPrefix("page.focus", () => this.focusSelector(selector, `page.focus(${JSON.stringify(selector)})`, {
|
|
16307
|
+
signal: options?.signal,
|
|
16308
|
+
timeout: options?.timeout
|
|
16309
|
+
}, options?.strict === true));
|
|
16216
16310
|
}
|
|
16217
16311
|
async hover(selector, options) {
|
|
16218
16312
|
await this.hoverSelector(selector, `page.hover(${JSON.stringify(selector)})`, options?.timeout, void 0, {
|
|
@@ -16221,8 +16315,8 @@ var PageImpl = class PageImpl {
|
|
|
16221
16315
|
});
|
|
16222
16316
|
}
|
|
16223
16317
|
async selectOption(selector, values, options) {
|
|
16224
|
-
assertPageActionOptions("selectOption", options, ["noWaitAfter"]);
|
|
16225
|
-
return this.selectOptionSelector(selector, values, `page.selectOption(${JSON.stringify(selector)})`, options?.timeout);
|
|
16318
|
+
assertPageActionOptions("selectOption", options, ["noWaitAfter", "strict"]);
|
|
16319
|
+
return withAbortPrefix("page.selectOption", () => this.selectOptionSelector(selector, values, `page.selectOption(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
|
|
16226
16320
|
}
|
|
16227
16321
|
async check(selector, options) {
|
|
16228
16322
|
await this.setCheckedSelector(selector, true, `page.check(${JSON.stringify(selector)})`, {
|
|
@@ -16250,10 +16344,14 @@ var PageImpl = class PageImpl {
|
|
|
16250
16344
|
}
|
|
16251
16345
|
async dispatchEvent(selector, type, eventInit = {}, options) {
|
|
16252
16346
|
assertPageDispatchEventOptions(options);
|
|
16253
|
-
await this.dispatchEventSelector(selector, type, eventInit, `page.dispatchEvent(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true);
|
|
16347
|
+
await withAbortPrefix("page.dispatchEvent", () => this.dispatchEventSelector(selector, type, eventInit, `page.dispatchEvent(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
|
|
16254
16348
|
}
|
|
16255
|
-
async dispatchEventSelector(selector, type, eventInit, label, timeout, deadline = this.createActionDeadline(timeout), strict = true) {
|
|
16256
|
-
|
|
16349
|
+
async dispatchEventSelector(selector, type, eventInit, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
|
|
16350
|
+
this.attachActionSignal(deadline, signal);
|
|
16351
|
+
await this.query(selector, label, {
|
|
16352
|
+
signal,
|
|
16353
|
+
timeout
|
|
16354
|
+
}, strict, (element) => this.actionableInjected.dispatchEvent(element, type, eventInit), deadline);
|
|
16257
16355
|
}
|
|
16258
16356
|
/**
|
|
16259
16357
|
* Pinned 26a9e47 client/frame.ts and server/frames.ts default to load,
|
|
@@ -16266,15 +16364,16 @@ var PageImpl = class PageImpl {
|
|
|
16266
16364
|
*/
|
|
16267
16365
|
async goto(url, options = {}) {
|
|
16268
16366
|
for (const [key, value] of Object.entries(options)) if (!["timeout", "waitUntil"].includes(key) && value !== void 0) throw new Error(`Unsupported Playwright option: goto.${key}`);
|
|
16269
|
-
const waitUntil = options.waitUntil
|
|
16270
|
-
if (
|
|
16271
|
-
"commit",
|
|
16272
|
-
"domcontentloaded",
|
|
16273
|
-
"load"
|
|
16274
|
-
].includes(waitUntil)) throw new Error(`Unsupported waitUntil value: ${waitUntil}`);
|
|
16367
|
+
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
|
16368
|
+
if (waitUntil === "networkidle") throw new Error(`Unsupported waitUntil value: ${waitUntil}`);
|
|
16275
16369
|
const timeout = this.resolveTimeout(options.timeout, DEFAULT_NAVIGATION_TIMEOUT, true);
|
|
16276
16370
|
if (typeof url !== "string") throw new Error("goto URL must be a string");
|
|
16277
|
-
|
|
16371
|
+
let target;
|
|
16372
|
+
try {
|
|
16373
|
+
target = new URL(url, this.document.baseURI);
|
|
16374
|
+
} catch {
|
|
16375
|
+
throw new Error("page.goto: Cannot navigate to invalid URL");
|
|
16376
|
+
}
|
|
16278
16377
|
if (![
|
|
16279
16378
|
"http:",
|
|
16280
16379
|
"https:",
|
|
@@ -16321,10 +16420,12 @@ var PageImpl = class PageImpl {
|
|
|
16321
16420
|
* and rendering. There is no frame traversal or protocol transport here.
|
|
16322
16421
|
*/
|
|
16323
16422
|
async ariaSnapshot(options = {}) {
|
|
16324
|
-
|
|
16325
|
-
|
|
16326
|
-
|
|
16327
|
-
|
|
16423
|
+
return withAbortPrefix("page.ariaSnapshot", async () => {
|
|
16424
|
+
assertAriaSnapshotOptions(options);
|
|
16425
|
+
if (options.signal?.aborted) throw actionAborted(options.signal, false);
|
|
16426
|
+
await this.waitForDocumentParser(options);
|
|
16427
|
+
return this.injectedAriaSnapshot(this.document.body ?? this.document.documentElement, options);
|
|
16428
|
+
});
|
|
16328
16429
|
}
|
|
16329
16430
|
injectedAriaSnapshot(element, options = {}) {
|
|
16330
16431
|
return this.injected.ariaSnapshot(element, {
|
|
@@ -16346,7 +16447,7 @@ var PageImpl = class PageImpl {
|
|
|
16346
16447
|
else resolve();
|
|
16347
16448
|
};
|
|
16348
16449
|
const ready = () => settle();
|
|
16349
|
-
const aborted = () => settle(
|
|
16450
|
+
const aborted = () => settle(actionAborted(options.signal, true));
|
|
16350
16451
|
this.window.addEventListener("DOMContentLoaded", ready, { once: true });
|
|
16351
16452
|
options.signal?.addEventListener("abort", aborted, { once: true });
|
|
16352
16453
|
if (timeout > 0) timeoutId = this.window.setTimeout(() => settle(new AdapterTimeoutError(`page.ariaSnapshot: Timeout ${timeout}ms exceeded.`)), timeout);
|
|
@@ -16512,17 +16613,25 @@ var PageImpl = class PageImpl {
|
|
|
16512
16613
|
expiresAt: effectiveTimeout === 0 ? Infinity : Date.now() + effectiveTimeout
|
|
16513
16614
|
};
|
|
16514
16615
|
}
|
|
16616
|
+
attachActionSignal(deadline, signal) {
|
|
16617
|
+
deadline.signal = signal;
|
|
16618
|
+
if (signal?.aborted) throw actionAborted(signal, false);
|
|
16619
|
+
}
|
|
16515
16620
|
assertActionDeadline(deadline, actionName) {
|
|
16621
|
+
if (deadline?.signal?.aborted) throw actionAborted(deadline.signal, true);
|
|
16516
16622
|
if (deadline && Date.now() >= deadline.expiresAt) throw new AdapterTimeoutError(`${actionName}: Timeout ${deadline.timeout}ms exceeded.`);
|
|
16517
16623
|
}
|
|
16518
16624
|
checkKeyboardActionDeadline(deadline) {
|
|
16519
16625
|
this.assertActionDeadline(deadline, "press");
|
|
16520
16626
|
}
|
|
16627
|
+
async waitKeyboardDelay(durationMs, deadline) {
|
|
16628
|
+
await this.waitWithinActionDeadline(durationMs, deadline, "press");
|
|
16629
|
+
}
|
|
16521
16630
|
async waitWithinActionDeadline(durationMs, deadline, actionName) {
|
|
16522
16631
|
this.assertActionDeadline(deadline, actionName);
|
|
16523
16632
|
if (!durationMs || durationMs <= 0) return;
|
|
16524
16633
|
const remaining = deadline ? deadline.expiresAt - Date.now() : durationMs;
|
|
16525
|
-
await this.
|
|
16634
|
+
if (!await waitForExpectationRetry(this.window, Math.min(durationMs, remaining), deadline?.signal) && deadline?.signal) throw actionAborted(deadline.signal, true);
|
|
16526
16635
|
this.assertActionDeadline(deadline, actionName);
|
|
16527
16636
|
}
|
|
16528
16637
|
async wait(durationMs) {
|
|
@@ -16566,9 +16675,7 @@ var PageImpl = class PageImpl {
|
|
|
16566
16675
|
return this.queryState(selector, "editable", options, true, label);
|
|
16567
16676
|
}
|
|
16568
16677
|
locatorIsVisible(selector, label, options) {
|
|
16569
|
-
assertQueryOptions(options,
|
|
16570
|
-
this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
|
|
16571
|
-
if (options?.signal?.aborted) throw queryAborted(options.signal);
|
|
16678
|
+
assertQueryOptions(options, ["timeout"]);
|
|
16572
16679
|
const element = this.resolveLocatorElement(selector, true);
|
|
16573
16680
|
if (!element) return false;
|
|
16574
16681
|
return this.elementState(element, "visible").matches;
|
|
@@ -16578,7 +16685,7 @@ var PageImpl = class PageImpl {
|
|
|
16578
16685
|
}
|
|
16579
16686
|
async locatorAriaSnapshot(selector, label, options = {}) {
|
|
16580
16687
|
assertAriaSnapshotOptions(options);
|
|
16581
|
-
if (options.signal?.aborted) throw
|
|
16688
|
+
if (options.signal?.aborted) throw actionAborted(options.signal, false);
|
|
16582
16689
|
if (options.mode === "ai") return this.injectedAriaSnapshot(this.queryElement(selector, label, true), options);
|
|
16583
16690
|
return this.query(selector, label, {
|
|
16584
16691
|
signal: options.signal,
|
|
@@ -16635,13 +16742,16 @@ var PageImpl = class PageImpl {
|
|
|
16635
16742
|
const state = options.state ?? "visible";
|
|
16636
16743
|
const timeout = this.resolveTimeout(options.timeout, DEFAULT_ACTION_TIMEOUT);
|
|
16637
16744
|
const deadline = timeout === 0 ? Infinity : Date.now() + timeout;
|
|
16745
|
+
const signal = options.signal;
|
|
16746
|
+
if (signal?.aborted) throw actionAborted(signal, false);
|
|
16638
16747
|
while (true) {
|
|
16639
16748
|
const element = root instanceof this.window.Element ? this.resolveWithinElement(root, selector, options.strict === true) : this.resolveLocatorElement(selector, options.strict === true);
|
|
16640
16749
|
const visible = !!element && this.elementState(element, "visible").matches === true;
|
|
16641
16750
|
if (state === "attached" && element || state === "visible" && visible) return this.elementHandleFor(element);
|
|
16642
16751
|
if (state === "detached" && !element || state === "hidden" && !visible) return null;
|
|
16643
16752
|
if (Date.now() >= deadline) throw new AdapterTimeoutError(`page.waitForSelector: Timeout ${timeout}ms exceeded.\nCall log:\n - waiting for ${formatLocator(selector)} to be ${state}`);
|
|
16644
|
-
|
|
16753
|
+
const delay = Math.min(QUERY_RETRY_DELAY, deadline - Date.now());
|
|
16754
|
+
if (!await waitForExpectationRetry(this.window, delay, signal)) throw actionAborted(signal, true);
|
|
16645
16755
|
}
|
|
16646
16756
|
}
|
|
16647
16757
|
async elementMatchesState(element, state) {
|
|
@@ -16658,10 +16768,14 @@ var PageImpl = class PageImpl {
|
|
|
16658
16768
|
return result.matches;
|
|
16659
16769
|
}
|
|
16660
16770
|
async query(selector, label, options, strict, evaluate, actionDeadline) {
|
|
16661
|
-
assertQueryOptions(options,
|
|
16771
|
+
assertQueryOptions(options, strict ? ["signal", "timeout"] : [
|
|
16772
|
+
"signal",
|
|
16773
|
+
"strict",
|
|
16774
|
+
"timeout"
|
|
16775
|
+
]);
|
|
16662
16776
|
const timeout = actionDeadline?.timeout ?? this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
|
|
16663
16777
|
const signal = options?.signal;
|
|
16664
|
-
if (signal?.aborted) throw
|
|
16778
|
+
if (signal?.aborted) throw actionAborted(signal, false);
|
|
16665
16779
|
const deadline = actionDeadline?.expiresAt ?? (timeout === 0 ? Infinity : Date.now() + timeout);
|
|
16666
16780
|
while (true) try {
|
|
16667
16781
|
return await evaluate(this.queryElement(selector, label, strict || options?.strict === true));
|
|
@@ -16670,7 +16784,7 @@ var PageImpl = class PageImpl {
|
|
|
16670
16784
|
const remaining = deadline - Date.now();
|
|
16671
16785
|
if (remaining <= 0) throw new AdapterTimeoutError(`Timeout ${timeout}ms exceeded.\nCall log:\n - waiting for ${formatLocator(selector)}`, { cause: error });
|
|
16672
16786
|
const delay = Math.min(QUERY_RETRY_DELAY, remaining);
|
|
16673
|
-
if (!await waitForExpectationRetry(this.window, delay, signal)) throw
|
|
16787
|
+
if (!await waitForExpectationRetry(this.window, delay, signal)) throw actionAborted(signal, true);
|
|
16674
16788
|
}
|
|
16675
16789
|
}
|
|
16676
16790
|
queryElement(selector, label, strict) {
|
|
@@ -16693,16 +16807,23 @@ var PageImpl = class PageImpl {
|
|
|
16693
16807
|
throw new Error(`Element is not ${result.missingState}`);
|
|
16694
16808
|
}
|
|
16695
16809
|
async waitForActionDeadline(operation, deadline, timeoutError) {
|
|
16696
|
-
if (
|
|
16697
|
-
if (Date.now() >= deadline.expiresAt) throw timeoutError();
|
|
16810
|
+
if (deadline?.signal?.aborted) throw actionAborted(deadline.signal, true);
|
|
16811
|
+
if (deadline && Date.now() >= deadline.expiresAt) throw timeoutError();
|
|
16812
|
+
if (!deadline) return operation;
|
|
16698
16813
|
let timeoutHandle;
|
|
16814
|
+
let onAbort;
|
|
16699
16815
|
try {
|
|
16700
16816
|
return await new Promise((resolve, reject) => {
|
|
16701
|
-
timeoutHandle = this.window.setTimeout(() => reject(timeoutError()), Math.max(0, deadline.expiresAt - Date.now()));
|
|
16817
|
+
if (deadline.expiresAt !== Infinity) timeoutHandle = this.window.setTimeout(() => reject(timeoutError()), Math.max(0, deadline.expiresAt - Date.now()));
|
|
16818
|
+
if (deadline.signal) {
|
|
16819
|
+
onAbort = () => reject(actionAborted(deadline.signal, true));
|
|
16820
|
+
deadline.signal.addEventListener("abort", onAbort, { once: true });
|
|
16821
|
+
}
|
|
16702
16822
|
operation.then(resolve, reject);
|
|
16703
16823
|
});
|
|
16704
16824
|
} finally {
|
|
16705
16825
|
if (timeoutHandle !== void 0) this.window.clearTimeout(timeoutHandle);
|
|
16826
|
+
if (onAbort) deadline.signal?.removeEventListener("abort", onAbort);
|
|
16706
16827
|
}
|
|
16707
16828
|
}
|
|
16708
16829
|
actionabilityDeadlineError(element, states) {
|
|
@@ -16717,7 +16838,7 @@ var PageImpl = class PageImpl {
|
|
|
16717
16838
|
}
|
|
16718
16839
|
return /* @__PURE__ */ new Error("Element is not stable");
|
|
16719
16840
|
}
|
|
16720
|
-
async retryActionability(selector, label, actionName, states, checkHitTarget, deadline, position, pointerOptions) {
|
|
16841
|
+
async retryActionability(selector, label, actionName, states, checkHitTarget, deadline, position, pointerOptions, strict = pointerOptions?.strict ?? true) {
|
|
16721
16842
|
let lastError;
|
|
16722
16843
|
let retry = 0;
|
|
16723
16844
|
const log = [];
|
|
@@ -16729,7 +16850,7 @@ var PageImpl = class PageImpl {
|
|
|
16729
16850
|
while (true) {
|
|
16730
16851
|
if (Date.now() >= deadline.expiresAt) throwTimeout();
|
|
16731
16852
|
try {
|
|
16732
|
-
const element = this.resolvePointerElement(selector, label,
|
|
16853
|
+
const element = this.resolvePointerElement(selector, label, strict);
|
|
16733
16854
|
if (pointerOptions && !pointerOptions.force) log.push(` - waiting for element to be ${states.includes("enabled") ? "visible, enabled and stable" : "visible and stable"}`);
|
|
16734
16855
|
if (!pointerOptions?.force) await this.ensureActionable(element, states, deadline);
|
|
16735
16856
|
if (Date.now() >= deadline.expiresAt) throwTimeout();
|
|
@@ -16776,7 +16897,12 @@ var PageImpl = class PageImpl {
|
|
|
16776
16897
|
if (log.length > 60) log.splice(0, log.length - 60);
|
|
16777
16898
|
}
|
|
16778
16899
|
if (remaining <= 0) throw timeoutError();
|
|
16779
|
-
|
|
16900
|
+
try {
|
|
16901
|
+
await this.waitWithinActionDeadline(Math.min(delay, remaining), deadline, actionName);
|
|
16902
|
+
} catch (error) {
|
|
16903
|
+
if (error instanceof AdapterTimeoutError) throw timeoutError();
|
|
16904
|
+
throw error;
|
|
16905
|
+
}
|
|
16780
16906
|
}
|
|
16781
16907
|
}
|
|
16782
16908
|
}
|
|
@@ -16969,8 +17095,8 @@ var PageImpl = class PageImpl {
|
|
|
16969
17095
|
this.assertActionDeadline(deadline, "press");
|
|
16970
17096
|
this.insertPressedText(element, text, inputType, eventData, deadline);
|
|
16971
17097
|
}
|
|
16972
|
-
async insertTextSelector(selector, text, label, deadline) {
|
|
16973
|
-
const element = await this.query(selector, label, { timeout: deadline.timeout },
|
|
17098
|
+
async insertTextSelector(selector, text, label, deadline, strict = true) {
|
|
17099
|
+
const element = await this.query(selector, label, { timeout: deadline.timeout }, strict, (candidate) => candidate, deadline);
|
|
16974
17100
|
this.assertActionDeadline(deadline, "press");
|
|
16975
17101
|
this.focusElement(element);
|
|
16976
17102
|
this.insertKeyboardText(element, text, "insertText", text, deadline);
|
|
@@ -17213,25 +17339,49 @@ var BrowserKeyboard = class {
|
|
|
17213
17339
|
async up(key, deadline) {
|
|
17214
17340
|
await this.upForTarget(key, deadline);
|
|
17215
17341
|
}
|
|
17216
|
-
async insertText(text) {
|
|
17217
|
-
this.page.insertKeyboardText(this.activeTarget(), text);
|
|
17342
|
+
async insertText(text, deadline) {
|
|
17343
|
+
this.page.insertKeyboardText(this.activeTarget(), text, "insertText", text, deadline);
|
|
17218
17344
|
}
|
|
17219
|
-
async type(text, options = {}) {
|
|
17345
|
+
async type(text, options = {}, deadline) {
|
|
17220
17346
|
const delay = options.delay || void 0;
|
|
17221
|
-
for (const character of text) if (keyboardLayout.has(character)) await this.press(character, { delay });
|
|
17347
|
+
for (const character of text) if (keyboardLayout.has(character)) await this.press(character, { delay }, deadline);
|
|
17222
17348
|
else {
|
|
17223
|
-
if (delay) await this.
|
|
17224
|
-
await this.insertText(character);
|
|
17349
|
+
if (delay) await this.page.waitKeyboardDelay(delay, deadline);
|
|
17350
|
+
await this.insertText(character, deadline);
|
|
17225
17351
|
}
|
|
17226
17352
|
}
|
|
17227
17353
|
async press(key, options = {}, deadline) {
|
|
17228
17354
|
const tokens = splitKeyboardShortcut(key);
|
|
17229
17355
|
const target = tokens.at(-1);
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17356
|
+
const modifiers = tokens.slice(0, -1);
|
|
17357
|
+
const held = /* @__PURE__ */ new Set();
|
|
17358
|
+
try {
|
|
17359
|
+
for (const modifier of modifiers) {
|
|
17360
|
+
held.add(modifier);
|
|
17361
|
+
await this.down(modifier, deadline);
|
|
17362
|
+
}
|
|
17363
|
+
held.add(target);
|
|
17364
|
+
await this.down(target, deadline);
|
|
17365
|
+
if (options.delay) await this.page.waitKeyboardDelay(options.delay, deadline);
|
|
17366
|
+
await this.up(target, deadline);
|
|
17367
|
+
held.delete(target);
|
|
17368
|
+
for (const modifier of modifiers.reverse()) {
|
|
17369
|
+
await this.up(modifier, deadline);
|
|
17370
|
+
held.delete(modifier);
|
|
17371
|
+
}
|
|
17372
|
+
} catch (error) {
|
|
17373
|
+
this.releaseKeys(held);
|
|
17374
|
+
throw error;
|
|
17375
|
+
}
|
|
17376
|
+
}
|
|
17377
|
+
releaseKeys(keys) {
|
|
17378
|
+
for (const key of keys) {
|
|
17379
|
+
const description = keyboardLayout.get(resolveKeyboardKey(key, this.page.window));
|
|
17380
|
+
if (!description) continue;
|
|
17381
|
+
this.pressedKeys.delete(description.code);
|
|
17382
|
+
this.keydownState.delete(description.code);
|
|
17383
|
+
if (isModifier(description.key)) this.pressedModifiers.delete(description.key);
|
|
17384
|
+
}
|
|
17235
17385
|
}
|
|
17236
17386
|
async downForTarget(key, deadline) {
|
|
17237
17387
|
this.page.checkKeyboardActionDeadline(deadline);
|
|
@@ -17288,13 +17438,6 @@ var BrowserKeyboard = class {
|
|
|
17288
17438
|
};
|
|
17289
17439
|
return description;
|
|
17290
17440
|
}
|
|
17291
|
-
async wait(delay, deadline) {
|
|
17292
|
-
this.page.checkKeyboardActionDeadline(deadline);
|
|
17293
|
-
const remaining = deadline ? Math.max(0, deadline.expiresAt - Date.now()) : delay;
|
|
17294
|
-
if (deadline && remaining <= 0) this.page.checkKeyboardActionDeadline(deadline);
|
|
17295
|
-
await new Promise((resolve) => this.page.window.setTimeout(resolve, Math.min(delay, remaining)));
|
|
17296
|
-
this.page.checkKeyboardActionDeadline(deadline);
|
|
17297
|
-
}
|
|
17298
17441
|
async waitForKeyboardPhase(deadline) {
|
|
17299
17442
|
this.page.checkKeyboardActionDeadline(deadline);
|
|
17300
17443
|
await new Promise((resolve) => this.page.window.setTimeout(resolve));
|
|
@@ -17411,12 +17554,17 @@ function validateTimeout(timeout, name) {
|
|
|
17411
17554
|
if (typeof timeout !== "number" || timeout < 0 || !Number.isFinite(timeout)) throw new TypeError(`${name} must be a non-negative finite number`);
|
|
17412
17555
|
return timeout;
|
|
17413
17556
|
}
|
|
17557
|
+
/** Returns the normalized `delay`, unwrapped like the pointer options. */
|
|
17414
17558
|
function assertPageActionOptions(method, options, supported = []) {
|
|
17415
|
-
if (!options) return;
|
|
17416
|
-
const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && key !== "timeout" && !supported.includes(key));
|
|
17559
|
+
if (!options) return void 0;
|
|
17560
|
+
const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && key !== "signal" && key !== "timeout" && !supported.includes(key));
|
|
17417
17561
|
if (unsupported.length > 0) throw new Error(`${method}(): unsupported options: ${unsupported.join(", ")}. Unsupported Playwright option(s) are not supported by the single-document adapter.`);
|
|
17562
|
+
validateSignal(method, options.signal);
|
|
17418
17563
|
if (options.timeout !== void 0) validateTimeout(options.timeout, `${method} timeout`);
|
|
17419
17564
|
if (supported.includes("noWaitAfter")) validateNoWaitAfter(method, options.noWaitAfter);
|
|
17565
|
+
const delay = supported.includes("delay") ? validateDelay(options.delay) : void 0;
|
|
17566
|
+
if (supported.includes("strict") && options.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError(`${method} strict must be a boolean`);
|
|
17567
|
+
return delay;
|
|
17420
17568
|
}
|
|
17421
17569
|
function assertPageDispatchEventOptions(options) {
|
|
17422
17570
|
assertPageActionOptions("dispatchEvent", options, ["strict"]);
|
|
@@ -17424,6 +17572,7 @@ function assertPageDispatchEventOptions(options) {
|
|
|
17424
17572
|
}
|
|
17425
17573
|
function assertPointerActionOptions(method, options) {
|
|
17426
17574
|
const supported = [
|
|
17575
|
+
"signal",
|
|
17427
17576
|
"noWaitAfter",
|
|
17428
17577
|
"position",
|
|
17429
17578
|
"trial",
|
|
@@ -17476,19 +17625,22 @@ function assertPointerActionOptions(method, options) {
|
|
|
17476
17625
|
}
|
|
17477
17626
|
function assertAriaSnapshotOptions(options) {
|
|
17478
17627
|
queryTimeout(options.timeout);
|
|
17479
|
-
|
|
17628
|
+
validateSignal("ARIA snapshot", options.signal);
|
|
17480
17629
|
}
|
|
17481
|
-
function assertQueryOptions(options,
|
|
17630
|
+
function assertQueryOptions(options, allowed) {
|
|
17482
17631
|
if (!options) return;
|
|
17483
|
-
for (const key of Object.keys(options))
|
|
17484
|
-
|
|
17485
|
-
|
|
17632
|
+
for (const key of Object.keys(options)) {
|
|
17633
|
+
if (key === "signal" && options.signal === void 0) continue;
|
|
17634
|
+
if (!allowed.includes(key)) throw new Error(`Unsupported query option: ${key}`);
|
|
17635
|
+
}
|
|
17636
|
+
validateSignal("Query", options.signal);
|
|
17486
17637
|
}
|
|
17487
17638
|
function assertDollarOptions(options) {
|
|
17488
17639
|
for (const key of Object.keys(options)) if (key !== "strict") throw new Error(`Unsupported query option: ${key}`);
|
|
17489
17640
|
}
|
|
17490
17641
|
function assertWaitForSelectorOptions(options, allowsStrict) {
|
|
17491
|
-
for (const key of Object.keys(options)) if (key !== "state" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported waitForSelector option: ${key}`);
|
|
17642
|
+
for (const key of Object.keys(options)) if (key !== "signal" && key !== "state" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported waitForSelector option: ${key}`);
|
|
17643
|
+
validateSignal("waitForSelector", options.signal);
|
|
17492
17644
|
if (!allowsStrict && "strict" in options) throw new Error("ElementHandle waitForSelector does not support strict");
|
|
17493
17645
|
if (options.state !== void 0 && ![
|
|
17494
17646
|
"attached",
|
|
@@ -17510,6 +17662,21 @@ function assertElementHandleStateOptions(state, options) {
|
|
|
17510
17662
|
for (const key of Object.keys(options)) if (key !== "timeout") throw new Error(`Unsupported waitForElementState option: ${key}`);
|
|
17511
17663
|
if (options.timeout !== void 0) validateTimeout(options.timeout, "waitForElementState timeout");
|
|
17512
17664
|
}
|
|
17665
|
+
/**
|
|
17666
|
+
* Pinned 26a9e47 client/frame.ts `verifyLoadState`: accepts the four lifecycle
|
|
17667
|
+
* events, keeps the `networkidle0` alias, and rejects anything else with the
|
|
17668
|
+
* client's wording before the navigation is requested.
|
|
17669
|
+
*/
|
|
17670
|
+
function verifyLoadState(name, waitUntil) {
|
|
17671
|
+
if (waitUntil === "networkidle0") waitUntil = "networkidle";
|
|
17672
|
+
if (![
|
|
17673
|
+
"load",
|
|
17674
|
+
"domcontentloaded",
|
|
17675
|
+
"networkidle",
|
|
17676
|
+
"commit"
|
|
17677
|
+
].includes(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
|
|
17678
|
+
return waitUntil;
|
|
17679
|
+
}
|
|
17513
17680
|
function isRetryableQueryError(error) {
|
|
17514
17681
|
const message = asError(error).message;
|
|
17515
17682
|
return message.startsWith("No elements found for locator") || message === "Element is not connected";
|
|
@@ -17525,8 +17692,24 @@ function presentOriginalXPath(error, selector) {
|
|
|
17525
17692
|
if (rewritten === source.message) return source;
|
|
17526
17693
|
return new Error(rewritten, { cause: source });
|
|
17527
17694
|
}
|
|
17528
|
-
function
|
|
17529
|
-
|
|
17695
|
+
function actionAborted(signal, inFlight) {
|
|
17696
|
+
const reason = abortReason(signal);
|
|
17697
|
+
const error = new Error(inFlight ? `${reason}\nCall log:\n - operation was aborted: ${reason}` : "The operation was aborted", { cause: signal.reason });
|
|
17698
|
+
error.name = "AbortError";
|
|
17699
|
+
return error;
|
|
17700
|
+
}
|
|
17701
|
+
async function withAbortPrefix(apiName, run) {
|
|
17702
|
+
try {
|
|
17703
|
+
return await run();
|
|
17704
|
+
} catch (error) {
|
|
17705
|
+
throw prefixAbortError(error, apiName);
|
|
17706
|
+
}
|
|
17707
|
+
}
|
|
17708
|
+
function prefixAbortError(error, apiName) {
|
|
17709
|
+
const result = asError(error);
|
|
17710
|
+
if (result.name !== "AbortError") return error;
|
|
17711
|
+
result.message = `${apiName}: ${result.message}`;
|
|
17712
|
+
return result;
|
|
17530
17713
|
}
|
|
17531
17714
|
function unknownKey(value) {
|
|
17532
17715
|
throw new Error(`Unknown key: "${value}"`);
|