feat(firefox): Page.waitForRequest/Page.waitForResponse (#3989)
Drive-by: refactor `Request.frame()` tests into a separate test suite.
This commit is contained in:
parent
afb9355b15
commit
1890dc04ba
@ -19,11 +19,11 @@ class NetworkManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onRequestWillBeSent(event) {
|
_onRequestWillBeSent(event) {
|
||||||
const frame = this._frameManager && event.frameId ? this._frameManager.frame(event.frameId) : null;
|
const redirected = event.redirectedFrom ? this._requests.get(event.redirectedFrom) : null;
|
||||||
|
const frame = redirected ? redirected.frame() : (this._frameManager && event.frameId ? this._frameManager.frame(event.frameId) : null);
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return;
|
return;
|
||||||
let redirectChain = [];
|
let redirectChain = [];
|
||||||
const redirected = event.redirectedFrom ? this._requests.get(event.redirectedFrom) : null;
|
|
||||||
if (redirected) {
|
if (redirected) {
|
||||||
redirectChain = redirected._redirectChain;
|
redirectChain = redirected._redirectChain;
|
||||||
redirectChain.push(redirected);
|
redirectChain.push(redirected);
|
||||||
|
@ -94,6 +94,42 @@ class Page extends EventEmitter {
|
|||||||
this._viewport = null;
|
this._viewport = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {(string|Function)} urlOrPredicate
|
||||||
|
* @param {!{timeout?: number}=} options
|
||||||
|
* @return {!Promise<!Puppeteer.Request>}
|
||||||
|
*/
|
||||||
|
async waitForRequest(urlOrPredicate, options = {}) {
|
||||||
|
const {
|
||||||
|
timeout = this._timeoutSettings.timeout(),
|
||||||
|
} = options;
|
||||||
|
return helper.waitForEvent(this._networkManager, Events.NetworkManager.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 {!{timeout?: number}=} options
|
||||||
|
* @return {!Promise<!Puppeteer.Response>}
|
||||||
|
*/
|
||||||
|
async waitForResponse(urlOrPredicate, options = {}) {
|
||||||
|
const {
|
||||||
|
timeout = this._timeoutSettings.timeout(),
|
||||||
|
} = options;
|
||||||
|
return helper.waitForEvent(this._networkManager, Events.NetworkManager.Response, response => {
|
||||||
|
if (helper.isString(urlOrPredicate))
|
||||||
|
return (urlOrPredicate === response.url());
|
||||||
|
if (typeof urlOrPredicate === 'function')
|
||||||
|
return !!(urlOrPredicate(response));
|
||||||
|
return false;
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} timeout
|
* @param {number} timeout
|
||||||
*/
|
*/
|
||||||
|
@ -116,6 +116,37 @@ class Helper {
|
|||||||
listeners.splice(0, listeners.length);
|
listeners.splice(0, listeners.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!NodeJS.EventEmitter} emitter
|
||||||
|
* @param {(string|symbol)} 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 TimeoutError('Timeout exceeded while waiting for event'));
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
function cleanup() {
|
||||||
|
Helper.removeEventListeners([listener]);
|
||||||
|
clearTimeout(eventTimeout);
|
||||||
|
}
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T
|
||||||
* @param {!Promise<T>} promise
|
* @param {!Promise<T>} promise
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"node": ">=8.9.4"
|
"node": ">=8.9.4"
|
||||||
},
|
},
|
||||||
"puppeteer": {
|
"puppeteer": {
|
||||||
"firefox_revision": "668e06245e539adf0d453b447401b8eb6e9acb44"
|
"firefox_revision": "ad27e01304952cb0ff0b2817016b0e9f31d7f8fa"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install": "node install.js",
|
"install": "node install.js",
|
||||||
|
@ -280,7 +280,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) {
|
|||||||
});
|
});
|
||||||
it_fails_ffox('should navigate to dataURL and fire dataURL requests', async({page, server}) => {
|
it_fails_ffox('should navigate to dataURL and fire dataURL requests', async({page, server}) => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
page.on('request', request => requests.push(request));
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
const dataURL = 'data:text/html,<div>yo</div>';
|
const dataURL = 'data:text/html,<div>yo</div>';
|
||||||
const response = await page.goto(dataURL);
|
const response = await page.goto(dataURL);
|
||||||
expect(response.status()).toBe(200);
|
expect(response.status()).toBe(200);
|
||||||
@ -289,7 +289,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) {
|
|||||||
});
|
});
|
||||||
it_fails_ffox('should navigate to URL with hash and fire requests without hash', async({page, server}) => {
|
it_fails_ffox('should navigate to URL with hash and fire requests without hash', async({page, server}) => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
page.on('request', request => requests.push(request));
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
const response = await page.goto(server.EMPTY_PAGE + '#hash');
|
const response = await page.goto(server.EMPTY_PAGE + '#hash');
|
||||||
expect(response.status()).toBe(200);
|
expect(response.status()).toBe(200);
|
||||||
expect(response.url()).toBe(server.EMPTY_PAGE);
|
expect(response.url()).toBe(server.EMPTY_PAGE);
|
||||||
|
@ -23,6 +23,56 @@ module.exports.addTests = function({testRunner, expect}) {
|
|||||||
const {it, fit, xit, it_fails_ffox} = testRunner;
|
const {it, fit, xit, it_fails_ffox} = testRunner;
|
||||||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
||||||
|
|
||||||
|
describe('Page.Events.Request', function() {
|
||||||
|
it('should fire for navigation requests', async({page, server}) => {
|
||||||
|
const requests = [];
|
||||||
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(requests.length).toBe(1);
|
||||||
|
});
|
||||||
|
it('should fire for iframes', async({page, server}) => {
|
||||||
|
const requests = [];
|
||||||
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
||||||
|
expect(requests.length).toBe(2);
|
||||||
|
});
|
||||||
|
it('should fire for fetches', async({page, server}) => {
|
||||||
|
const requests = [];
|
||||||
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
||||||
|
expect(requests.length).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Request.frame', function() {
|
||||||
|
it('should work for main frame navigation request', async({page, server}) => {
|
||||||
|
const requests = [];
|
||||||
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(requests.length).toBe(1);
|
||||||
|
expect(requests[0].frame()).toBe(page.mainFrame());
|
||||||
|
});
|
||||||
|
it('should work for subframe navigation request', async({page, server}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
const requests = [];
|
||||||
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
|
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
||||||
|
expect(requests.length).toBe(1);
|
||||||
|
expect(requests[0].frame()).toBe(page.frames()[1]);
|
||||||
|
});
|
||||||
|
it('should work for fetch requests', async({page, server}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
let requests = [];
|
||||||
|
page.on('request', request => !utils.isFavicon(request) && requests.push(request));
|
||||||
|
await page.evaluate(() => fetch('/digits/1.png'));
|
||||||
|
requests = requests.filter(request => !request.url().includes('favicon'));
|
||||||
|
expect(requests.length).toBe(1);
|
||||||
|
expect(requests[0].frame()).toBe(page.mainFrame());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Network Events', function() {
|
describe('Network Events', function() {
|
||||||
it('Page.Events.Request', async({page, server}) => {
|
it('Page.Events.Request', async({page, server}) => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
@ -632,22 +682,6 @@ module.exports.addTests = function({testRunner, expect}) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.Events.Request', function() {
|
|
||||||
it('should fire', async({page, server}) => {
|
|
||||||
const requests = [];
|
|
||||||
page.on('request', request => requests.push(request));
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
|
|
||||||
expect(requests.length).toBe(2);
|
|
||||||
expect(requests[0].url()).toBe(server.EMPTY_PAGE);
|
|
||||||
expect(requests[0].frame() === page.mainFrame()).toBe(true);
|
|
||||||
expect(requests[0].frame().url()).toBe(server.EMPTY_PAGE);
|
|
||||||
expect(requests[1].url()).toBe(server.EMPTY_PAGE);
|
|
||||||
expect(requests[1].frame() === page.frames()[1]).toBe(true);
|
|
||||||
expect(requests[1].frame().url()).toBe(server.EMPTY_PAGE);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe_fails_ffox('Page.setExtraHTTPHeaders', function() {
|
describe_fails_ffox('Page.setExtraHTTPHeaders', function() {
|
||||||
it('should work', async({page, server}) => {
|
it('should work', async({page, server}) => {
|
||||||
await page.setExtraHTTPHeaders({
|
await page.setExtraHTTPHeaders({
|
||||||
|
@ -423,7 +423,7 @@ module.exports.addTests = function({testRunner, expect, headless, Errors, Device
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe_fails_ffox('Page.waitForRequest', function() {
|
describe('Page.waitForRequest', function() {
|
||||||
it('should work', async({page, server}) => {
|
it('should work', async({page, server}) => {
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
const [request] = await Promise.all([
|
const [request] = await Promise.all([
|
||||||
@ -473,7 +473,7 @@ module.exports.addTests = function({testRunner, expect, headless, Errors, Device
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe_fails_ffox('Page.waitForResponse', function() {
|
describe('Page.waitForResponse', function() {
|
||||||
it('should work', async({page, server}) => {
|
it('should work', async({page, server}) => {
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
const [response] = await Promise.all([
|
const [response] = await Promise.all([
|
||||||
|
@ -97,6 +97,10 @@ const utils = module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isFavicon: function(request) {
|
||||||
|
return request.url().includes('favicon.ico');
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Page} page
|
* @param {!Page} page
|
||||||
* @param {string} frameId
|
* @param {string} frameId
|
||||||
|
Loading…
Reference in New Issue
Block a user