mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: add waitForXPath to ElementHandle (#8329)
This commit is contained in:
parent
1e82d98027
commit
7eaadafe19
39
docs/api.md
39
docs/api.md
@ -342,6 +342,7 @@
|
|||||||
* [elementHandle.type(text[, options])](#elementhandletypetext-options)
|
* [elementHandle.type(text[, options])](#elementhandletypetext-options)
|
||||||
* [elementHandle.uploadFile(...filePaths)](#elementhandleuploadfilefilepaths)
|
* [elementHandle.uploadFile(...filePaths)](#elementhandleuploadfilefilepaths)
|
||||||
* [elementHandle.waitForSelector(selector[, options])](#elementhandlewaitforselectorselector-options)
|
* [elementHandle.waitForSelector(selector[, options])](#elementhandlewaitforselectorselector-options)
|
||||||
|
* [elementHandle.waitForXPath(xpath[, options])](#elementhandlewaitforxpathxpath-options)
|
||||||
- [class: HTTPRequest](#class-httprequest)
|
- [class: HTTPRequest](#class-httprequest)
|
||||||
* [httpRequest.abort([errorCode], [priority])](#httprequestaborterrorcode-priority)
|
* [httpRequest.abort([errorCode], [priority])](#httprequestaborterrorcode-priority)
|
||||||
* [httpRequest.abortErrorReason()](#httprequestaborterrorreason)
|
* [httpRequest.abortErrorReason()](#httprequestaborterrorreason)
|
||||||
@ -4902,6 +4903,44 @@ Wait for an element matching `selector` to appear within the `elementHandle`’s
|
|||||||
|
|
||||||
This method does not work across navigations or if the element is detached from DOM.
|
This method does not work across navigations or if the element is detached from DOM.
|
||||||
|
|
||||||
|
#### elementHandle.waitForXPath(xpath[, options])
|
||||||
|
|
||||||
|
- `xpath` <[string]> A [xpath] of an element to wait for
|
||||||
|
- `options` <[Object]> Optional waiting parameters
|
||||||
|
- `visible` <[boolean]> wait for element to be present in DOM and to be visible, i.e. to not have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`.
|
||||||
|
- `hidden` <[boolean]> wait for element to not be found in the DOM or to be hidden, i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`.
|
||||||
|
- `timeout` <[number]> 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 [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) method.
|
||||||
|
- returns: <[Promise]<?[ElementHandle]>> Promise which resolves when element specified by xpath string is added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is not found in DOM.
|
||||||
|
|
||||||
|
Wait for the `xpath` to appear within the element. If at the moment of calling
|
||||||
|
the method the `xpath` already exists, the method will return
|
||||||
|
immediately. If the xpath doesn't appear after the `timeout` milliseconds of waiting, the function will throw.
|
||||||
|
|
||||||
|
If `xpath` starts with `//` instead of `.//`, the dot will be appended automatically.
|
||||||
|
|
||||||
|
This method works across navigations:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const puppeteer = require('puppeteer');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const browser = await puppeteer.launch();
|
||||||
|
const page = await browser.newPage();
|
||||||
|
let currentURL;
|
||||||
|
page
|
||||||
|
.waitForXPath('//img')
|
||||||
|
.then(() => console.log('First URL with image: ' + currentURL));
|
||||||
|
for (currentURL of [
|
||||||
|
'https://example.com',
|
||||||
|
'https://google.com',
|
||||||
|
'https://bbc.com',
|
||||||
|
]) {
|
||||||
|
await page.goto(currentURL);
|
||||||
|
}
|
||||||
|
await browser.close();
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
### class: HTTPRequest
|
### class: HTTPRequest
|
||||||
|
|
||||||
Whenever the page sends a request, such as for a network resource, the following events are emitted by Puppeteer's page:
|
Whenever the page sends a request, such as for a network resource, the following events are emitted by Puppeteer's page:
|
||||||
|
@ -416,6 +416,84 @@ export class ElementHandle<
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the `xpath` within the element. If at the moment of calling the
|
||||||
|
* method the `xpath` already exists, the method will return immediately. If
|
||||||
|
* the `xpath` doesn't appear after the `timeout` milliseconds of waiting, the
|
||||||
|
* function will throw.
|
||||||
|
*
|
||||||
|
* If `xpath` starts with `//` instead of `.//`, the dot will be appended automatically.
|
||||||
|
*
|
||||||
|
* This method works across navigation
|
||||||
|
* ```js
|
||||||
|
* const puppeteer = require('puppeteer');
|
||||||
|
* (async () => {
|
||||||
|
* const browser = await puppeteer.launch();
|
||||||
|
* const page = await browser.newPage();
|
||||||
|
* let currentURL;
|
||||||
|
* page
|
||||||
|
* .waitForXPath('//img')
|
||||||
|
* .then(() => console.log('First URL with image: ' + currentURL));
|
||||||
|
* for (currentURL of [
|
||||||
|
* 'https://example.com',
|
||||||
|
* 'https://google.com',
|
||||||
|
* 'https://bbc.com',
|
||||||
|
* ]) {
|
||||||
|
* await page.goto(currentURL);
|
||||||
|
* }
|
||||||
|
* await browser.close();
|
||||||
|
* })();
|
||||||
|
* ```
|
||||||
|
* @param xpath - A
|
||||||
|
* {@link https://developer.mozilla.org/en-US/docs/Web/XPath | xpath} of an
|
||||||
|
* element to wait for
|
||||||
|
* @param options - Optional waiting parameters
|
||||||
|
* @returns Promise which resolves when element specified by xpath string is
|
||||||
|
* added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is
|
||||||
|
* not found in DOM.
|
||||||
|
* @remarks
|
||||||
|
* The optional Argument `options` have properties:
|
||||||
|
*
|
||||||
|
* - `visible`: A boolean to wait for element to be present in DOM and to be
|
||||||
|
* visible, i.e. to not have `display: none` or `visibility: hidden` CSS
|
||||||
|
* properties. Defaults to `false`.
|
||||||
|
*
|
||||||
|
* - `hidden`: A boolean wait for element to not be found in the DOM or to be
|
||||||
|
* hidden, i.e. have `display: none` or `visibility: hidden` CSS properties.
|
||||||
|
* Defaults to `false`.
|
||||||
|
*
|
||||||
|
* - `timeout`: A number which is 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 {@link Page.setDefaultTimeout} method.
|
||||||
|
*/
|
||||||
|
async waitForXPath(
|
||||||
|
xpath: string,
|
||||||
|
options: {
|
||||||
|
visible?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
|
timeout?: number;
|
||||||
|
} = {}
|
||||||
|
): Promise<ElementHandle | null> {
|
||||||
|
const frame = this._context.frame();
|
||||||
|
const secondaryContext = await frame._secondaryWorld.executionContext();
|
||||||
|
const adoptedRoot = await secondaryContext._adoptElementHandle(this);
|
||||||
|
xpath = xpath.startsWith('//') ? '.' + xpath : xpath;
|
||||||
|
if (!xpath.startsWith('.//')) {
|
||||||
|
await adoptedRoot.dispose();
|
||||||
|
throw new Error('Unsupported xpath expression: ' + xpath);
|
||||||
|
}
|
||||||
|
const handle = await frame._secondaryWorld.waitForXPath(xpath, {
|
||||||
|
...options,
|
||||||
|
root: adoptedRoot,
|
||||||
|
});
|
||||||
|
await adoptedRoot.dispose();
|
||||||
|
if (!handle) return null;
|
||||||
|
const mainExecutionContext = await frame._mainWorld.executionContext();
|
||||||
|
const result = await mainExecutionContext._adoptElementHandle(handle);
|
||||||
|
await handle.dispose();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
asElement(): ElementHandle<ElementType> | null {
|
asElement(): ElementHandle<ElementType> | null {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -280,6 +280,34 @@ describe('ElementHandle specs', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Element.waitForXPath', () => {
|
||||||
|
it('should wait correctly with waitForXPath on an element', async () => {
|
||||||
|
const { page } = getTestState();
|
||||||
|
// Set the page content after the waitFor has been started.
|
||||||
|
await page.setContent(
|
||||||
|
`<div id=el1>
|
||||||
|
el1
|
||||||
|
<div id=el2>
|
||||||
|
el2
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=el3>
|
||||||
|
el3
|
||||||
|
</div>`
|
||||||
|
);
|
||||||
|
|
||||||
|
const el2 = await page.waitForSelector('#el1');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await (await el2.waitForXPath('//div')).evaluate((el) => el.id)
|
||||||
|
).toStrictEqual('el2');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await (await el2.waitForXPath('.//div')).evaluate((el) => el.id)
|
||||||
|
).toStrictEqual('el2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ElementHandle.hover', function () {
|
describe('ElementHandle.hover', function () {
|
||||||
it('should work', async () => {
|
it('should work', async () => {
|
||||||
const { page, server } = getTestState();
|
const { page, server } = getTestState();
|
||||||
|
Loading…
Reference in New Issue
Block a user