feat(strict): introduce strict mode (#7851)

This commit is contained in:
Pavel Feldman 2021-07-26 22:00:23 -07:00 committed by GitHub
parent d370f65713
commit 0a6ae11da1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 720 additions and 239 deletions

View file

@ -195,14 +195,11 @@ When all steps combined have not finished during the specified [`option: timeout
### param: Frame.check.selector = %%-input-selector-%%
### option: Frame.check.position = %%-input-position-%%
### option: Frame.check.force = %%-input-force-%%
### option: Frame.check.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.check.position = %%-input-position-%%
### option: Frame.check.strict = %%-input-strict-%%
### option: Frame.check.timeout = %%-input-timeout-%%
### option: Frame.check.trial = %%-input-trial-%%
## method: Frame.childFrames
@ -225,21 +222,14 @@ When all steps combined have not finished during the specified [`option: timeout
### param: Frame.click.selector = %%-input-selector-%%
### option: Frame.click.button = %%-input-button-%%
### option: Frame.click.clickCount = %%-input-click-count-%%
### option: Frame.click.delay = %%-input-down-up-delay-%%
### option: Frame.click.position = %%-input-position-%%
### option: Frame.click.modifiers = %%-input-modifiers-%%
### option: Frame.click.force = %%-input-force-%%
### option: Frame.click.modifiers = %%-input-modifiers-%%
### option: Frame.click.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.click.position = %%-input-position-%%
### option: Frame.click.strict = %%-input-strict-%%
### option: Frame.click.timeout = %%-input-timeout-%%
### option: Frame.click.trial = %%-input-trial-%%
## async method: Frame.content
@ -271,19 +261,13 @@ When all steps combined have not finished during the specified [`option: timeout
### param: Frame.dblclick.selector = %%-input-selector-%%
### option: Frame.dblclick.button = %%-input-button-%%
### option: Frame.dblclick.delay = %%-input-down-up-delay-%%
### option: Frame.dblclick.position = %%-input-position-%%
### option: Frame.dblclick.modifiers = %%-input-modifiers-%%
### option: Frame.dblclick.force = %%-input-force-%%
### option: Frame.dblclick.delay = %%-input-down-up-delay-%%
### option: Frame.dblclick.modifiers = %%-input-modifiers-%%
### option: Frame.dblclick.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.dblclick.position = %%-input-position-%%
### option: Frame.dblclick.strict = %%-input-strict-%%
### option: Frame.dblclick.timeout = %%-input-timeout-%%
### option: Frame.dblclick.trial = %%-input-trial-%%
## async method: Frame.dispatchEvent
@ -372,6 +356,7 @@ DOM event type: `"click"`, `"dragstart"`, etc.
Optional event-specific initialization properties.
### option: Frame.dispatchEvent.strict = %%-input-strict-%%
### option: Frame.dispatchEvent.timeout = %%-input-timeout-%%
## async method: Frame.dragAndDrop
@ -381,11 +366,9 @@ Optional event-specific initialization properties.
### param: Frame.dragAndDrop.target = %%-input-target-%%
### option: Frame.dragAndDrop.force = %%-input-force-%%
### option: Frame.dragAndDrop.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.dragAndDrop.strict = %%-input-strict-%%
### option: Frame.dragAndDrop.timeout = %%-input-timeout-%%
### option: Frame.dragAndDrop.trial = %%-input-trial-%%
## async method: Frame.evalOnSelector
@ -436,14 +419,14 @@ var html = await frame.EvalOnSelectorAsync(".main-container", "(e, suffix) => e.
```
### param: Frame.evalOnSelector.selector = %%-query-selector-%%
### param: Frame.evalOnSelector.expression = %%-evaluate-expression-%%
### param: Frame.evalOnSelector.arg
- `arg` <[EvaluationArgument]>
Optional argument to pass to [`param: expression`].
### option: Frame.evalOnSelector.strict = %%-input-strict-%%
## async method: Frame.evalOnSelectorAll
* langs:
- alias-python: eval_on_selector_all
@ -482,7 +465,6 @@ var divsCount = await frame.EvalOnSelectorAllAsync<bool>("div", "(divs, min) =>
```
### param: Frame.evalOnSelectorAll.selector = %%-query-selector-%%
### param: Frame.evalOnSelectorAll.expression = %%-evaluate-expression-%%
### param: Frame.evalOnSelectorAll.arg
@ -724,6 +706,7 @@ This method fetches an element with [`param: selector`] and focuses it. If there
### param: Frame.focus.selector = %%-input-selector-%%
### option: Frame.focus.strict = %%-input-strict-%%
### option: Frame.focus.timeout = %%-input-timeout-%%
## async method: Frame.frameElement
@ -778,6 +761,7 @@ Returns element attribute value.
Attribute name to get the value for.
### option: Frame.getAttribute.strict = %%-input-strict-%%
### option: Frame.getAttribute.timeout = %%-input-timeout-%%
## async method: Frame.goto
@ -841,13 +825,10 @@ When all steps combined have not finished during the specified [`option: timeout
### param: Frame.hover.selector = %%-input-selector-%%
### option: Frame.hover.position = %%-input-position-%%
### option: Frame.hover.modifiers = %%-input-modifiers-%%
### option: Frame.hover.force = %%-input-force-%%
### option: Frame.hover.strict = %%-input-strict-%%
### option: Frame.hover.timeout = %%-input-timeout-%%
### option: Frame.hover.trial = %%-input-trial-%%
## async method: Frame.innerHTML
@ -857,6 +838,7 @@ Returns `element.innerHTML`.
### param: Frame.innerHTML.selector = %%-input-selector-%%
### option: Frame.innerHTML.strict = %%-input-strict-%%
### option: Frame.innerHTML.timeout = %%-input-timeout-%%
## async method: Frame.innerText
@ -866,6 +848,7 @@ Returns `element.innerText`.
### param: Frame.innerText.selector = %%-input-selector-%%
### option: Frame.innerText.strict = %%-input-strict-%%
### option: Frame.innerText.timeout = %%-input-timeout-%%
## async method: Frame.inputValue
@ -874,6 +857,8 @@ Returns `element.innerText`.
Returns `input.value` for the selected `<input>` or `<textarea>` element. Throws for non-input elements.
### param: Frame.inputValue.selector = %%-input-selector-%%
### option: Frame.inputValue.strict = %%-input-strict-%%
### option: Frame.inputValue.timeout = %%-input-timeout-%%
## async method: Frame.isChecked
@ -883,6 +868,7 @@ Returns whether the element is checked. Throws if the element is not a checkbox
### param: Frame.isChecked.selector = %%-input-selector-%%
### option: Frame.isChecked.strict = %%-input-strict-%%
### option: Frame.isChecked.timeout = %%-input-timeout-%%
## method: Frame.isDetached
@ -897,6 +883,7 @@ Returns whether the element is disabled, the opposite of [enabled](./actionabili
### param: Frame.isDisabled.selector = %%-input-selector-%%
### option: Frame.isDisabled.strict = %%-input-strict-%%
### option: Frame.isDisabled.timeout = %%-input-timeout-%%
## async method: Frame.isEditable
@ -906,6 +893,7 @@ Returns whether the element is [editable](./actionability.md#editable).
### param: Frame.isEditable.selector = %%-input-selector-%%
### option: Frame.isEditable.strict = %%-input-strict-%%
### option: Frame.isEditable.timeout = %%-input-timeout-%%
## async method: Frame.isEnabled
@ -915,6 +903,7 @@ Returns whether the element is [enabled](./actionability.md#enabled).
### param: Frame.isEnabled.selector = %%-input-selector-%%
### option: Frame.isEnabled.strict = %%-input-strict-%%
### option: Frame.isEnabled.timeout = %%-input-timeout-%%
## async method: Frame.isHidden
@ -924,6 +913,7 @@ Returns whether the element is hidden, the opposite of [visible](./actionability
### param: Frame.isHidden.selector = %%-input-selector-%%
### option: Frame.isHidden.strict = %%-input-strict-%%
### option: Frame.isHidden.timeout = %%-input-timeout-%%
## async method: Frame.isVisible
@ -933,6 +923,7 @@ Returns whether the element is [visible](./actionability.md#visible). [`option:
### param: Frame.isVisible.selector = %%-input-selector-%%
### option: Frame.isVisible.strict = %%-input-strict-%%
### option: Frame.isVisible.timeout = %%-input-timeout-%%
## method: Frame.locator
@ -999,7 +990,7 @@ Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
### option: Frame.press.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.press.strict = %%-input-strict-%%
### option: Frame.press.timeout = %%-input-timeout-%%
## async method: Frame.querySelector
@ -1016,6 +1007,8 @@ returns `null`.
### param: Frame.querySelector.selector = %%-query-selector-%%
### option: Frame.querySelector.strict = %%-input-strict-%%
## async method: Frame.querySelectorAll
* langs:
- alias-python: query_selector_all
@ -1092,6 +1085,7 @@ await frame.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" })
### param: Frame.selectOption.values = %%-select-options-values-%%
### option: Frame.selectOption.force = %%-input-force-%%
### option: Frame.selectOption.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.selectOption.strict = %%-input-strict-%%
### option: Frame.selectOption.timeout = %%-input-timeout-%%
## async method: Frame.setContent
@ -1114,11 +1108,9 @@ Sets the value of the file input to these file paths or files. If some of the `f
are resolved relative to the the current working directory. For empty array, clears the selected files.
### param: Frame.setInputFiles.selector = %%-input-selector-%%
### param: Frame.setInputFiles.files = %%-input-files-%%
### option: Frame.setInputFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.setInputFiles.strict = %%-input-strict-%%
### option: Frame.setInputFiles.timeout = %%-input-timeout-%%
## async method: Frame.tap
@ -1141,16 +1133,12 @@ When all steps combined have not finished during the specified [`option: timeout
### param: Frame.tap.selector = %%-input-selector-%%
### option: Frame.tap.position = %%-input-position-%%
### option: Frame.tap.modifiers = %%-input-modifiers-%%
### option: Frame.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.tap.force = %%-input-force-%%
### option: Frame.tap.modifiers = %%-input-modifiers-%%
### option: Frame.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.tap.position = %%-input-position-%%
### option: Frame.tap.strict = %%-input-strict-%%
### option: Frame.tap.timeout = %%-input-timeout-%%
### option: Frame.tap.trial = %%-input-trial-%%
## async method: Frame.textContent
@ -1160,6 +1148,7 @@ Returns `element.textContent`.
### param: Frame.textContent.selector = %%-input-selector-%%
### option: Frame.textContent.strict = %%-input-strict-%%
### option: Frame.textContent.timeout = %%-input-timeout-%%
## async method: Frame.title
@ -1214,7 +1203,7 @@ A text to type into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: Frame.type.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.type.strict = %%-input-strict-%%
### option: Frame.type.timeout = %%-input-timeout-%%
## async method: Frame.uncheck
@ -1236,14 +1225,11 @@ When all steps combined have not finished during the specified [`option: timeout
### param: Frame.uncheck.selector = %%-input-selector-%%
### option: Frame.uncheck.position = %%-input-position-%%
### option: Frame.uncheck.force = %%-input-force-%%
### option: Frame.uncheck.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.uncheck.position = %%-input-position-%%
### option: Frame.uncheck.strict = %%-input-strict-%%
### option: Frame.uncheck.timeout = %%-input-timeout-%%
### option: Frame.uncheck.trial = %%-input-trial-%%
## method: Frame.url
@ -1584,9 +1570,8 @@ class FrameExamples
```
### param: Frame.waitForSelector.selector = %%-query-selector-%%
### option: Frame.waitForSelector.state = %%-wait-for-selector-state-%%
### option: Frame.waitForSelector.strict = %%-input-strict-%%
### option: Frame.waitForSelector.timeout = %%-input-timeout-%%
## async method: Frame.waitForTimeout

View file

@ -599,14 +599,11 @@ Shortcut for main frame's [`method: Frame.check`].
### param: Page.check.selector = %%-input-selector-%%
### option: Page.check.position = %%-input-position-%%
### option: Page.check.force = %%-input-force-%%
### option: Page.check.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.check.position = %%-input-position-%%
### option: Page.check.strict = %%-input-strict-%%
### option: Page.check.timeout = %%-input-timeout-%%
### option: Page.check.trial = %%-input-trial-%%
## async method: Page.click
@ -628,21 +625,14 @@ Shortcut for main frame's [`method: Frame.click`].
### param: Page.click.selector = %%-input-selector-%%
### option: Page.click.button = %%-input-button-%%
### option: Page.click.clickCount = %%-input-click-count-%%
### option: Page.click.delay = %%-input-down-up-delay-%%
### option: Page.click.position = %%-input-position-%%
### option: Page.click.modifiers = %%-input-modifiers-%%
### option: Page.click.force = %%-input-force-%%
### option: Page.click.modifiers = %%-input-modifiers-%%
### option: Page.click.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.click.position = %%-input-position-%%
### option: Page.click.strict = %%-input-strict-%%
### option: Page.click.timeout = %%-input-timeout-%%
### option: Page.click.trial = %%-input-trial-%%
## async method: Page.close
@ -709,19 +699,13 @@ Shortcut for main frame's [`method: Frame.dblclick`].
### param: Page.dblclick.selector = %%-input-selector-%%
### option: Page.dblclick.button = %%-input-button-%%
### option: Page.dblclick.delay = %%-input-down-up-delay-%%
### option: Page.dblclick.position = %%-input-position-%%
### option: Page.dblclick.modifiers = %%-input-modifiers-%%
### option: Page.dblclick.force = %%-input-force-%%
### option: Page.dblclick.delay = %%-input-down-up-delay-%%
### option: Page.dblclick.modifiers = %%-input-modifiers-%%
### option: Page.dblclick.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.dblclick.position = %%-input-position-%%
### option: Page.dblclick.strict = %%-input-strict-%%
### option: Page.dblclick.timeout = %%-input-timeout-%%
### option: Page.dblclick.trial = %%-input-trial-%%
## async method: Page.dispatchEvent
@ -809,20 +793,18 @@ DOM event type: `"click"`, `"dragstart"`, etc.
Optional event-specific initialization properties.
### option: Page.dispatchEvent.strict = %%-input-strict-%%
### option: Page.dispatchEvent.timeout = %%-input-timeout-%%
## async method: Page.dragAndDrop
### param: Page.dragAndDrop.source = %%-input-source-%%
### param: Page.dragAndDrop.target = %%-input-target-%%
### option: Page.dragAndDrop.force = %%-input-force-%%
### option: Page.dragAndDrop.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.dragAndDrop.strict = %%-input-strict-%%
### option: Page.dragAndDrop.timeout = %%-input-timeout-%%
### option: Page.dragAndDrop.trial = %%-input-trial-%%
## async method: Page.emulateMedia
@ -1063,14 +1045,14 @@ var html = await page.EvalOnSelectorAsync(".main-container", "(e, suffix) => e.o
Shortcut for main frame's [`method: Frame.evalOnSelector`].
### param: Page.evalOnSelector.selector = %%-query-selector-%%
### param: Page.evalOnSelector.expression = %%-evaluate-expression-%%
### param: Page.evalOnSelector.arg
- `arg` <[EvaluationArgument]>
Optional argument to pass to [`param: expression`].
### option: Page.evalOnSelector.strict = %%-input-strict-%%
## async method: Page.evalOnSelectorAll
* langs:
- alias-python: eval_on_selector_all
@ -1106,9 +1088,7 @@ var divsCount = await page.EvalOnSelectorAllAsync<bool>("div", "(divs, min) => d
```
### param: Page.evalOnSelectorAll.selector = %%-query-selector-%%
### param: Page.evalOnSelectorAll.expression = %%-evaluate-expression-%%
### param: Page.evalOnSelectorAll.arg
- `arg` <[EvaluationArgument]>
@ -1762,6 +1742,7 @@ Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
### option: Page.fill.force = %%-input-force-%%
### option: Page.fill.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.fill.strict = %%-input-strict-%%
### option: Page.fill.timeout = %%-input-timeout-%%
## async method: Page.focus
@ -1773,6 +1754,7 @@ Shortcut for main frame's [`method: Frame.focus`].
### param: Page.focus.selector = %%-input-selector-%%
### option: Page.focus.strict = %%-input-strict-%%
### option: Page.focus.timeout = %%-input-timeout-%%
## method: Page.frame
@ -1856,6 +1838,7 @@ Returns element attribute value.
Attribute name to get the value for.
### option: Page.getAttribute.strict = %%-input-strict-%%
### option: Page.getAttribute.timeout = %%-input-timeout-%%
## async method: Page.goBack
@ -1948,14 +1931,11 @@ Shortcut for main frame's [`method: Frame.hover`].
### param: Page.hover.selector = %%-input-selector-%%
### option: Page.hover.position = %%-input-position-%%
### option: Page.hover.modifiers = %%-input-modifiers-%%
### option: Page.hover.force = %%-input-force-%%
### option: Page.hover.modifiers = %%-input-modifiers-%%
### option: Page.hover.position = %%-input-position-%%
### option: Page.hover.strict = %%-input-strict-%%
### option: Page.hover.timeout = %%-input-timeout-%%
### option: Page.hover.trial = %%-input-trial-%%
## async method: Page.innerHTML
@ -1965,6 +1945,7 @@ Returns `element.innerHTML`.
### param: Page.innerHTML.selector = %%-input-selector-%%
### option: Page.innerHTML.strict = %%-input-strict-%%
### option: Page.innerHTML.timeout = %%-input-timeout-%%
## async method: Page.innerText
@ -1974,6 +1955,7 @@ Returns `element.innerText`.
### param: Page.innerText.selector = %%-input-selector-%%
### option: Page.innerText.strict = %%-input-strict-%%
### option: Page.innerText.timeout = %%-input-timeout-%%
## async method: Page.inputValue
@ -1982,6 +1964,8 @@ Returns `element.innerText`.
Returns `input.value` for the selected `<input>` or `<textarea>` element. Throws for non-input elements.
### param: Page.inputValue.selector = %%-input-selector-%%
### option: Page.inputValue.strict = %%-input-strict-%%
### option: Page.inputValue.timeout = %%-input-timeout-%%
## async method: Page.isChecked
@ -1991,6 +1975,8 @@ Returns whether the element is checked. Throws if the element is not a checkbox
### param: Page.isChecked.selector = %%-input-selector-%%
### option: Page.isChecked.strict = %%-input-strict-%%
### option: Page.isChecked.timeout = %%-input-timeout-%%
## method: Page.isClosed
@ -2005,6 +1991,7 @@ Returns whether the element is disabled, the opposite of [enabled](./actionabili
### param: Page.isDisabled.selector = %%-input-selector-%%
### option: Page.isDisabled.strict = %%-input-strict-%%
### option: Page.isDisabled.timeout = %%-input-timeout-%%
## async method: Page.isEditable
@ -2014,6 +2001,7 @@ Returns whether the element is [editable](./actionability.md#editable).
### param: Page.isEditable.selector = %%-input-selector-%%
### option: Page.isEditable.strict = %%-input-strict-%%
### option: Page.isEditable.timeout = %%-input-timeout-%%
## async method: Page.isEnabled
@ -2023,6 +2011,7 @@ Returns whether the element is [enabled](./actionability.md#enabled).
### param: Page.isEnabled.selector = %%-input-selector-%%
### option: Page.isEnabled.strict = %%-input-strict-%%
### option: Page.isEnabled.timeout = %%-input-timeout-%%
## async method: Page.isHidden
@ -2032,6 +2021,7 @@ Returns whether the element is hidden, the opposite of [visible](./actionability
### param: Page.isHidden.selector = %%-input-selector-%%
### option: Page.isHidden.strict = %%-input-strict-%%
### option: Page.isHidden.timeout = %%-input-timeout-%%
## async method: Page.isVisible
@ -2041,6 +2031,7 @@ Returns whether the element is [visible](./actionability.md#visible). [`option:
### param: Page.isVisible.selector = %%-input-selector-%%
### option: Page.isVisible.strict = %%-input-strict-%%
### option: Page.isVisible.timeout = %%-input-timeout-%%
## property: Page.keyboard
@ -2360,7 +2351,7 @@ Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
### option: Page.press.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.press.strict = %%-input-strict-%%
### option: Page.press.timeout = %%-input-timeout-%%
## async method: Page.querySelector
@ -2376,6 +2367,8 @@ Shortcut for main frame's [`method: Frame.querySelector`].
### param: Page.querySelector.selector = %%-query-selector-%%
### option: Page.querySelector.strict = %%-input-strict-%%
## async method: Page.querySelectorAll
* langs:
- alias-python: query_selector_all
@ -2663,6 +2656,7 @@ Shortcut for main frame's [`method: Frame.selectOption`].
### param: Page.selectOption.values = %%-select-options-values-%%
### option: Page.selectOption.force = %%-input-force-%%
### option: Page.selectOption.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.selectOption.strict = %%-input-strict-%%
### option: Page.selectOption.timeout = %%-input-timeout-%%
## async method: Page.setContent
@ -2736,7 +2730,7 @@ are resolved relative to the the current working directory. For empty array, cle
### param: Page.setInputFiles.files = %%-input-files-%%
### option: Page.setInputFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.setInputFiles.strict = %%-input-strict-%%
### option: Page.setInputFiles.timeout = %%-input-timeout-%%
## async method: Page.setViewportSize
@ -2816,16 +2810,12 @@ Shortcut for main frame's [`method: Frame.tap`].
### param: Page.tap.selector = %%-input-selector-%%
### option: Page.tap.position = %%-input-position-%%
### option: Page.tap.modifiers = %%-input-modifiers-%%
### option: Page.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.tap.force = %%-input-force-%%
### option: Page.tap.modifiers = %%-input-modifiers-%%
### option: Page.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.tap.position = %%-input-position-%%
### option: Page.tap.strict = %%-input-strict-%%
### option: Page.tap.timeout = %%-input-timeout-%%
### option: Page.tap.trial = %%-input-trial-%%
## async method: Page.textContent
@ -2835,6 +2825,7 @@ Returns `element.textContent`.
### param: Page.textContent.selector = %%-input-selector-%%
### option: Page.textContent.strict = %%-input-strict-%%
### option: Page.textContent.timeout = %%-input-timeout-%%
## async method: Page.title
@ -2894,7 +2885,7 @@ A text to type into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: Page.type.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.type.strict = %%-input-strict-%%
### option: Page.type.timeout = %%-input-timeout-%%
## async method: Page.uncheck
@ -2918,14 +2909,11 @@ Shortcut for main frame's [`method: Frame.uncheck`].
### param: Page.uncheck.selector = %%-input-selector-%%
### option: Page.uncheck.position = %%-input-position-%%
### option: Page.uncheck.force = %%-input-force-%%
### option: Page.uncheck.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.uncheck.position = %%-input-position-%%
### option: Page.uncheck.strict = %%-input-strict-%%
### option: Page.uncheck.timeout = %%-input-timeout-%%
### option: Page.uncheck.trial = %%-input-trial-%%
## async method: Page.unroute
@ -3687,6 +3675,7 @@ class FrameExamples
### param: Page.waitForSelector.selector = %%-query-selector-%%
### option: Page.waitForSelector.state = %%-wait-for-selector-state-%%
### option: Page.waitForSelector.strict = %%-input-strict-%%
### option: Page.waitForSelector.timeout = %%-input-timeout-%%
## async method: Page.waitForTimeout

View file

@ -22,6 +22,12 @@ The default value can be changed by using the
maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default
value can be changed by using the [`method: BrowserContext.setDefaultTimeout`].
## input-strict
- `strict` <[boolean]>
When true, the call requires selector to resolve to a single element. If given selector resolves to more
then one element, the call throws an exception.
## input-timeout
- `timeout` <[float]>

View file

@ -183,9 +183,9 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
});
}
async $(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
async $(selector: string, options?: { strict?: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
return this._wrapApiCall(async (channel: channels.FrameChannel) => {
const result = await channel.querySelector({ selector });
const result = await channel.querySelector({ selector, ...options });
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
});
}

View file

@ -250,8 +250,8 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
return this._forceVideo();
}
async $(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
return this._mainFrame.$(selector);
async $(selector: string, options?: { strict?: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
return this._mainFrame.$(selector, options);
}
waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;

View file

@ -173,17 +173,17 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements chann
}
async querySelector(params: channels.ElementHandleQuerySelectorParams, metadata: CallMetadata): Promise<channels.ElementHandleQuerySelectorResult> {
const handle = await this._elementHandle.$(params.selector);
const handle = await this._elementHandle.querySelector(params.selector, params);
return { element: ElementHandleDispatcher.fromNullable(this._scope, handle) };
}
async querySelectorAll(params: channels.ElementHandleQuerySelectorAllParams, metadata: CallMetadata): Promise<channels.ElementHandleQuerySelectorAllResult> {
const elements = await this._elementHandle.$$(params.selector);
const elements = await this._elementHandle.querySelectorAll(params.selector);
return { elements: elements.map(e => ElementHandleDispatcher.from(this._scope, e)) };
}
async evalOnSelector(params: channels.ElementHandleEvalOnSelectorParams, metadata: CallMetadata): Promise<channels.ElementHandleEvalOnSelectorResult> {
return { value: serializeResult(await this._elementHandle.evalOnSelectorAndWaitForSignals(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) };
return { value: serializeResult(await this._elementHandle.evalOnSelectorAndWaitForSignals(params.selector, !!params.strict, params.expression, params.isFunction, parseArgument(params.arg))) };
}
async evalOnSelectorAll(params: channels.ElementHandleEvalOnSelectorAllParams, metadata: CallMetadata): Promise<channels.ElementHandleEvalOnSelectorAllResult> {

View file

@ -83,7 +83,7 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameInitializer
}
async evalOnSelector(params: channels.FrameEvalOnSelectorParams, metadata: CallMetadata): Promise<channels.FrameEvalOnSelectorResult> {
return { value: serializeResult(await this._frame.evalOnSelectorAndWaitForSignals(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) };
return { value: serializeResult(await this._frame.evalOnSelectorAndWaitForSignals(params.selector, !!params.strict, params.expression, params.isFunction, parseArgument(params.arg))) };
}
async evalOnSelectorAll(params: channels.FrameEvalOnSelectorAllParams, metadata: CallMetadata): Promise<channels.FrameEvalOnSelectorAllResult> {
@ -91,7 +91,7 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameInitializer
}
async querySelector(params: channels.FrameQuerySelectorParams, metadata: CallMetadata): Promise<channels.FrameQuerySelectorResult> {
return { element: ElementHandleDispatcher.fromNullable(this._scope, await this._frame.querySelector(params.selector)) };
return { element: ElementHandleDispatcher.fromNullable(this._scope, await this._frame.querySelector(params.selector, params)) };
}
async querySelectorAll(params: channels.FrameQuerySelectorAllParams, metadata: CallMetadata): Promise<channels.FrameQuerySelectorAllResult> {

View file

@ -1358,11 +1358,13 @@ export type FrameNavigatedEvent = {
};
export type FrameEvalOnSelectorParams = {
selector: string,
strict?: boolean,
expression: string,
isFunction?: boolean,
arg: SerializedArgument,
};
export type FrameEvalOnSelectorOptions = {
strict?: boolean,
isFunction?: boolean,
};
export type FrameEvalOnSelectorResult = {
@ -1406,6 +1408,7 @@ export type FrameAddStyleTagResult = {
};
export type FrameCheckParams = {
selector: string,
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
position?: Point,
@ -1413,6 +1416,7 @@ export type FrameCheckParams = {
trial?: boolean,
};
export type FrameCheckOptions = {
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
position?: Point,
@ -1422,6 +1426,7 @@ export type FrameCheckOptions = {
export type FrameCheckResult = void;
export type FrameClickParams = {
selector: string,
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
@ -1433,6 +1438,7 @@ export type FrameClickParams = {
trial?: boolean,
};
export type FrameClickOptions = {
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
@ -1466,6 +1472,7 @@ export type FrameDragAndDropOptions = {
export type FrameDragAndDropResult = void;
export type FrameDblclickParams = {
selector: string,
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
@ -1476,6 +1483,7 @@ export type FrameDblclickParams = {
trial?: boolean,
};
export type FrameDblclickOptions = {
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
@ -1488,11 +1496,13 @@ export type FrameDblclickOptions = {
export type FrameDblclickResult = void;
export type FrameDispatchEventParams = {
selector: string,
strict?: boolean,
type: string,
eventInit: SerializedArgument,
timeout?: number,
};
export type FrameDispatchEventOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameDispatchEventResult = void;
@ -1520,12 +1530,14 @@ export type FrameEvaluateExpressionHandleResult = {
};
export type FrameFillParams = {
selector: string,
strict?: boolean,
value: string,
force?: boolean,
timeout?: number,
noWaitAfter?: boolean,
};
export type FrameFillOptions = {
strict?: boolean,
force?: boolean,
timeout?: number,
noWaitAfter?: boolean,
@ -1533,9 +1545,11 @@ export type FrameFillOptions = {
export type FrameFillResult = void;
export type FrameFocusParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameFocusOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameFocusResult = void;
@ -1546,10 +1560,12 @@ export type FrameFrameElementResult = {
};
export type FrameGetAttributeParams = {
selector: string,
strict?: boolean,
name: string,
timeout?: number,
};
export type FrameGetAttributeOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameGetAttributeResult = {
@ -1571,6 +1587,7 @@ export type FrameGotoResult = {
};
export type FrameHoverParams = {
selector: string,
strict?: boolean,
force?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
position?: Point,
@ -1578,6 +1595,7 @@ export type FrameHoverParams = {
trial?: boolean,
};
export type FrameHoverOptions = {
strict?: boolean,
force?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
position?: Point,
@ -1587,9 +1605,11 @@ export type FrameHoverOptions = {
export type FrameHoverResult = void;
export type FrameInnerHTMLParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameInnerHTMLOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameInnerHTMLResult = {
@ -1597,9 +1617,11 @@ export type FrameInnerHTMLResult = {
};
export type FrameInnerTextParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameInnerTextOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameInnerTextResult = {
@ -1607,9 +1629,11 @@ export type FrameInnerTextResult = {
};
export type FrameInputValueParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameInputValueOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameInputValueResult = {
@ -1617,9 +1641,11 @@ export type FrameInputValueResult = {
};
export type FrameIsCheckedParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameIsCheckedOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameIsCheckedResult = {
@ -1627,9 +1653,11 @@ export type FrameIsCheckedResult = {
};
export type FrameIsDisabledParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameIsDisabledOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameIsDisabledResult = {
@ -1637,9 +1665,11 @@ export type FrameIsDisabledResult = {
};
export type FrameIsEnabledParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameIsEnabledOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameIsEnabledResult = {
@ -1647,9 +1677,11 @@ export type FrameIsEnabledResult = {
};
export type FrameIsHiddenParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameIsHiddenOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameIsHiddenResult = {
@ -1657,9 +1689,11 @@ export type FrameIsHiddenResult = {
};
export type FrameIsVisibleParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameIsVisibleOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameIsVisibleResult = {
@ -1667,9 +1701,11 @@ export type FrameIsVisibleResult = {
};
export type FrameIsEditableParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameIsEditableOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameIsEditableResult = {
@ -1677,12 +1713,14 @@ export type FrameIsEditableResult = {
};
export type FramePressParams = {
selector: string,
strict?: boolean,
key: string,
delay?: number,
noWaitAfter?: boolean,
timeout?: number,
};
export type FramePressOptions = {
strict?: boolean,
delay?: number,
noWaitAfter?: boolean,
timeout?: number,
@ -1690,24 +1728,27 @@ export type FramePressOptions = {
export type FramePressResult = void;
export type FrameQuerySelectorParams = {
selector: string,
strict?: boolean,
};
export type FrameQuerySelectorOptions = {
strict?: boolean,
};
export type FrameQuerySelectorResult = {
element?: ElementHandleChannel,
};
export type FrameQuerySelectorAllParams = {
selector: string,
strict?: boolean,
};
export type FrameQuerySelectorAllOptions = {
strict?: boolean,
};
export type FrameQuerySelectorAllResult = {
elements: ElementHandleChannel[],
};
export type FrameSelectOptionParams = {
selector: string,
strict?: boolean,
elements?: ElementHandleChannel[],
options?: {
value?: string,
@ -1719,6 +1760,7 @@ export type FrameSelectOptionParams = {
noWaitAfter?: boolean,
};
export type FrameSelectOptionOptions = {
strict?: boolean,
elements?: ElementHandleChannel[],
options?: {
value?: string,
@ -1744,6 +1786,7 @@ export type FrameSetContentOptions = {
export type FrameSetContentResult = void;
export type FrameSetInputFilesParams = {
selector: string,
strict?: boolean,
files: {
name: string,
mimeType?: string,
@ -1753,12 +1796,14 @@ export type FrameSetInputFilesParams = {
noWaitAfter?: boolean,
};
export type FrameSetInputFilesOptions = {
strict?: boolean,
timeout?: number,
noWaitAfter?: boolean,
};
export type FrameSetInputFilesResult = void;
export type FrameTapParams = {
selector: string,
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
@ -1767,6 +1812,7 @@ export type FrameTapParams = {
trial?: boolean,
};
export type FrameTapOptions = {
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[],
@ -1777,9 +1823,11 @@ export type FrameTapOptions = {
export type FrameTapResult = void;
export type FrameTextContentParams = {
selector: string,
strict?: boolean,
timeout?: number,
};
export type FrameTextContentOptions = {
strict?: boolean,
timeout?: number,
};
export type FrameTextContentResult = {
@ -1792,12 +1840,14 @@ export type FrameTitleResult = {
};
export type FrameTypeParams = {
selector: string,
strict?: boolean,
text: string,
delay?: number,
noWaitAfter?: boolean,
timeout?: number,
};
export type FrameTypeOptions = {
strict?: boolean,
delay?: number,
noWaitAfter?: boolean,
timeout?: number,
@ -1805,6 +1855,7 @@ export type FrameTypeOptions = {
export type FrameTypeResult = void;
export type FrameUncheckParams = {
selector: string,
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
position?: Point,
@ -1812,6 +1863,7 @@ export type FrameUncheckParams = {
trial?: boolean,
};
export type FrameUncheckOptions = {
strict?: boolean,
force?: boolean,
noWaitAfter?: boolean,
position?: Point,
@ -1836,10 +1888,12 @@ export type FrameWaitForFunctionResult = {
};
export type FrameWaitForSelectorParams = {
selector: string,
strict?: boolean,
timeout?: number,
state?: 'attached' | 'detached' | 'visible' | 'hidden',
};
export type FrameWaitForSelectorOptions = {
strict?: boolean,
timeout?: number,
state?: 'attached' | 'detached' | 'visible' | 'hidden',
};
@ -1986,11 +2040,13 @@ export interface ElementHandleChannel extends JSHandleChannel {
}
export type ElementHandleEvalOnSelectorParams = {
selector: string,
strict?: boolean,
expression: string,
isFunction?: boolean,
arg: SerializedArgument,
};
export type ElementHandleEvalOnSelectorOptions = {
strict?: boolean,
isFunction?: boolean,
};
export type ElementHandleEvalOnSelectorResult = {
@ -2188,9 +2244,10 @@ export type ElementHandlePressOptions = {
export type ElementHandlePressResult = void;
export type ElementHandleQuerySelectorParams = {
selector: string,
strict?: boolean,
};
export type ElementHandleQuerySelectorOptions = {
strict?: boolean,
};
export type ElementHandleQuerySelectorResult = {
element?: ElementHandleChannel,
@ -2333,10 +2390,12 @@ export type ElementHandleWaitForElementStateOptions = {
export type ElementHandleWaitForElementStateResult = void;
export type ElementHandleWaitForSelectorParams = {
selector: string,
strict?: boolean,
timeout?: number,
state?: 'attached' | 'detached' | 'visible' | 'hidden',
};
export type ElementHandleWaitForSelectorOptions = {
strict?: boolean,
timeout?: number,
state?: 'attached' | 'detached' | 'visible' | 'hidden',
};

View file

@ -1096,6 +1096,7 @@ Frame:
evalOnSelector:
parameters:
selector: string
strict: boolean?
expression: string
isFunction: boolean?
arg: SerializedArgument
@ -1137,6 +1138,7 @@ Frame:
check:
parameters:
selector: string
strict: boolean?
force: boolean?
noWaitAfter: boolean?
position: Point?
@ -1148,6 +1150,7 @@ Frame:
click:
parameters:
selector: string
strict: boolean?
force: boolean?
noWaitAfter: boolean?
modifiers:
@ -1189,6 +1192,7 @@ Frame:
dblclick:
parameters:
selector: string
strict: boolean?
force: boolean?
noWaitAfter: boolean?
modifiers:
@ -1216,6 +1220,7 @@ Frame:
dispatchEvent:
parameters:
selector: string
strict: boolean?
type: string
eventInit: SerializedArgument
timeout: number?
@ -1245,6 +1250,7 @@ Frame:
fill:
parameters:
selector: string
strict: boolean?
value: string
force: boolean?
timeout: number?
@ -1255,6 +1261,7 @@ Frame:
focus:
parameters:
selector: string
strict: boolean?
timeout: number?
tracing:
snapshot: true
@ -1266,6 +1273,7 @@ Frame:
getAttribute:
parameters:
selector: string
strict: boolean?
name: string
timeout: number?
returns:
@ -1292,6 +1300,7 @@ Frame:
hover:
parameters:
selector: string
strict: boolean?
force: boolean?
modifiers:
type: array?
@ -1311,6 +1320,7 @@ Frame:
innerHTML:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: string
@ -1320,6 +1330,7 @@ Frame:
innerText:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: string
@ -1329,6 +1340,7 @@ Frame:
inputValue:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: string
@ -1338,6 +1350,7 @@ Frame:
isChecked:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: boolean
@ -1347,6 +1360,7 @@ Frame:
isDisabled:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: boolean
@ -1356,6 +1370,7 @@ Frame:
isEnabled:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: boolean
@ -1365,6 +1380,7 @@ Frame:
isHidden:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: boolean
@ -1374,6 +1390,7 @@ Frame:
isVisible:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: boolean
@ -1381,6 +1398,7 @@ Frame:
isEditable:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: boolean
@ -1390,6 +1408,7 @@ Frame:
press:
parameters:
selector: string
strict: boolean?
key: string
delay: number?
noWaitAfter: boolean?
@ -1400,12 +1419,14 @@ Frame:
querySelector:
parameters:
selector: string
strict: boolean?
returns:
element: ElementHandle?
querySelectorAll:
parameters:
selector: string
strict: boolean?
returns:
elements:
type: array
@ -1414,6 +1435,7 @@ Frame:
selectOption:
parameters:
selector: string
strict: boolean?
elements:
type: array?
items: ElementHandle
@ -1451,6 +1473,7 @@ Frame:
setInputFiles:
parameters:
selector: string
strict: boolean?
files:
type: array
items:
@ -1467,6 +1490,7 @@ Frame:
tap:
parameters:
selector: string
strict: boolean?
force: boolean?
noWaitAfter: boolean?
modifiers:
@ -1487,6 +1511,7 @@ Frame:
textContent:
parameters:
selector: string
strict: boolean?
timeout: number?
returns:
value: string?
@ -1500,6 +1525,7 @@ Frame:
type:
parameters:
selector: string
strict: boolean?
text: string
delay: number?
noWaitAfter: boolean?
@ -1510,6 +1536,7 @@ Frame:
uncheck:
parameters:
selector: string
strict: boolean?
force: boolean?
noWaitAfter: boolean?
position: Point?
@ -1534,6 +1561,7 @@ Frame:
waitForSelector:
parameters:
selector: string
strict: boolean?
timeout: number?
state:
type: enum?
@ -1673,6 +1701,7 @@ ElementHandle:
evalOnSelector:
parameters:
selector: string
strict: boolean?
expression: string
isFunction: boolean?
arg: SerializedArgument
@ -1857,6 +1886,7 @@ ElementHandle:
querySelector:
parameters:
selector: string
strict: boolean?
returns:
element: ElementHandle?
@ -1992,6 +2022,7 @@ ElementHandle:
waitForSelector:
parameters:
selector: string
strict: boolean?
timeout: number?
state:
type: enum?

View file

@ -547,6 +547,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
scheme.PageBringToFrontParams = tOptional(tObject({}));
scheme.FrameEvalOnSelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
expression: tString,
isFunction: tOptional(tBoolean),
arg: tType('SerializedArgument'),
@ -568,6 +569,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameCheckParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
position: tOptional(tType('Point')),
@ -576,6 +578,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameClickParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
@ -597,6 +600,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameDblclickParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
@ -608,6 +612,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameDispatchEventParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
type: tString,
eventInit: tType('SerializedArgument'),
timeout: tOptional(tNumber),
@ -624,6 +629,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameFillParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
value: tString,
force: tOptional(tBoolean),
timeout: tOptional(tNumber),
@ -631,11 +637,13 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameFocusParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameFrameElementParams = tOptional(tObject({}));
scheme.FrameGetAttributeParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
name: tString,
timeout: tOptional(tNumber),
});
@ -647,6 +655,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameHoverParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
@ -655,42 +664,52 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameInnerHTMLParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameInnerTextParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameInputValueParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameIsCheckedParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameIsDisabledParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameIsEnabledParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameIsHiddenParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameIsVisibleParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameIsEditableParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FramePressParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
key: tString,
delay: tOptional(tNumber),
noWaitAfter: tOptional(tBoolean),
@ -698,12 +717,15 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameQuerySelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
});
scheme.FrameQuerySelectorAllParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
});
scheme.FrameSelectOptionParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
elements: tOptional(tArray(tChannel('ElementHandle'))),
options: tOptional(tArray(tObject({
value: tOptional(tString),
@ -721,6 +743,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameSetInputFilesParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
files: tArray(tObject({
name: tString,
mimeType: tOptional(tString),
@ -731,6 +754,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameTapParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'Meta', 'Shift']))),
@ -740,11 +764,13 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameTextContentParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameTitleParams = tOptional(tObject({}));
scheme.FrameTypeParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
text: tString,
delay: tOptional(tNumber),
noWaitAfter: tOptional(tBoolean),
@ -752,6 +778,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameUncheckParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
noWaitAfter: tOptional(tBoolean),
position: tOptional(tType('Point')),
@ -767,6 +794,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.FrameWaitForSelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
});
@ -804,6 +832,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
scheme.ElementHandleJsonValueParams = tType('JSHandleJsonValueParams');
scheme.ElementHandleEvalOnSelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
expression: tString,
isFunction: tOptional(tBoolean),
arg: tType('SerializedArgument'),
@ -883,6 +912,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.ElementHandleQuerySelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
});
scheme.ElementHandleQuerySelectorAllParams = tObject({
selector: tString,
@ -948,6 +978,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
});
scheme.ElementHandleWaitForSelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
timeout: tOptional(tNumber),
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
});

View file

@ -673,16 +673,16 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
this._page._timeoutSettings.timeout(options));
}
async $(selector: string): Promise<ElementHandle | null> {
return this._page.selectors._query(this._context.frame, selector, this);
async querySelector(selector: string, options: types.StrictOptions): Promise<ElementHandle | null> {
return this._page.selectors._query(this._context.frame, selector, !!options.strict, this);
}
async $$(selector: string): Promise<ElementHandle<Element>[]> {
async querySelectorAll(selector: string): Promise<ElementHandle<Element>[]> {
return this._page.selectors._queryAll(this._context.frame, selector, this, true /* adoptToMain */);
}
async evalOnSelectorAndWaitForSignals(selector: string, expression: string, isFunction: boolean | undefined, arg: any): Promise<any> {
const handle = await this._page.selectors._query(this._context.frame, selector, this);
async evalOnSelectorAndWaitForSignals(selector: string, strict: boolean, expression: string, isFunction: boolean | undefined, arg: any): Promise<any> {
const handle = await this._page.selectors._query(this._context.frame, selector, strict, this);
if (!handle)
throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = await handle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);
@ -743,7 +743,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
const { state = 'visible' } = options;
if (!['attached', 'detached', 'visible', 'hidden'].includes(state))
throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = waitForSelectorTask(info, state, this);
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
@ -934,7 +934,7 @@ function compensateHalfIntegerRoundingError(point: types.Point) {
export type SchedulableTask<T> = (injectedScript: js.JSHandle<InjectedScript>) => Promise<js.JSHandle<InjectedScriptPoll<T>>>;
export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' | 'detached' | 'visible' | 'hidden', root?: ElementHandle): SchedulableTask<Element | undefined> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, state, root }) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict, state, root }) => {
let lastElement: Element | undefined;
return injected.pollRaf((progress, continuePolling) => {
@ -947,8 +947,11 @@ export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' |
if (!element) {
progress.log(` selector did not resolve to any element`);
} else {
if (elements.length > 1)
if (elements.length > 1) {
if (strict)
throw new Error(`strict mode violation: selector resolved to ${elements.length} elements.`);
progress.log(` selector resolved to ${elements.length} elements. Proceeding with the first one.`);
}
progress.log(` selector resolved to ${visible ? 'visible' : 'hidden'} ${injected.previewNode(element)}`);
}
}
@ -964,37 +967,37 @@ export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' |
return !visible ? undefined : continuePolling;
}
});
}, { parsed: selector.parsed, state, root });
}, { parsed: selector.parsed, strict: selector.strict, state, root });
}
export function dispatchEventTask(selector: SelectorInfo, type: string, eventInit: Object): SchedulableTask<undefined> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, type, eventInit }) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict, type, eventInit }) => {
return injected.pollRaf<undefined>((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
injected.dispatchEvent(element, type, eventInit);
});
}, { parsed: selector.parsed, type, eventInit });
}, { parsed: selector.parsed, strict: selector.strict, type, eventInit });
}
export function textContentTask(selector: SelectorInfo): SchedulableTask<string | null> {
return injectedScript => injectedScript.evaluateHandle((injected, parsed) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict }) => {
return injected.pollRaf((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
return element.textContent;
});
}, selector.parsed);
}, { parsed: selector.parsed, strict: selector.strict });
}
export function innerTextTask(selector: SelectorInfo): SchedulableTask<'error:nothtmlelement' | { innerText: string }> {
return injectedScript => injectedScript.evaluateHandle((injected, parsed) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict }) => {
return injected.pollRaf((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
@ -1002,37 +1005,37 @@ export function innerTextTask(selector: SelectorInfo): SchedulableTask<'error:no
return 'error:nothtmlelement';
return { innerText: (element as HTMLElement).innerText };
});
}, selector.parsed);
}, { parsed: selector.parsed, strict: selector.strict });
}
export function innerHTMLTask(selector: SelectorInfo): SchedulableTask<string> {
return injectedScript => injectedScript.evaluateHandle((injected, parsed) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict }) => {
return injected.pollRaf((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
return element.innerHTML;
});
}, selector.parsed);
}, { parsed: selector.parsed, strict: selector.strict });
}
export function getAttributeTask(selector: SelectorInfo, name: string): SchedulableTask<string | null> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, name }) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict, name }) => {
return injected.pollRaf((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
return element.getAttribute(name);
});
}, { parsed: selector.parsed, name });
}, { parsed: selector.parsed, strict: selector.strict, name });
}
export function inputValueTask(selector: SelectorInfo): SchedulableTask<string> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed }) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict }) => {
return injected.pollRaf((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
@ -1040,19 +1043,19 @@ export function inputValueTask(selector: SelectorInfo): SchedulableTask<string>
return 'error:notinputvalue';
return (element as any).value;
});
}, { parsed: selector.parsed });
}, { parsed: selector.parsed, strict: selector.strict, });
}
export function elementStateTask(selector: SelectorInfo, state: ElementStateWithoutStable): SchedulableTask<boolean | 'error:notconnected' | FatalDOMError> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, state }) => {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, strict, state }) => {
return injected.pollRaf((progress, continuePolling) => {
const element = injected.querySelector(parsed, document);
const element = injected.querySelector(parsed, document, strict);
if (!element)
return continuePolling;
progress.log(` selector resolved to ${injected.previewNode(element)}`);
return injected.checkElementState(element, state);
});
}, { parsed: selector.parsed, state });
}, { parsed: selector.parsed, strict: selector.strict, state });
}
export const kUnableToAdoptErrorMessage = 'Unable to adopt element handle from a different document';

View file

@ -682,9 +682,9 @@ export class Frame extends SdkObject {
return value;
}
async querySelector(selector: string): Promise<dom.ElementHandle<Element> | null> {
async querySelector(selector: string, options: types.StrictOptions): Promise<dom.ElementHandle<Element> | null> {
debugLogger.log('api', ` finding element using the selector "${selector}"`);
return this._page.selectors._query(this, selector);
return this._page.selectors._query(this, selector, !!options.strict);
}
async waitForSelector(metadata: CallMetadata, selector: string, options: types.WaitForElementOptions = {}): Promise<dom.ElementHandle<Element> | null> {
@ -696,7 +696,7 @@ export class Frame extends SdkObject {
const { state = 'visible' } = options;
if (!['attached', 'detached', 'visible', 'hidden'].includes(state))
throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.waitForSelectorTask(info, state);
return controller.run(async progress => {
progress.log(`waiting for selector "${selector}"${state === 'attached' ? '' : ' to be ' + state}`);
@ -723,9 +723,9 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
async dispatchEvent(metadata: CallMetadata, selector: string, type: string, eventInit?: Object, options: types.TimeoutOptions = {}): Promise<void> {
async dispatchEvent(metadata: CallMetadata, selector: string, type: string, eventInit?: Object, options: types.QueryOnSelectorOptions = {}): Promise<void> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.dispatchEventTask(info, type, eventInit || {});
await controller.run(async progress => {
progress.log(`Dispatching "${type}" event on selector "${selector}"...`);
@ -735,8 +735,8 @@ export class Frame extends SdkObject {
await this._page._doSlowMo();
}
async evalOnSelectorAndWaitForSignals(selector: string, expression: string, isFunction: boolean | undefined, arg: any): Promise<any> {
const handle = await this.querySelector(selector);
async evalOnSelectorAndWaitForSignals(selector: string, strict: boolean, expression: string, isFunction: boolean | undefined, arg: any): Promise<any> {
const handle = await this.querySelector(selector, { strict });
if (!handle)
throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = await handle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);
@ -936,8 +936,9 @@ export class Frame extends SdkObject {
private async _retryWithProgressIfNotConnected<R>(
progress: Progress,
selector: string,
strict: boolean,
action: (handle: dom.ElementHandle<Element>) => Promise<R | 'error:notconnected'>): Promise<R> {
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, strict);
while (progress.isRunning()) {
progress.log(`waiting for selector "${selector}"`);
const task = dom.waitForSelectorTask(info, 'attached');
@ -961,31 +962,31 @@ export class Frame extends SdkObject {
private async _retryWithSelectorIfNotConnected<R>(
controller: ProgressController,
selector: string, options: types.TimeoutOptions,
selector: string, options: types.TimeoutOptions & types.StrictOptions,
action: (progress: Progress, handle: dom.ElementHandle<Element>) => Promise<R | 'error:notconnected'>): Promise<R> {
return controller.run(async progress => {
return this._retryWithProgressIfNotConnected(progress, selector, handle => action(progress, handle));
return this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => action(progress, handle));
}, this._page._timeoutSettings.timeout(options));
}
async click(metadata: CallMetadata, selector: string, options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._click(progress, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._click(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}
async dblclick(metadata: CallMetadata, selector: string, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._dblclick(progress, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._dblclick(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}
async dragAndDrop(metadata: CallMetadata, source: string, target: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
await controller.run(async progress => {
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, async handle => {
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, !!options.strict, async handle => {
return handle._retryPointerAction(progress, 'move and down', false, async point => {
await this._page.mouse.move(point.x, point.y);
await this._page.mouse.down();
@ -994,7 +995,7 @@ export class Frame extends SdkObject {
timeout: progress.timeUntilDeadline(),
});
}));
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, async handle => {
await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, !!options.strict, async handle => {
return handle._retryPointerAction(progress, 'move and up', false, async point => {
await this._page.mouse.move(point.x, point.y);
await this._page.mouse.up();
@ -1009,14 +1010,14 @@ export class Frame extends SdkObject {
async tap(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._tap(progress, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._tap(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}
async fill(metadata: CallMetadata, selector: string, value: string, options: types.NavigatingActionWaitOptions & { force?: boolean }) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._fill(progress, value, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._fill(progress, value, options)));
}, this._page._timeoutSettings.timeout(options));
}
@ -1026,9 +1027,9 @@ export class Frame extends SdkObject {
await this._page._doSlowMo();
}
async textContent(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<string | null> {
async textContent(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<string | null> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.textContentTask(info);
return controller.run(async progress => {
progress.log(` retrieving textContent from "${selector}"`);
@ -1036,9 +1037,9 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
async innerText(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<string> {
async innerText(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<string> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.innerTextTask(info);
return controller.run(async progress => {
progress.log(` retrieving innerText from "${selector}"`);
@ -1047,9 +1048,9 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
async innerHTML(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<string> {
async innerHTML(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<string> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.innerHTMLTask(info);
return controller.run(async progress => {
progress.log(` retrieving innerHTML from "${selector}"`);
@ -1057,9 +1058,9 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
async getAttribute(metadata: CallMetadata, selector: string, name: string, options: types.TimeoutOptions = {}): Promise<string | null> {
async getAttribute(metadata: CallMetadata, selector: string, name: string, options: types.QueryOnSelectorOptions = {}): Promise<string | null> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.getAttributeTask(info, name);
return controller.run(async progress => {
progress.log(` retrieving attribute "${name}" from "${selector}"`);
@ -1067,9 +1068,9 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
async inputValue(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<string> {
async inputValue(metadata: CallMetadata, selector: string, options: types.TimeoutOptions & types.StrictOptions = {}): Promise<string> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.inputValueTask(info);
return controller.run(async progress => {
progress.log(` retrieving value from "${selector}"`);
@ -1077,9 +1078,9 @@ export class Frame extends SdkObject {
}, this._page._timeoutSettings.timeout(options));
}
private async _checkElementState(metadata: CallMetadata, selector: string, state: ElementStateWithoutStable, options: types.TimeoutOptions = {}): Promise<boolean> {
private async _checkElementState(metadata: CallMetadata, selector: string, state: ElementStateWithoutStable, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
const controller = new ProgressController(metadata, this);
const info = this._page.selectors._parseSelector(selector);
const info = this._page.selectors._parseSelector(selector, !!options.strict);
const task = dom.elementStateTask(info, state);
const result = await controller.run(async progress => {
progress.log(` checking "${state}" state of "${selector}"`);
@ -1088,81 +1089,81 @@ export class Frame extends SdkObject {
return dom.throwFatalDOMError(dom.throwRetargetableDOMError(result));
}
async isVisible(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<boolean> {
async isVisible(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
progress.log(` checking visibility of "${selector}"`);
const element = await this.querySelector(selector);
const element = await this.querySelector(selector, options);
return element ? await element.isVisible() : false;
}, this._page._timeoutSettings.timeout(options));
}
async isHidden(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<boolean> {
async isHidden(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
return !(await this.isVisible(metadata, selector, options));
}
async isDisabled(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<boolean> {
async isDisabled(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
return this._checkElementState(metadata, selector, 'disabled', options);
}
async isEnabled(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<boolean> {
async isEnabled(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
return this._checkElementState(metadata, selector, 'enabled', options);
}
async isEditable(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<boolean> {
async isEditable(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
return this._checkElementState(metadata, selector, 'editable', options);
}
async isChecked(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<boolean> {
async isChecked(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}): Promise<boolean> {
return this._checkElementState(metadata, selector, 'checked', options);
}
async hover(metadata: CallMetadata, selector: string, options: types.PointerActionOptions & types.PointerActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._hover(progress, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._hover(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}
async selectOption(metadata: CallMetadata, selector: string, elements: dom.ElementHandle[], values: types.SelectOption[], options: types.NavigatingActionWaitOptions & types.ForceOptions = {}): Promise<string[]> {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._selectOption(progress, elements, values, options));
return await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._selectOption(progress, elements, values, options));
}, this._page._timeoutSettings.timeout(options));
}
async setInputFiles(metadata: CallMetadata, selector: string, files: channels.ElementHandleSetInputFilesParams['files'], options: types.NavigatingActionWaitOptions = {}): Promise<void> {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._setInputFiles(progress, files, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._setInputFiles(progress, files, options)));
}, this._page._timeoutSettings.timeout(options));
}
async type(metadata: CallMetadata, selector: string, text: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._type(progress, text, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._type(progress, text, options)));
}, this._page._timeoutSettings.timeout(options));
}
async press(metadata: CallMetadata, selector: string, key: string, options: { delay?: number } & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._press(progress, key, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._press(progress, key, options)));
}, this._page._timeoutSettings.timeout(options));
}
async check(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._setChecked(progress, true, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._setChecked(progress, true, options)));
}, this._page._timeoutSettings.timeout(options));
}
async uncheck(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, handle => handle._setChecked(progress, false, options)));
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, !!options.strict, handle => handle._setChecked(progress, false, options)));
}, this._page._timeoutSettings.timeout(options));
}

View file

@ -69,6 +69,7 @@ export class InjectedScript {
this._engines.set('data-test', this._createAttributeEngine('data-test', true));
this._engines.set('data-test:light', this._createAttributeEngine('data-test', false));
this._engines.set('css', this._createCSSEngine());
for (const { name, engine } of customEngines)
this._engines.set(name, engine);
@ -85,24 +86,32 @@ export class InjectedScript {
return result;
}
querySelector(selector: ParsedSelector, root: Node): Element | undefined {
querySelector(selector: ParsedSelector, root: Node, strict: boolean): Element | undefined {
if (!(root as any)['querySelector'])
throw new Error('Node is not queryable.');
this._evaluator.begin();
try {
return this._querySelectorRecursively(root as SelectorRoot, selector, 0);
return this._querySelectorRecursively(root as SelectorRoot, selector, strict, 0);
} finally {
this._evaluator.end();
}
}
private _querySelectorRecursively(root: SelectorRoot, selector: ParsedSelector, index: number): Element | undefined {
private _querySelectorRecursively(root: SelectorRoot, selector: ParsedSelector, strict: boolean, index: number): Element | undefined {
const current = selector.parts[index];
if (index === selector.parts.length - 1)
return this._queryEngine(current, root);
if (index === selector.parts.length - 1) {
if (strict) {
const all = this._queryEngineAll(current, root);
if (all.length > 1)
throw new Error(`strict mode violation: selector resolved to ${all.length} elements.`);
return all[0];
} else {
return this._queryEngine(current, root);
}
}
const all = this._queryEngineAll(current, root);
for (const next of all) {
const result = this._querySelectorRecursively(next, selector, index + 1);
const result = this._querySelectorRecursively(next, selector, strict, index + 1);
if (result)
return selector.capture === index ? next : result;
}
@ -133,7 +142,7 @@ export class InjectedScript {
let result = [...set] as Element[];
if (partsToCheckOne.length) {
const partial = { parts: partsToCheckOne };
result = result.filter(e => !!this._querySelectorRecursively(e, partial, 0));
result = result.filter(e => !!this._querySelectorRecursively(e, partial, false, 0));
}
return result;
} finally {
@ -243,6 +252,7 @@ export class InjectedScript {
else
requestAnimationFrame(onRaf);
} catch (e) {
progress.log(' ' + e.message);
reject(e);
}
};

View file

@ -25,6 +25,7 @@ export type SelectorInfo = {
parsed: ParsedSelector,
world: types.World,
selector: string,
strict: boolean,
};
export class Selectors {
@ -61,13 +62,13 @@ export class Selectors {
this._engines.clear();
}
async _query(frame: frames.Frame, selector: string, scope?: dom.ElementHandle): Promise<dom.ElementHandle<Element> | null> {
const info = this._parseSelector(selector);
async _query(frame: frames.Frame, selector: string, strict: boolean, scope?: dom.ElementHandle): Promise<dom.ElementHandle<Element> | null> {
const info = this._parseSelector(selector, strict);
const context = await frame._context(info.world);
const injectedScript = await context.injectedScript();
const handle = await injectedScript.evaluateHandle((injected, { parsed, scope }) => {
return injected.querySelector(parsed, scope || document);
}, { parsed: info.parsed, scope });
const handle = await injectedScript.evaluateHandle((injected, { parsed, scope, strict }) => {
return injected.querySelector(parsed, scope || document, strict);
}, { parsed: info.parsed, scope, strict });
const elementHandle = handle.asElement() as dom.ElementHandle<Element> | null;
if (!elementHandle) {
handle.dispose();
@ -78,7 +79,7 @@ export class Selectors {
}
async _queryArray(frame: frames.Frame, selector: string, scope?: dom.ElementHandle): Promise<js.JSHandle<Element[]>> {
const info = this._parseSelector(selector);
const info = this._parseSelector(selector, false);
const context = await frame._mainContext();
const injectedScript = await context.injectedScript();
const arrayHandle = await injectedScript.evaluateHandle((injected, { parsed, scope }) => {
@ -88,7 +89,7 @@ export class Selectors {
}
async _queryAll(frame: frames.Frame, selector: string, scope?: dom.ElementHandle, adoptToMain?: boolean): Promise<dom.ElementHandle<Element>[]> {
const info = this._parseSelector(selector);
const info = this._parseSelector(selector, false);
const context = await frame._context(info.world);
const injectedScript = await context.injectedScript();
const arrayHandle = await injectedScript.evaluateHandle((injected, { parsed, scope }) => {
@ -120,7 +121,7 @@ export class Selectors {
return adopted;
}
_parseSelector(selector: string): SelectorInfo {
_parseSelector(selector: string, strict: boolean): SelectorInfo {
const parsed = parseSelector(selector);
let needsMainWorld = false;
for (const part of parsed.parts) {
@ -136,6 +137,7 @@ export class Selectors {
parsed,
selector,
world: needsMainWorld ? 'main' : 'utility',
strict,
};
}
}

View file

@ -41,7 +41,7 @@ export class ConsoleAPI {
if (window.playwright)
return;
window.playwright = {
$: (selector: string) => this._querySelector(selector),
$: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
$$: (selector: string) => this._querySelectorAll(selector),
inspect: (selector: string) => this._inspect(selector),
selector: (element: Element) => this._selector(element),
@ -49,11 +49,11 @@ export class ConsoleAPI {
};
}
private _querySelector(selector: string): (Element | undefined) {
private _querySelector(selector: string, strict: boolean): (Element | undefined) {
if (typeof selector !== 'string')
throw new Error(`Usage: playwright.query('Playwright >> selector').`);
const parsed = this._injectedScript.parseSelector(selector);
return this._injectedScript.querySelector(parsed, document);
return this._injectedScript.querySelector(parsed, document, strict);
}
private _querySelectorAll(selector: string): Element[] {
@ -66,7 +66,7 @@ export class ConsoleAPI {
private _inspect(selector: string) {
if (typeof selector !== 'string')
throw new Error(`Usage: playwright.inspect('Playwright >> selector').`);
window.inspect(this._querySelector(selector));
window.inspect(this._querySelector(selector, false));
}
private _selector(element: Element) {

View file

@ -225,7 +225,7 @@ function cssFallback(injectedScript: InjectedScript, targetElement: Element): Se
path.unshift(prefix);
const selector = path.join(' ');
const parsedSelector = injectedScript.parseSelector(selector);
const node = injectedScript.querySelector(parsedSelector, targetElement.ownerDocument);
const node = injectedScript.querySelector(parsedSelector, targetElement.ownerDocument, false);
return node === targetElement ? selector : undefined;
}

View file

@ -18,7 +18,13 @@
import { Size, Point, Rect, TimeoutOptions } from '../common/types';
export { Size, Point, Rect, Quad, URLMatch, TimeoutOptions } from '../common/types';
export type WaitForElementOptions = TimeoutOptions & { state?: 'attached' | 'detached' | 'visible' | 'hidden' };
export type StrictOptions = {
strict?: boolean,
};
export type QueryOnSelectorOptions = StrictOptions & TimeoutOptions;
export type WaitForElementOptions = TimeoutOptions & StrictOptions & { state?: 'attached' | 'detached' | 'visible' | 'hidden' };
export type WaitForFunctionOptions = TimeoutOptions & { pollingInterval?: number };
@ -29,7 +35,7 @@ export type NavigateOptions = TimeoutOptions & {
waitUntil?: LifecycleEvent,
};
export type NavigatingActionWaitOptions = TimeoutOptions & {
export type NavigatingActionWaitOptions = TimeoutOptions & StrictOptions & {
noWaitAfter?: boolean,
};
@ -37,7 +43,7 @@ export type ForceOptions = {
force?: boolean,
};
export type PointerActionWaitOptions = TimeoutOptions & ForceOptions & {
export type PointerActionWaitOptions = TimeoutOptions & ForceOptions & StrictOptions & {
trial?: boolean;
};

View file

@ -0,0 +1,53 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { test as it, expect } from './pageTest';
it('should fail page.textContent in strict mode', async ({ page }) => {
await page.setContent(`<span>span1</span><div><span>target</span></div>`);
const error = await page.textContent('span', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation');
});
it('should fail page.getAttribute in strict mode', async ({ page }) => {
await page.setContent(`<span>span1</span><div><span>target</span></div>`);
const error = await page.getAttribute('span', 'id', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation');
});
it('should fail page.fill in strict mode', async ({ page }) => {
await page.setContent(`<input></input><div><input></input></div>`);
const error = await page.fill('input', 'text', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation');
});
it('should fail page.$ in strict mode', async ({ page }) => {
await page.setContent(`<span>span1</span><div><span>target</span></div>`);
const error = await page.$('span', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation');
});
it('should fail page.waitForSelector in strict mode', async ({ page }) => {
await page.setContent(`<span>span1</span><div><span>target</span></div>`);
const error = await page.waitForSelector('span', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation');
});
it('should fail page.dispatchEvent in strict mode', async ({ page }) => {
await page.setContent(`<span></span><div><span></span></div>`);
const error = await page.dispatchEvent('span', 'click', {}, { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation');
});

337
types/types.d.ts vendored
View file

@ -168,11 +168,13 @@ export interface Page {
* return value resolves to `null`. To wait for an element on the page, use
* [page.waitForSelector(selector[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-selector).
*
* Shortcut for main frame's [frame.$(selector)](https://playwright.dev/docs/api/class-frame#frame-query-selector).
* Shortcut for main frame's
* [frame.$(selector[, options])](https://playwright.dev/docs/api/class-frame#frame-query-selector).
* @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param options
*/
$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K> | null>;
$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
$(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
/**
* The method finds all elements matching the specified selector within the page. If no elements match the selector, the
@ -189,8 +191,8 @@ export interface Page {
* `pageFunction`. If no elements match the selector, the method throws an error. Returns the value of `pageFunction`.
*
* If `pageFunction` returns a [Promise], then
* [page.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-eval-on-selector) would wait
* for the promise to resolve and return its value.
* [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector)
* would wait for the promise to resolve and return its value.
*
* Examples:
*
@ -203,10 +205,11 @@ export interface Page {
* ```
*
* Shortcut for main frame's
* [frame.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector).
* [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector).
* @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param pageFunction Function to be evaluated in the page context.
* @param arg Optional argument to pass to `pageFunction`.
* @param options
*/
$eval<K extends keyof HTMLElementTagNameMap, R, Arg>(selector: K, pageFunction: PageFunctionOn<HTMLElementTagNameMap[K], Arg, R>, arg: Arg): Promise<R>;
$eval<R, Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(selector: string, pageFunction: PageFunctionOn<E, Arg, R>, arg: Arg): Promise<R>;
@ -1151,6 +1154,12 @@ export interface Page {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1227,6 +1236,12 @@ export interface Page {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1337,6 +1352,12 @@ export interface Page {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1387,6 +1408,12 @@ export interface Page {
* @param options
*/
dispatchEvent(selector: string, type: string, eventInit?: EvaluationArgument, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1414,6 +1441,12 @@ export interface Page {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1558,6 +1591,12 @@ export interface Page {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1576,6 +1615,12 @@ export interface Page {
* @param options
*/
focus(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1622,6 +1667,12 @@ export interface Page {
* @param options
*/
getAttribute(selector: string, name: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1775,6 +1826,12 @@ export interface Page {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1796,6 +1853,12 @@ export interface Page {
* @param options
*/
innerHTML(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1811,6 +1874,12 @@ export interface Page {
* @param options
*/
innerText(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1826,6 +1895,12 @@ export interface Page {
* @param options
*/
inputValue(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1841,6 +1916,12 @@ export interface Page {
* @param options
*/
isChecked(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1861,6 +1942,12 @@ export interface Page {
* @param options
*/
isDisabled(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1876,6 +1963,12 @@ export interface Page {
* @param options
*/
isEditable(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1891,6 +1984,12 @@ export interface Page {
* @param options
*/
isEnabled(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1907,6 +2006,12 @@ export interface Page {
* @param options
*/
isHidden(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -1923,6 +2028,12 @@ export interface Page {
* @param options
*/
isVisible(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2164,6 +2275,12 @@ export interface Page {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2329,6 +2446,12 @@ export interface Page {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2451,6 +2574,12 @@ export interface Page {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2540,6 +2669,12 @@ export interface Page {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2561,6 +2696,12 @@ export interface Page {
* @param options
*/
textContent(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2610,6 +2751,12 @@ export interface Page {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -2662,6 +2809,12 @@ export interface Page {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3228,9 +3381,10 @@ export interface Frame {
* The method finds an element matching the specified selector within the frame. See
* [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, returns `null`.
* @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param options
*/
$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K> | null>;
$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
$(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
/**
* Returns the ElementHandles pointing to the frame elements.
@ -3250,8 +3404,8 @@ export interface Frame {
* method throws an error.
*
* If `pageFunction` returns a [Promise], then
* [frame.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector) would
* wait for the promise to resolve and return its value.
* [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector)
* would wait for the promise to resolve and return its value.
*
* Examples:
*
@ -3264,6 +3418,7 @@ export interface Frame {
* @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param pageFunction Function to be evaluated in the page context.
* @param arg Optional argument to pass to `pageFunction`.
* @param options
*/
$eval<K extends keyof HTMLElementTagNameMap, R, Arg>(selector: K, pageFunction: PageFunctionOn<HTMLElementTagNameMap[K], Arg, R>, arg: Arg): Promise<R>;
$eval<R, Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(selector: string, pageFunction: PageFunctionOn<E, Arg, R>, arg: Arg): Promise<R>;
@ -3456,6 +3611,12 @@ export interface Frame {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3532,6 +3693,12 @@ export interface Frame {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3609,6 +3776,12 @@ export interface Frame {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3659,6 +3832,12 @@ export interface Frame {
* @param options
*/
dispatchEvent(selector: string, type: string, eventInit?: EvaluationArgument, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3686,6 +3865,12 @@ export interface Frame {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3746,6 +3931,12 @@ export interface Frame {
* @param options
*/
focus(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3780,6 +3971,12 @@ export interface Frame {
* @param options
*/
getAttribute(selector: string, name: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3874,6 +4071,12 @@ export interface Frame {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3895,6 +4098,12 @@ export interface Frame {
* @param options
*/
innerHTML(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3910,6 +4119,12 @@ export interface Frame {
* @param options
*/
innerText(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3925,6 +4140,12 @@ export interface Frame {
* @param options
*/
inputValue(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3940,6 +4161,12 @@ export interface Frame {
* @param options
*/
isChecked(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3960,6 +4187,12 @@ export interface Frame {
* @param options
*/
isDisabled(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3975,6 +4208,12 @@ export interface Frame {
* @param options
*/
isEditable(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -3990,6 +4229,12 @@ export interface Frame {
* @param options
*/
isEnabled(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4006,6 +4251,12 @@ export interface Frame {
* @param options
*/
isHidden(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4022,6 +4273,12 @@ export interface Frame {
* @param options
*/
isVisible(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4094,6 +4351,12 @@ export interface Frame {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4174,6 +4437,12 @@ export interface Frame {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4255,6 +4524,12 @@ export interface Frame {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4310,6 +4585,12 @@ export interface Frame {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4331,6 +4612,12 @@ export interface Frame {
* @param options
*/
textContent(selector: string, options?: {
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4375,6 +4662,12 @@ export interface Frame {
*/
noWaitAfter?: boolean;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -4424,6 +4717,12 @@ export interface Frame {
y: number;
};
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the
@ -5536,7 +5835,7 @@ export interface Worker {
* their origin frame gets navigated or the parent context gets destroyed.
*
* JSHandle instances can be used as an argument in
* [page.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-eval-on-selector),
* [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector),
* [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) and
* [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle) methods.
*/
@ -5621,7 +5920,7 @@ export interface JSHandle<T = any> {
* - extends: [JSHandle]
*
* ElementHandle represents an in-page DOM element. ElementHandles can be created with the
* [page.$(selector)](https://playwright.dev/docs/api/class-page#page-query-selector) method.
* [page.$(selector[, options])](https://playwright.dev/docs/api/class-page#page-query-selector) method.
*
* ```js
* const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
@ -5641,8 +5940,8 @@ export interface JSHandle<T = any> {
* when their origin frame gets navigated.
*
* ElementHandle instances can be used as an argument in
* [page.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-eval-on-selector) and
* [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) methods.
* [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector)
* and [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) methods.
*/
export interface ElementHandle<T=Node> extends JSHandle<T> {
/**
@ -5650,8 +5949,8 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
* [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, returns `null`.
* @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
*/
$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K> | null>;
$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
$(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
/**
* The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See
@ -12448,6 +12747,12 @@ interface PageWaitForSelectorOptions {
*/
state?: "attached"|"detached"|"visible"|"hidden";
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
strict?: boolean;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by
* using the

View file

@ -33,8 +33,8 @@ export interface Page {
evaluateHandle<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
evaluateHandle<R>(pageFunction: PageFunction<void, R>, arg?: any): Promise<SmartHandle<R>>;
$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K> | null>;
$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
$(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K>[]>;
$$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]>;
@ -68,8 +68,8 @@ export interface Frame {
evaluateHandle<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
evaluateHandle<R>(pageFunction: PageFunction<void, R>, arg?: any): Promise<SmartHandle<R>>;
$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K> | null>;
$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
$(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K>[]>;
$$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]>;
@ -118,8 +118,8 @@ export interface JSHandle<T = any> {
}
export interface ElementHandle<T=Node> extends JSHandle<T> {
$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K> | null>;
$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
$(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
$$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K>[]>;
$$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]>;