mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(page): introduce waitForRequest and waitForResponse methods (#2776)
This patch introduces `page.waitForRequest` and `page.waitForResponse` helper methods. Fixes #2362
This commit is contained in:
parent
3ebbf125ff
commit
726c8dc046
26
docs/api.md
26
docs/api.md
@ -128,6 +128,8 @@
|
||||
* [page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#pagewaitforselectororfunctionortimeout-options-args)
|
||||
* [page.waitForFunction(pageFunction[, options[, ...args]])](#pagewaitforfunctionpagefunction-options-args)
|
||||
* [page.waitForNavigation(options)](#pagewaitfornavigationoptions)
|
||||
* [page.waitForRequest(urlOrPredicate, options)](#pagewaitforrequesturlorpredicate-options)
|
||||
* [page.waitForResponse(urlOrPredicate, options)](#pagewaitforresponseurlorpredicate-options)
|
||||
* [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options)
|
||||
* [page.waitForXPath(xpath[, options])](#pagewaitforxpathxpath-options)
|
||||
* [page.workers()](#pageworkers)
|
||||
@ -1572,6 +1574,30 @@ await navigationPromise; // The navigationPromise resolves after navigation has
|
||||
|
||||
**NOTE** Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is considered a navigation.
|
||||
|
||||
#### page.waitForRequest(urlOrPredicate, options)
|
||||
- `urlOrPredicate` <[string]|[Function]> A URL or predicate to wait for.
|
||||
- `options` <[Object]> Optional waiting parameters
|
||||
- `timeout` <[number]> Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout.
|
||||
- returns: <[Promise]<[Request]>> Promise which resolves to the matched request.
|
||||
|
||||
```js
|
||||
const firstRequest = await page.waitForRequest('http://example.com/resource');
|
||||
const finalRequest = await page.waitForRequest(request => request.url() === 'http://example.com' && request.method() === 'GET');
|
||||
return firstRequest.url();
|
||||
```
|
||||
|
||||
#### page.waitForResponse(urlOrPredicate, options)
|
||||
- `urlOrPredicate` <[string]|[Function]> A URL or predicate to wait for.
|
||||
- `options` <[Object]> Optional waiting parameters
|
||||
- `timeout` <[number]> Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout.
|
||||
- returns: <[Promise]<[Response]>> Promise which resolves to the matched response.
|
||||
|
||||
```js
|
||||
const firstResponse = await page.waitForResponse('https://example.com/resource');
|
||||
const finalResponse = await page.waitForResponse(response => response.url() === 'https://example.com' && response.status() === 200);
|
||||
return finalResponse.ok();
|
||||
```
|
||||
|
||||
#### page.waitForSelector(selector[, options])
|
||||
- `selector` <[string]> A [selector] of an element to wait for
|
||||
- `options` <[Object]> Optional waiting parameters
|
||||
|
32
lib/Page.js
32
lib/Page.js
@ -632,6 +632,38 @@ class Page extends EventEmitter {
|
||||
return responses.get(this.mainFrame().url()) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(string|Function)} urlOrPredicate
|
||||
* @param {!Object=} options
|
||||
* @return {!Promise<!Puppeteer.Request>}
|
||||
*/
|
||||
async waitForRequest(urlOrPredicate, options = {}) {
|
||||
const timeout = typeof options.timeout === 'number' ? options.timeout : 30000;
|
||||
return helper.waitForEvent(this._networkManager, NetworkManager.Events.Request, request => {
|
||||
if (helper.isString(urlOrPredicate))
|
||||
return (urlOrPredicate === request.url());
|
||||
if (typeof urlOrPredicate === 'function')
|
||||
return !!(urlOrPredicate(request));
|
||||
return false;
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(string|Function)} urlOrPredicate
|
||||
* @param {!Object=} options
|
||||
* @return {!Promise<!Puppeteer.Response>}
|
||||
*/
|
||||
async waitForResponse(urlOrPredicate, options = {}) {
|
||||
const timeout = typeof options.timeout === 'number' ? options.timeout : 30000;
|
||||
return helper.waitForEvent(this._networkManager, NetworkManager.Events.Response, response => {
|
||||
if (helper.isString(urlOrPredicate))
|
||||
return (urlOrPredicate === response.url());
|
||||
if (typeof urlOrPredicate === 'function')
|
||||
return !!(urlOrPredicate(response));
|
||||
return false;
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Object=} options
|
||||
* @return {!Promise<?Puppeteer.Response>}
|
||||
|
@ -240,6 +240,37 @@ class Helper {
|
||||
}
|
||||
return promisified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!NodeJS.EventEmitter} emitter
|
||||
* @param {string} eventName
|
||||
* @param {function} predicate
|
||||
* @return {!Promise}
|
||||
*/
|
||||
static waitForEvent(emitter, eventName, predicate, timeout) {
|
||||
let eventTimeout, resolveCallback, rejectCallback;
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
resolveCallback = resolve;
|
||||
rejectCallback = reject;
|
||||
});
|
||||
const listener = Helper.addEventListener(emitter, eventName, event => {
|
||||
if (!predicate(event))
|
||||
return;
|
||||
cleanup();
|
||||
resolveCallback(event);
|
||||
});
|
||||
if (timeout) {
|
||||
eventTimeout = setTimeout(() => {
|
||||
cleanup();
|
||||
rejectCallback(new Error('Timeout exceeded while waiting for event'));
|
||||
}, timeout);
|
||||
}
|
||||
function cleanup() {
|
||||
Helper.removeEventListeners([listener]);
|
||||
clearTimeout(eventTimeout);
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -786,6 +786,89 @@ module.exports.addTests = function({testRunner, expect, puppeteer, DeviceDescrip
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.waitForRequest', function() {
|
||||
it('should work', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest(server.PREFIX + '/404'),
|
||||
page.evaluate(() => fetch('/404', {method: 'GET'}))
|
||||
]);
|
||||
expect(request.method()).toBe('GET');
|
||||
expect(request.url()).toBe(server.PREFIX + '/404');
|
||||
});
|
||||
it('should work with regex pattern', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest(request => new RegExp(`${server.PREFIX}/(200|404)`).test(request.url())),
|
||||
page.evaluate(() => fetch('/404', {method: 'GET'}))
|
||||
]);
|
||||
expect(request.method()).toBe('GET');
|
||||
expect(request.url()).toBe(server.PREFIX + '/404');
|
||||
});
|
||||
it('should work with predicate', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest(request => request.url() === server.PREFIX + '/404' && request.method() === 'PATCH'),
|
||||
page.evaluate(() => fetch('/404', {method: 'PATCH'}))
|
||||
]);
|
||||
expect(request.method()).toBe('PATCH');
|
||||
expect(request.url()).toBe(server.PREFIX + '/404');
|
||||
});
|
||||
it('should work with no timeout', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest(server.PREFIX + '/404', { timeout: 0}),
|
||||
page.waitFor(50),
|
||||
page.evaluate(() => fetch('/404', {method: 'GET'}))
|
||||
]);
|
||||
expect(request.method()).toBe('GET');
|
||||
expect(request.url()).toBe(server.PREFIX + '/404');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.waitForResponse', function() {
|
||||
it('should work', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(server.PREFIX + '/grid.html'),
|
||||
page.waitFor(100),
|
||||
page.evaluate(() => fetch('/grid.html', {method: 'GET'}))
|
||||
]);
|
||||
expect(response.ok()).toBe(true);
|
||||
expect(response.url()).toBe(server.PREFIX + '/grid.html');
|
||||
});
|
||||
it('should work with regex', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(response => new RegExp(`${server.PREFIX}/(get|grid.html)`).test(response.url())),
|
||||
page.waitFor(100),
|
||||
page.evaluate(() => fetch('/grid.html', {method: 'GET'}))
|
||||
]);
|
||||
expect(response.ok()).toBe(true);
|
||||
expect(response.url()).toBe(server.PREFIX + '/grid.html');
|
||||
});
|
||||
it('should work with predicate', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(response => response.url() === server.PREFIX + '/grid.html' && response.status() === 200),
|
||||
page.waitFor(100),
|
||||
page.evaluate(() => fetch('/grid.html', {method: 'PATCH'}))
|
||||
]);
|
||||
expect(response.ok()).toBe(true);
|
||||
expect(response.url()).toBe(server.PREFIX + '/grid.html');
|
||||
});
|
||||
it('should work with no timeout', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [response] = await Promise.all([
|
||||
page.waitForResponse(server.PREFIX + '/grid.html', { timeout: 0}),
|
||||
page.waitFor(50),
|
||||
page.evaluate(() => fetch('/grid.html', {method: 'GET'}))
|
||||
]);
|
||||
expect(response.ok()).toBe(true);
|
||||
expect(response.url()).toBe(server.PREFIX + '/grid.html');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.goBack', function() {
|
||||
it('should work', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
Loading…
Reference in New Issue
Block a user