fix: support async functions as an argument for waitForFunction (#5682)

This commit is contained in:
Islam ElHakmi 2020-05-19 09:09:31 +02:00 committed by GitHub
parent e6c22dae05
commit caaf4d2086
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 12 deletions

View File

@ -2098,6 +2098,22 @@ const selector = '.foo';
await page.waitForFunction(selector => !!document.querySelector(selector), {}, selector); await page.waitForFunction(selector => !!document.querySelector(selector), {}, selector);
``` ```
The predicate of `page.waitForFunction` can be asynchronous too:
```js
const username = 'github-username';
await page.waitForFunction(async username => {
const githubResponse = await fetch(`https://api.github.com/users/${username}`);
const githubUser = await githubResponse.json();
// show the avatar
const img = document.createElement('img');
img.src = githubUser.avatar_url;
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
}, {}, username);
```
Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args). Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args).
#### page.waitForNavigation([options]) #### page.waitForNavigation([options])

View File

@ -692,18 +692,18 @@ async function waitForPredicatePageFunction(
/** /**
* @return {!Promise<*>} * @return {!Promise<*>}
*/ */
function pollMutation(): Promise<unknown> { async function pollMutation(): Promise<unknown> {
const success = predicate(...args); const success = await predicate(...args);
if (success) return Promise.resolve(success); if (success) return Promise.resolve(success);
let fulfill; let fulfill;
const result = new Promise((x) => (fulfill = x)); const result = new Promise((x) => (fulfill = x));
const observer = new MutationObserver(() => { const observer = new MutationObserver(async () => {
if (timedOut) { if (timedOut) {
observer.disconnect(); observer.disconnect();
fulfill(); fulfill();
} }
const success = predicate(...args); const success = await predicate(...args);
if (success) { if (success) {
observer.disconnect(); observer.disconnect();
fulfill(success); fulfill(success);
@ -717,35 +717,35 @@ async function waitForPredicatePageFunction(
return result; return result;
} }
function pollRaf(): Promise<unknown> { async function pollRaf(): Promise<unknown> {
let fulfill; let fulfill;
const result = new Promise((x) => (fulfill = x)); const result = new Promise((x) => (fulfill = x));
onRaf(); await onRaf();
return result; return result;
function onRaf(): void { async function onRaf(): Promise<unknown> {
if (timedOut) { if (timedOut) {
fulfill(); fulfill();
return; return;
} }
const success = predicate(...args); const success = await predicate(...args);
if (success) fulfill(success); if (success) fulfill(success);
else requestAnimationFrame(onRaf); else requestAnimationFrame(onRaf);
} }
} }
function pollInterval(pollInterval: number): Promise<unknown> { async function pollInterval(pollInterval: number): Promise<unknown> {
let fulfill; let fulfill;
const result = new Promise((x) => (fulfill = x)); const result = new Promise((x) => (fulfill = x));
onTimeout(); await onTimeout();
return result; return result;
function onTimeout(): void { async function onTimeout(): Promise<unknown> {
if (timedOut) { if (timedOut) {
fulfill(); fulfill();
return; return;
} }
const success = predicate(...args); const success = await predicate(...args);
if (success) fulfill(success); if (success) fulfill(success);
else setTimeout(onTimeout, pollInterval); else setTimeout(onTimeout, pollInterval);
} }

View File

@ -138,6 +138,22 @@ describe('waittask specs', function () {
await watchdog; await watchdog;
expect(Date.now() - startTime).not.toBeLessThan(polling / 2); expect(Date.now() - startTime).not.toBeLessThan(polling / 2);
}); });
it('should poll on interval async', async () => {
const { page } = getTestState();
let success = false;
const startTime = Date.now();
const polling = 100;
const watchdog = page
.waitForFunction(async () => window.__FOO === 'hit', { polling })
.then(() => (success = true));
await page.evaluate(async () => (window.__FOO = 'hit'));
expect(success).toBe(false);
await page.evaluate(async () =>
document.body.appendChild(document.createElement('div'))
);
await watchdog;
expect(Date.now() - startTime).not.toBeLessThan(polling / 2);
});
it('should poll on mutation', async () => { it('should poll on mutation', async () => {
const { page } = getTestState(); const { page } = getTestState();
@ -152,6 +168,22 @@ describe('waittask specs', function () {
); );
await watchdog; await watchdog;
}); });
it('should poll on mutation async', async () => {
const { page } = getTestState();
let success = false;
const watchdog = page
.waitForFunction(async () => window.__FOO === 'hit', {
polling: 'mutation',
})
.then(() => (success = true));
await page.evaluate(async () => (window.__FOO = 'hit'));
expect(success).toBe(false);
await page.evaluate(async () =>
document.body.appendChild(document.createElement('div'))
);
await watchdog;
});
it('should poll on raf', async () => { it('should poll on raf', async () => {
const { page } = getTestState(); const { page } = getTestState();
@ -161,6 +193,18 @@ describe('waittask specs', function () {
await page.evaluate(() => (window.__FOO = 'hit')); await page.evaluate(() => (window.__FOO = 'hit'));
await watchdog; await watchdog;
}); });
it('should poll on raf async', async () => {
const { page } = getTestState();
const watchdog = page.waitForFunction(
async () => window.__FOO === 'hit',
{
polling: 'raf',
}
);
await page.evaluate(async () => (window.__FOO = 'hit'));
await watchdog;
});
itFailsFirefox('should work with strict CSP policy', async () => { itFailsFirefox('should work with strict CSP policy', async () => {
const { page, server } = getTestState(); const { page, server } = getTestState();