feat($wait): make $wait a shortcut for waitForSelector (#932)
This commit is contained in:
parent
3a32b14f32
commit
53237009ad
62
docs/api.md
62
docs/api.md
|
|
@ -452,7 +452,7 @@ page.removeListener('request', logRequest);
|
|||
- [page.$$(selector)](#pageselector-1)
|
||||
- [page.$$eval(selector, pageFunction[, ...args])](#pageevalselector-pagefunction-args)
|
||||
- [page.$eval(selector, pageFunction[, ...args])](#pageevalselector-pagefunction-args-1)
|
||||
- [page.$wait(selector, pageFunction[, options[, ...args]])](#pagewaitselector-pagefunction-options-args)
|
||||
- [page.$wait(selector[, options])](#pagewaitselector-options)
|
||||
- [page.accessibility](#pageaccessibility)
|
||||
- [page.addScriptTag(options)](#pageaddscripttagoptions)
|
||||
- [page.addStyleTag(options)](#pageaddstyletagoptions)
|
||||
|
|
@ -683,23 +683,24 @@ const html = await page.$eval('.main-container', e => e.outerHTML);
|
|||
|
||||
Shortcut for [page.mainFrame().$eval(selector, pageFunction)](#frameevalselector-pagefunction-args).
|
||||
|
||||
#### page.$wait(selector, pageFunction[, options[, ...args]])
|
||||
- `selector` <[string]> A selector to query page for
|
||||
- `pageFunction` <[function]\([Element]\)> Function to be evaluated in browser context
|
||||
- `options` <[Object]> Optional waiting parameters
|
||||
- `polling` <[number]|"raf"|"mutation"> An interval at which the `pageFunction` is executed, defaults to `raf`. If `polling` is a number, then it is treated as an interval in milliseconds at which the function would be executed. If `polling` is a string, then it can be one of the following values:
|
||||
- `'raf'` - to constantly execute `pageFunction` in `requestAnimationFrame` callback. This is the tightest polling mode which is suitable to observe styling changes.
|
||||
- `'mutation'` - to execute `pageFunction` on every DOM mutation.
|
||||
- `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.
|
||||
- `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction`
|
||||
- returns: <[Promise]<[JSHandle]>> Promise which resolves to a JSHandle of the success value
|
||||
#### page.$wait(selector[, options])
|
||||
- `selector` <[string]> A selector of an element to wait for
|
||||
- `options` <[Object]>
|
||||
- `visibility` <"visible"|"hidden"|"any"> Wait for element to become visible (`visible`), hidden (`hidden`), present in dom (`any`). Defaults to `any`.
|
||||
- `timeout` <[number]> Maximum time in milliseconds, defaults to 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 selector string is added to DOM. Resolves to `null` if waiting for `hidden: true` and selector is not found in DOM.
|
||||
|
||||
This method runs `document.querySelector` within the page and passes it as the first argument to `pageFunction`. If there's no element matching `selector`, the method throws an error.
|
||||
Wait for the `selector` to appear in page. If at the moment of calling
|
||||
the method the `selector` already exists, the method will return
|
||||
immediately. If the selector doesn't appear after the `timeout` milliseconds of waiting, the function will throw.
|
||||
|
||||
If `pageFunction` returns a [Promise], then `page.$wait` would wait for the promise to resolve and return its value. The function
|
||||
is being called on the element periodically until either timeout expires or the function returns the truthy value.
|
||||
This method works across navigations:
|
||||
```js
|
||||
const handle = await page.$wait(selector);
|
||||
await handle.click();
|
||||
```
|
||||
|
||||
Shortcut for [page.mainFrame().$wait(selector, pageFunction[, options[, ...args]])](#framewaitselector-pagefunction-options-args).
|
||||
This is a shortcut to [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options).
|
||||
|
||||
#### page.accessibility
|
||||
- returns: <[Accessibility]>
|
||||
|
|
@ -1668,7 +1669,7 @@ An example of getting text from an iframe element:
|
|||
- [frame.$$(selector)](#frameselector-1)
|
||||
- [frame.$$eval(selector, pageFunction[, ...args])](#frameevalselector-pagefunction-args)
|
||||
- [frame.$eval(selector, pageFunction[, ...args])](#frameevalselector-pagefunction-args-1)
|
||||
- [frame.$wait(selector, pageFunction[, options[, ...args]])](#framewaitselector-pagefunction-options-args)
|
||||
- [frame.$wait(selector[, options])](#framewaitselector-options)
|
||||
- [frame.addScriptTag(options)](#frameaddscripttagoptions)
|
||||
- [frame.addStyleTag(options)](#frameaddstyletagoptions)
|
||||
- [frame.check(selector, [options])](#framecheckselector-options)
|
||||
|
|
@ -1744,21 +1745,24 @@ const preloadHref = await frame.$eval('link[rel=preload]', el => el.href);
|
|||
const html = await frame.$eval('.main-container', e => e.outerHTML);
|
||||
```
|
||||
|
||||
#### frame.$wait(selector, pageFunction[, options[, ...args]])
|
||||
- `selector` <[string]> A selector to query page for
|
||||
- `pageFunction` <[function]\([Element]\)> Function to be evaluated in browser context
|
||||
- `options` <[Object]> Optional waiting parameters
|
||||
- `polling` <[number]|"raf"|"mutation"> An interval at which the `pageFunction` is executed, defaults to `raf`. If `polling` is a number, then it is treated as an interval in milliseconds at which the function would be executed. If `polling` is a string, then it can be one of the following values:
|
||||
- `'raf'` - to constantly execute `pageFunction` in `requestAnimationFrame` callback. This is the tightest polling mode which is suitable to observe styling changes.
|
||||
- `'mutation'` - to execute `pageFunction` on every DOM mutation.
|
||||
- `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.
|
||||
- `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction`
|
||||
- returns: <[Promise]<[JSHandle]>> Promise which resolves to a JSHandle of the success value
|
||||
#### frame.$wait(selector[, options])
|
||||
- `selector` <[string]> A selector of an element to wait for
|
||||
- `options` <[Object]>
|
||||
- `visibility` <"visible"|"hidden"|"any"> Wait for element to become visible (`visible`), hidden (`hidden`), present in dom (`any`). Defaults to `any`.
|
||||
- `timeout` <[number]> Maximum time in milliseconds, defaults to 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 selector string is added to DOM. Resolves to `null` if waiting for `hidden: true` and selector is not found in DOM.
|
||||
|
||||
This method runs `document.querySelector` within the frame and passes it as the first argument to `pageFunction`. If there's no element matching `selector`, the method throws an error.
|
||||
Wait for the `selector` to appear in page. If at the moment of calling
|
||||
the method the `selector` already exists, the method will return
|
||||
immediately. If the selector doesn't appear after the `timeout` milliseconds of waiting, the function will throw.
|
||||
|
||||
If `pageFunction` returns a [Promise], then `page.$wait` would wait for the promise to resolve and return its value. The function
|
||||
is being called on the element periodically until either timeout expires or the function returns the truthy value.
|
||||
This method works across navigations:
|
||||
```js
|
||||
const handle = await page.$wait(selector);
|
||||
await handle.click();
|
||||
```
|
||||
|
||||
This is a shortcut to [frame.waitForSelector(selector[, options])](#framewaitforselectorselector-options).
|
||||
|
||||
#### frame.addScriptTag(options)
|
||||
- `options` <[Object]>
|
||||
|
|
|
|||
|
|
@ -620,6 +620,10 @@ export class Frame {
|
|||
return handle;
|
||||
}
|
||||
|
||||
async $wait(selector: string, options?: types.TimeoutOptions & { visibility?: types.Visibility }): Promise<dom.ElementHandle<Element> | null> {
|
||||
return this.waitForSelector(selector, options);
|
||||
}
|
||||
|
||||
$eval: types.$Eval = async (selector, pageFunction, ...args) => {
|
||||
const context = await this._mainContext();
|
||||
const elementHandle = await context._$(selector);
|
||||
|
|
@ -938,12 +942,6 @@ export class Frame {
|
|||
return this._scheduleRerunnableTask(task, 'main', options.timeout);
|
||||
}
|
||||
|
||||
$wait: types.$Wait = async (selector, pageFunction, options, ...args) => {
|
||||
options = { timeout: this._page._timeoutSettings.timeout(), ...(options || {}) };
|
||||
const task = dom.waitForFunctionTask(selector, pageFunction, options, ...args);
|
||||
return this._scheduleRerunnableTask(task, 'main', options.timeout) as any;
|
||||
}
|
||||
|
||||
async title(): Promise<string> {
|
||||
const context = await this._utilityContext();
|
||||
return context.evaluate(() => document.title);
|
||||
|
|
|
|||
|
|
@ -215,6 +215,10 @@ export class Page extends platform.EventEmitter {
|
|||
return this.mainFrame().waitForSelector(selector, options);
|
||||
}
|
||||
|
||||
async $wait(selector: string, options?: types.TimeoutOptions & { visibility?: types.Visibility }): Promise<dom.ElementHandle<Element> | null> {
|
||||
return this.waitForSelector(selector, options);
|
||||
}
|
||||
|
||||
evaluateHandle: types.EvaluateHandle = async (pageFunction, ...args) => {
|
||||
return this.mainFrame().evaluateHandle(pageFunction, ...args as any);
|
||||
}
|
||||
|
|
@ -529,10 +533,6 @@ export class Page extends platform.EventEmitter {
|
|||
return this.mainFrame().waitForFunction(pageFunction, options, ...args);
|
||||
}
|
||||
|
||||
$wait: types.$Wait = async (selector, pageFunction, options, ...args) => {
|
||||
return this.mainFrame().$wait(selector, pageFunction, options, ...args as any);
|
||||
}
|
||||
|
||||
workers(): Worker[] {
|
||||
return [...this._workers.values()];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ export type Evaluate = <Args extends any[], R>(pageFunction: PageFunction<Args,
|
|||
export type EvaluateHandle = <Args extends any[], R>(pageFunction: PageFunction<Args, R>, ...args: Boxed<Args>) => Promise<Handle<R>>;
|
||||
export type $Eval = <Args extends any[], R>(selector: string, pageFunction: PageFunctionOn<Element, Args, R>, ...args: Boxed<Args>) => Promise<R>;
|
||||
export type $$Eval = <Args extends any[], R>(selector: string, pageFunction: PageFunctionOn<Element[], Args, R>, ...args: Boxed<Args>) => Promise<R>;
|
||||
export type $Wait = <Args extends any[], R>(selector: string, pageFunction: PageFunctionOn<Element | undefined, Args, R>, options?: WaitForFunctionOptions, ...args: Boxed<Args>) => Promise<Handle<R>>;
|
||||
export type EvaluateOn<T> = <Args extends any[], R>(pageFunction: PageFunctionOn<T, Args, R>, ...args: Boxed<Args>) => Promise<R>;
|
||||
export type EvaluateHandleOn<T> = <Args extends any[], R>(pageFunction: PageFunctionOn<T, Args, R>, ...args: Boxed<Args>) => Promise<Handle<R>>;
|
||||
|
||||
|
|
|
|||
|
|
@ -208,39 +208,8 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
});
|
||||
});
|
||||
|
||||
describe('Frame.$wait', function() {
|
||||
it('should accept arguments', async({page, server}) => {
|
||||
await page.setContent('<div></div>');
|
||||
const result = await page.$wait('div', (e, foo, bar) => e.nodeName + foo + bar, {}, 'foo1', 'bar2');
|
||||
expect(await result.jsonValue()).toBe('DIVfoo1bar2');
|
||||
});
|
||||
it('should query selector constantly', async({page, server}) => {
|
||||
await page.setContent('<div></div>');
|
||||
let done = null;
|
||||
const resultPromise = page.$wait('span', e => e).then(r => done = r);
|
||||
expect(done).toBe(null);
|
||||
await page.setContent('<section></section>');
|
||||
expect(done).toBe(null);
|
||||
await page.setContent('<span>text</span>');
|
||||
await resultPromise;
|
||||
expect(done).not.toBe(null);
|
||||
expect(await done.evaluate(e => e.textContent)).toBe('text');
|
||||
});
|
||||
it('should be able to wait for removal', async({page}) => {
|
||||
await page.setContent('<div></div>');
|
||||
let done = null;
|
||||
const resultPromise = page.$wait('div', e => !e).then(r => done = r);
|
||||
expect(done).toBe(null);
|
||||
await page.setContent('<section></section>');
|
||||
await resultPromise;
|
||||
expect(done).not.toBe(null);
|
||||
expect(await done.jsonValue()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Frame.waitForSelector', function() {
|
||||
const addElement = tag => document.body.appendChild(document.createElement(tag));
|
||||
|
||||
it('should immediately resolve promise if node exists', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const frame = page.mainFrame();
|
||||
|
|
@ -248,7 +217,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
await frame.evaluate(addElement, 'div');
|
||||
await frame.waitForSelector('div');
|
||||
});
|
||||
|
||||
it('should work with removed MutationObserver', async({page, server}) => {
|
||||
await page.evaluate(() => delete window.MutationObserver);
|
||||
const [handle] = await Promise.all([
|
||||
|
|
@ -257,7 +225,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
]);
|
||||
expect(await page.evaluate(x => x.textContent, handle)).toBe('anything');
|
||||
});
|
||||
|
||||
it('should resolve promise when node is added', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const frame = page.mainFrame();
|
||||
|
|
@ -268,7 +235,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
const tagName = await eHandle.getProperty('tagName').then(e => e.jsonValue());
|
||||
expect(tagName).toBe('DIV');
|
||||
});
|
||||
|
||||
it('should work when node is added through innerHTML', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const watchdog = page.waitForSelector('h3 div');
|
||||
|
|
@ -276,7 +242,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
await page.evaluate(() => document.querySelector('span').innerHTML = '<h3><div></div></h3>');
|
||||
await watchdog;
|
||||
});
|
||||
|
||||
it('Page.$ waitFor is shortcut for main frame', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
||||
|
|
@ -287,7 +252,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
const eHandle = await watchdog;
|
||||
expect(await eHandle.ownerFrame()).toBe(page.mainFrame());
|
||||
});
|
||||
|
||||
it('should run in specified frame', async({page, server}) => {
|
||||
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
||||
await utils.attachFrame(page, 'frame2', server.EMPTY_PAGE);
|
||||
|
|
@ -299,7 +263,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
const eHandle = await waitForSelectorPromise;
|
||||
expect(await eHandle.ownerFrame()).toBe(frame2);
|
||||
});
|
||||
|
||||
it('should throw when frame is detached', async({page, server}) => {
|
||||
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
||||
const frame = page.frames()[1];
|
||||
|
|
@ -391,7 +354,6 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
expect(error).toBeTruthy();
|
||||
expect(error.message).toContain('waiting for selector "[hidden] div" failed: timeout');
|
||||
});
|
||||
|
||||
it('should respond to node attribute mutation', async({page, server}) => {
|
||||
let divFound = false;
|
||||
const waitForSelector = page.waitForSelector('.zombo').then(() => divFound = true);
|
||||
|
|
@ -441,6 +403,11 @@ module.exports.describe = function({testRunner, expect, product, playwright, FFO
|
|||
const tagName = await eHandle.getProperty('tagName').then(e => e.jsonValue());
|
||||
expect(tagName).toBe('SPAN');
|
||||
});
|
||||
it('$wait alias should work', async({page, server}) => {
|
||||
await page.setContent('<section>test</section>');
|
||||
const handle = await page.$wait('section');
|
||||
expect(await handle.evaluate(e => e.textContent)).toBe('test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Frame.waitForSelector xpath', function() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue