mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: add support for async waitForTarget (#7885)
* feat: add support for async waitForTarget * fix: add timeout * fix: potential async bugs
This commit is contained in:
parent
543a4d44bc
commit
dbf0639822
@ -983,7 +983,7 @@ the method will return an array with all the targets in all browser contexts.
|
||||
|
||||
#### browser.waitForTarget(predicate[, options])
|
||||
|
||||
- `predicate` <[function]\([Target]\):[boolean]> A function to be run for every target
|
||||
- `predicate` <[function]\([Target]\):[boolean]|[Promise<boolean>]> A function to be run for every target
|
||||
- `options` <[Object]>
|
||||
- `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds.
|
||||
- returns: <[Promise]<[Target]>> Promise which resolves to the first target found that matches the `predicate` function.
|
||||
@ -1135,7 +1135,7 @@ An array of all active targets inside the browser context.
|
||||
|
||||
#### browserContext.waitForTarget(predicate[, options])
|
||||
|
||||
- `predicate` <[function]\([Target]\):[boolean]> A function to be run for every target
|
||||
- `predicate` <[function]\([Target]\):[boolean]|[Promise<boolean>]> A function to be run for every target
|
||||
- `options` <[Object]>
|
||||
- `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds.
|
||||
- returns: <[Promise]<[Target]>> Promise which resolves to the first target found that matches the `predicate` function.
|
||||
|
@ -114,7 +114,7 @@ class Browser extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function(!Target):boolean} predicate
|
||||
* @param {function(!Target):boolean|Promise<boolean>} predicate
|
||||
* @param {{timeout?: number}=} options
|
||||
* @return {!Promise<!Target>}
|
||||
*/
|
||||
@ -122,9 +122,6 @@ class Browser extends EventEmitter {
|
||||
const {
|
||||
timeout = 30000
|
||||
} = options;
|
||||
const existingTarget = this.targets().find(predicate);
|
||||
if (existingTarget)
|
||||
return existingTarget;
|
||||
let resolve;
|
||||
const targetPromise = new Promise(x => resolve = x);
|
||||
this.on(Events.Browser.TargetCreated, check);
|
||||
@ -132,7 +129,21 @@ class Browser extends EventEmitter {
|
||||
try {
|
||||
if (!timeout)
|
||||
return await targetPromise;
|
||||
return await helper.waitWithTimeout(targetPromise, 'target', timeout);
|
||||
return await helper.waitWithTimeout(
|
||||
Promise.race([
|
||||
targetPromise,
|
||||
(async () => {
|
||||
for (const target of this.targets()) {
|
||||
if (await predicate(target)) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
await targetPromise;
|
||||
})(),
|
||||
]),
|
||||
'target',
|
||||
timeout
|
||||
);
|
||||
} finally {
|
||||
this.removeListener(Events.Browser.TargetCreated, check);
|
||||
this.removeListener('targetchanged', check);
|
||||
@ -141,8 +152,8 @@ class Browser extends EventEmitter {
|
||||
/**
|
||||
* @param {!Target} target
|
||||
*/
|
||||
function check(target) {
|
||||
if (predicate(target))
|
||||
async function check(target) {
|
||||
if (await predicate(target))
|
||||
resolve(target);
|
||||
}
|
||||
}
|
||||
@ -334,7 +345,7 @@ class BrowserContext extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function(Target):boolean} predicate
|
||||
* @param {function(Target):boolean|Promise<boolean>} predicate
|
||||
* @param {{timeout?: number}=} options
|
||||
* @return {!Promise<Target>}
|
||||
*/
|
||||
|
@ -539,12 +539,10 @@ export class Browser extends EventEmitter {
|
||||
* ```
|
||||
*/
|
||||
async waitForTarget(
|
||||
predicate: (x: Target) => boolean,
|
||||
predicate: (x: Target) => boolean | Promise<boolean>,
|
||||
options: WaitForTargetOptions = {}
|
||||
): Promise<Target> {
|
||||
const { timeout = 30000 } = options;
|
||||
const existingTarget = this.targets().find(predicate);
|
||||
if (existingTarget) return existingTarget;
|
||||
let resolve: (value: Target | PromiseLike<Target>) => void;
|
||||
const targetPromise = new Promise<Target>((x) => (resolve = x));
|
||||
this.on(BrowserEmittedEvents.TargetCreated, check);
|
||||
@ -552,7 +550,17 @@ export class Browser extends EventEmitter {
|
||||
try {
|
||||
if (!timeout) return await targetPromise;
|
||||
return await helper.waitWithTimeout<Target>(
|
||||
Promise.race([
|
||||
targetPromise,
|
||||
(async () => {
|
||||
for (const target of this.targets()) {
|
||||
if (await predicate(target)) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
await targetPromise;
|
||||
})(),
|
||||
]),
|
||||
'target',
|
||||
timeout
|
||||
);
|
||||
@ -561,8 +569,8 @@ export class Browser extends EventEmitter {
|
||||
this.removeListener(BrowserEmittedEvents.TargetChanged, check);
|
||||
}
|
||||
|
||||
function check(target: Target): void {
|
||||
if (predicate(target)) resolve(target);
|
||||
async function check(target: Target): Promise<void> {
|
||||
if (await predicate(target)) resolve(target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -736,7 +744,7 @@ export class BrowserContext extends EventEmitter {
|
||||
* that matches the `predicate` function.
|
||||
*/
|
||||
waitForTarget(
|
||||
predicate: (x: Target) => boolean,
|
||||
predicate: (x: Target) => boolean | Promise<boolean>,
|
||||
options: { timeout?: number } = {}
|
||||
): Promise<Target> {
|
||||
return this._browser.waitForTarget(
|
||||
|
@ -67,6 +67,30 @@ describe('Target', function () {
|
||||
).toBe('Hello world');
|
||||
expect(await originalPage.$('body')).toBeTruthy();
|
||||
});
|
||||
itFailsFirefox('should be able to use async waitForTarget', async () => {
|
||||
const { page, server, context } = getTestState();
|
||||
|
||||
const [otherPage] = await Promise.all([
|
||||
context
|
||||
.waitForTarget((target) =>
|
||||
target
|
||||
.page()
|
||||
.then(
|
||||
(page) =>
|
||||
page.url() === server.CROSS_PROCESS_PREFIX + '/empty.html'
|
||||
)
|
||||
)
|
||||
.then((target) => target.page()),
|
||||
page.evaluate(
|
||||
(url: string) => window.open(url),
|
||||
server.CROSS_PROCESS_PREFIX + '/empty.html'
|
||||
),
|
||||
]);
|
||||
expect(otherPage.url()).toEqual(
|
||||
server.CROSS_PROCESS_PREFIX + '/empty.html'
|
||||
);
|
||||
expect(page).not.toEqual(otherPage);
|
||||
});
|
||||
itFailsFirefox(
|
||||
'should report when a new page is created and closed',
|
||||
async () => {
|
||||
|
Loading…
Reference in New Issue
Block a user