fix: convert all getters to methods (#1621)

The patch converts all the getters in the codebase into the methods.
For example, the `request.url` getter becomes the `request.url()`
method.

This is done in order to unify the API and make it more predictable.
The general rule for all further changes would be:
- there are no getters/fields exposed in the api
- the only exceptions are "namespaces", e.g. `page.keyboard`

Fixes #280.

BREAKING CHANGE:
This patch ditches getters and replaces them with methods throughout
the API. The following methods were added instead of the fields:
- dialog.type()
- consoleMessage.args()
- consoleMessage.text()
- consoleMessage.type()
- request.headers()
- request.method()
- request.postData()
- request.resourceType()
- request.url()
- response.headers()
- response.ok()
- response.status()
- response.url()
This commit is contained in:
Andrey Lushnikov 2017-12-18 17:05:57 -08:00 committed by GitHub
parent 10f3b92304
commit b73737302a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 230 additions and 148 deletions

View File

@ -113,11 +113,11 @@
* [dialog.defaultValue()](#dialogdefaultvalue) * [dialog.defaultValue()](#dialogdefaultvalue)
* [dialog.dismiss()](#dialogdismiss) * [dialog.dismiss()](#dialogdismiss)
* [dialog.message()](#dialogmessage) * [dialog.message()](#dialogmessage)
* [dialog.type](#dialogtype) * [dialog.type()](#dialogtype)
- [class: ConsoleMessage](#class-consolemessage) - [class: ConsoleMessage](#class-consolemessage)
* [consoleMessage.args](#consolemessageargs) * [consoleMessage.args()](#consolemessageargs)
* [consoleMessage.text](#consolemessagetext) * [consoleMessage.text()](#consolemessagetext)
* [consoleMessage.type](#consolemessagetype) * [consoleMessage.type()](#consolemessagetype)
- [class: Frame](#class-frame) - [class: Frame](#class-frame)
* [frame.$(selector)](#frameselector) * [frame.$(selector)](#frameselector)
* [frame.$$(selector)](#frameselector) * [frame.$$(selector)](#frameselector)
@ -173,22 +173,22 @@
* [request.abort([errorCode])](#requestaborterrorcode) * [request.abort([errorCode])](#requestaborterrorcode)
* [request.continue([overrides])](#requestcontinueoverrides) * [request.continue([overrides])](#requestcontinueoverrides)
* [request.failure()](#requestfailure) * [request.failure()](#requestfailure)
* [request.headers](#requestheaders) * [request.headers()](#requestheaders)
* [request.method](#requestmethod) * [request.method()](#requestmethod)
* [request.postData](#requestpostdata) * [request.postData()](#requestpostdata)
* [request.resourceType](#requestresourcetype) * [request.resourceType()](#requestresourcetype)
* [request.respond(response)](#requestrespondresponse) * [request.respond(response)](#requestrespondresponse)
* [request.response()](#requestresponse) * [request.response()](#requestresponse)
* [request.url](#requesturl) * [request.url()](#requesturl)
- [class: Response](#class-response) - [class: Response](#class-response)
* [response.buffer()](#responsebuffer) * [response.buffer()](#responsebuffer)
* [response.headers](#responseheaders) * [response.headers()](#responseheaders)
* [response.json()](#responsejson) * [response.json()](#responsejson)
* [response.ok](#responseok) * [response.ok()](#responseok)
* [response.request()](#responserequest) * [response.request()](#responserequest)
* [response.status](#responsestatus) * [response.status()](#responsestatus)
* [response.text()](#responsetext) * [response.text()](#responsetext)
* [response.url](#responseurl) * [response.url()](#responseurl)
- [class: Target](#class-target) - [class: Target](#class-target)
* [target.page()](#targetpage) * [target.page()](#targetpage)
* [target.type()](#targettype) * [target.type()](#targettype)
@ -1396,23 +1396,21 @@ puppeteer.launch().then(async browser => {
#### dialog.message() #### dialog.message()
- returns: <[string]> A message displayed in the dialog. - returns: <[string]> A message displayed in the dialog.
#### dialog.type #### dialog.type()
- <[string]> - returns: <[string]> Dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
Dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
### class: ConsoleMessage ### class: ConsoleMessage
[ConsoleMessage] objects are dispatched by page via the ['console'](#event-console) event. [ConsoleMessage] objects are dispatched by page via the ['console'](#event-console) event.
#### consoleMessage.args #### consoleMessage.args()
- <[Array]<[JSHandle]>> - returns: <[Array]<[JSHandle]>>
#### consoleMessage.text #### consoleMessage.text()
- <[string]> - returns: <[string]>
#### consoleMessage.type #### consoleMessage.type()
- <[string]> - returns: <[string]>
One of the following values: `'log'`, `'debug'`, `'info'`, `'error'`, `'warning'`, `'dir'`, `'dirxml'`, `'table'`, `'trace'`, `'clear'`, `'startGroup'`, `'startGroupCollapsed'`, `'endGroup'`, `'assert'`, `'profile'`, `'profileEnd'`, `'count'`, `'timeEnd'`. One of the following values: `'log'`, `'debug'`, `'info'`, `'error'`, `'warning'`, `'dir'`, `'dirxml'`, `'table'`, `'trace'`, `'clear'`, `'startGroup'`, `'startGroupCollapsed'`, `'endGroup'`, `'assert'`, `'profile'`, `'profileEnd'`, `'count'`, `'timeEnd'`.
@ -2010,21 +2008,17 @@ page.on('requestfailed', request => {
}); });
``` ```
#### request.headers #### request.headers()
- <[Object]> An object with HTTP headers associated with the request. All header names are lower-case. - returns: <[Object]> An object with HTTP headers associated with the request. All header names are lower-case.
#### request.method #### request.method()
- <[string]> - returns: <[string]> Request's method (GET, POST, etc.)
Contains the request's method (GET, POST, etc.) #### request.postData()
- returns: <[string]> Request's post body, if any.
#### request.postData #### request.resourceType()
- <[string]> - returns: <[string]>
Contains the request's post body, if any.
#### request.resourceType
- <[string]>
Contains the request's resource type as it was perceived by the rendering engine. Contains the request's resource type as it was perceived by the rendering engine.
ResourceType will be one of the following: `document`, `stylesheet`, `image`, `media`, `font`, `script`, `texttrack`, `xhr`, `fetch`, `eventsource`, `websocket`, `manifest`, `other`. ResourceType will be one of the following: `document`, `stylesheet`, `image`, `media`, `font`, `script`, `texttrack`, `xhr`, `fetch`, `eventsource`, `websocket`, `manifest`, `other`.
@ -2060,10 +2054,8 @@ page.on('request', request => {
#### request.response() #### request.response()
- returns: <?[Response]> A matching [Response] object, or `null` if the response has not been received yet. - returns: <?[Response]> A matching [Response] object, or `null` if the response has not been received yet.
#### request.url #### request.url()
- <[string]> - returns: <[string]> URL of the request.
Contains the URL of the request.
### class: Response ### class: Response
@ -2072,32 +2064,32 @@ Contains the URL of the request.
#### response.buffer() #### response.buffer()
- returns: <Promise<[Buffer]>> Promise which resolves to a buffer with response body. - returns: <Promise<[Buffer]>> Promise which resolves to a buffer with response body.
#### response.headers #### response.headers()
- <[Object]> An object with HTTP headers associated with the response. All header names are lower-case. - returns: <[Object]> An object with HTTP headers associated with the response. All header names are lower-case.
#### response.json() #### response.json()
- returns: <Promise<[Object]>> Promise which resolves to a JSON representation of response body. - returns: <Promise<[Object]>> Promise which resolves to a JSON representation of response body.
This method will throw if the response body is not parsable via `JSON.parse`. This method will throw if the response body is not parsable via `JSON.parse`.
#### response.ok #### response.ok()
- <[boolean]> - returns: <[boolean]>
Contains a boolean stating whether the response was successful (status in the range 200-299) or not. Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
#### response.request() #### response.request()
- returns: <[Request]> A matching [Request] object. - returns: <[Request]> A matching [Request] object.
#### response.status #### response.status()
- <[number]> - returns: <[number]>
Contains the status code of the response (e.g., 200 for a success). Contains the status code of the response (e.g., 200 for a success).
#### response.text() #### response.text()
- returns: <[Promise]<[string]>> Promise which resolves to a text representation of response body. - returns: <[Promise]<[string]>> Promise which resolves to a text representation of response body.
#### response.url #### response.url()
- <[string]> - returns: <[string]>
Contains the URL of the response. Contains the URL of the response.

View File

@ -24,7 +24,7 @@ const browser = await puppeteer.launch();
const page = await browser.newPage(); const page = await browser.newPage();
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
if (request.resourceType === 'image') if (request.resourceType() === 'image')
request.abort(); request.abort();
else else
request.continue(); request.continue();

View File

@ -25,12 +25,19 @@ class Dialog {
*/ */
constructor(client, type, message, defaultValue = '') { constructor(client, type, message, defaultValue = '') {
this._client = client; this._client = client;
this.type = type; this._type = type;
this._message = message; this._message = message;
this._handled = false; this._handled = false;
this._defaultValue = defaultValue; this._defaultValue = defaultValue;
} }
/**
* @return {string}
*/
type() {
return this._type;
}
/** /**
* @return {string} * @return {string}
*/ */

View File

@ -294,13 +294,48 @@ class Request {
this._completePromiseFulfill = fulfill; this._completePromiseFulfill = fulfill;
}); });
this.url = url; this._url = url;
this.resourceType = resourceType.toLowerCase(); this._resourceType = resourceType.toLowerCase();
this.method = payload.method; this._method = payload.method;
this.postData = payload.postData; this._postData = payload.postData;
this.headers = {}; this._headers = {};
for (const key of Object.keys(payload.headers)) for (const key of Object.keys(payload.headers))
this.headers[key.toLowerCase()] = payload.headers[key]; this._headers[key.toLowerCase()] = payload.headers[key];
}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @return {string}
*/
resourceType() {
return this._resourceType;
}
/**
* @return {string}
*/
method() {
return this._method;
}
/**
* @return {string}
*/
postData() {
return this._postData;
}
/**
* @return {!Object}
*/
headers() {
return this._headers;
} }
/** /**
@ -346,7 +381,7 @@ class Request {
*/ */
async respond(response) { async respond(response) {
// Mocking responses for dataURL requests is not currently supported. // Mocking responses for dataURL requests is not currently supported.
if (this.url.startsWith('data:')) if (this._url.startsWith('data:'))
return; return;
console.assert(this._allowInterception, 'Request Interception is not enabled!'); console.assert(this._allowInterception, 'Request Interception is not enabled!');
console.assert(!this._interceptionHandled, 'Request is already handled!'); console.assert(!this._interceptionHandled, 'Request is already handled!');
@ -438,12 +473,39 @@ class Response {
this._request = request; this._request = request;
this._contentPromise = null; this._contentPromise = null;
this.status = status; this._status = status;
this.ok = status >= 200 && status <= 299; this._url = request.url();
this.url = request.url; this._headers = {};
this.headers = {};
for (const key of Object.keys(headers)) for (const key of Object.keys(headers))
this.headers[key.toLowerCase()] = headers[key]; this._headers[key.toLowerCase()] = headers[key];
}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @return {boolean}
*/
ok() {
return this._status >= 200 && this._status <= 299;
}
/**
* @return {number}
*/
status() {
return this._status;
}
/**
* @return {!Object}
*/
headers() {
return this._headers;
} }
/** /**

View File

@ -457,7 +457,7 @@ class Page extends EventEmitter {
const requests = new Map(); const requests = new Map();
const eventListeners = [ const eventListeners = [
helper.addEventListener(this._networkManager, NetworkManager.Events.Request, request => requests.set(request.url, request)) helper.addEventListener(this._networkManager, NetworkManager.Events.Request, request => requests.set(request.url(), request))
]; ];
const mainFrame = this._frameManager.mainFrame(); const mainFrame = this._frameManager.mainFrame();
@ -513,7 +513,7 @@ class Page extends EventEmitter {
const watcher = new NavigatorWatcher(this._frameManager, mainFrame, options); const watcher = new NavigatorWatcher(this._frameManager, mainFrame, options);
const responses = new Map(); const responses = new Map();
const listener = helper.addEventListener(this._networkManager, NetworkManager.Events.Response, response => responses.set(response.url, response)); const listener = helper.addEventListener(this._networkManager, NetworkManager.Events.Response, response => responses.set(response.url(), response));
const error = await watcher.navigationPromise(); const error = await watcher.navigationPromise();
helper.removeEventListeners([listener]); helper.removeEventListeners([listener]);
if (error) if (error)
@ -978,9 +978,30 @@ class ConsoleMessage {
* @param {!Array<*>} args * @param {!Array<*>} args
*/ */
constructor(type, text, args) { constructor(type, text, args) {
this.type = type; this._type = type;
this.text = text; this._text = text;
this.args = args; this._args = args;
}
/**
* @return {string}
*/
type() {
return this._type;
}
/**
* @return {string}
*/
text() {
return this._text;
}
/**
* @return {!Array<string>}
*/
args() {
return this._args;
} }
} }

View File

@ -112,7 +112,7 @@ describe('Puppeteer', function() {
let error = null; let error = null;
const response = await page.goto(httpsServer.EMPTY_PAGE).catch(e => error = e); const response = await page.goto(httpsServer.EMPTY_PAGE).catch(e => error = e);
expect(error).toBe(null); expect(error).toBe(null);
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
browser.close(); browser.close();
}); });
it('should reject all promises when browser is closed', async() => { it('should reject all promises when browser is closed', async() => {
@ -445,7 +445,7 @@ describe('Page', function() {
expect(error).toBeTruthy(); expect(error).toBeTruthy();
await page.setOfflineMode(false); await page.setOfflineMode(false);
const response = await page.reload(); const response = await page.reload();
expect(response.status).toBe(200); expect(response.status()).toBe(200);
}); });
it('should emulate navigator.onLine', async({page, server}) => { it('should emulate navigator.onLine', async({page, server}) => {
expect(await page.evaluate(() => window.navigator.onLine)).toBe(true); expect(await page.evaluate(() => window.navigator.onLine)).toBe(true);
@ -891,11 +891,11 @@ describe('Page', function() {
page.evaluate(() => console.log('hello', 5, {foo: 'bar'})), page.evaluate(() => console.log('hello', 5, {foo: 'bar'})),
waitForEvents(page, 'console') waitForEvents(page, 'console')
]); ]);
expect(message.text).toEqual('hello 5 JSHandle@object'); expect(message.text()).toEqual('hello 5 JSHandle@object');
expect(message.type).toEqual('log'); expect(message.type()).toEqual('log');
expect(await message.args[0].jsonValue()).toEqual('hello'); expect(await message.args()[0].jsonValue()).toEqual('hello');
expect(await message.args[1].jsonValue()).toEqual(5); expect(await message.args()[1].jsonValue()).toEqual(5);
expect(await message.args[2].jsonValue()).toEqual({foo: 'bar'}); expect(await message.args()[2].jsonValue()).toEqual({foo: 'bar'});
}); });
it('should work for different console API calls', async({page, server}) => { it('should work for different console API calls', async({page, server}) => {
const messages = []; const messages = [];
@ -914,11 +914,11 @@ describe('Page', function() {
// Wait for 5 events to hit - console.time is not reported // Wait for 5 events to hit - console.time is not reported
waitForEvents(page, 'console', 5) waitForEvents(page, 'console', 5)
]); ]);
expect(messages.map(msg => msg.type)).toEqual([ expect(messages.map(msg => msg.type())).toEqual([
'timeEnd', 'trace', 'dir', 'warning', 'error', 'log' 'timeEnd', 'trace', 'dir', 'warning', 'error', 'log'
]); ]);
expect(messages[0].text).toContain('calling console.time'); expect(messages[0].text()).toContain('calling console.time');
expect(messages.slice(1).map(msg => msg.text)).toEqual([ expect(messages.slice(1).map(msg => msg.text())).toEqual([
'calling console.trace', 'calling console.trace',
'calling console.dir', 'calling console.dir',
'calling console.warn', 'calling console.warn',
@ -933,7 +933,7 @@ describe('Page', function() {
page.evaluate(() => console.error(window)), page.evaluate(() => console.error(window)),
waitForEvents(page, 'console') waitForEvents(page, 'console')
]); ]);
expect(message.text).toBe('JSHandle@object'); expect(message.text()).toBe('JSHandle@object');
}); });
}); });
@ -982,15 +982,15 @@ describe('Page', function() {
}); });
it('should navigate to empty page with domcontentloaded', async({page, server}) => { it('should navigate to empty page with domcontentloaded', async({page, server}) => {
const response = await page.goto(server.EMPTY_PAGE, {waitUntil: 'domcontentloaded'}); const response = await page.goto(server.EMPTY_PAGE, {waitUntil: 'domcontentloaded'});
expect(response.status).toBe(200); expect(response.status()).toBe(200);
}); });
it('should navigate to empty page with networkidle0', async({page, server}) => { it('should navigate to empty page with networkidle0', async({page, server}) => {
const response = await page.goto(server.EMPTY_PAGE, {waitUntil: 'networkidle0'}); const response = await page.goto(server.EMPTY_PAGE, {waitUntil: 'networkidle0'});
expect(response.status).toBe(200); expect(response.status()).toBe(200);
}); });
it('should navigate to empty page with networkidle2', async({page, server}) => { it('should navigate to empty page with networkidle2', async({page, server}) => {
const response = await page.goto(server.EMPTY_PAGE, {waitUntil: 'networkidle2'}); const response = await page.goto(server.EMPTY_PAGE, {waitUntil: 'networkidle2'});
expect(response.status).toBe(200); expect(response.status()).toBe(200);
}); });
it('should fail when navigating to bad url', async({page, server}) => { it('should fail when navigating to bad url', async({page, server}) => {
let error = null; let error = null;
@ -1041,24 +1041,24 @@ describe('Page', function() {
}); });
it('should work when navigating to valid url', async({page, server}) => { it('should work when navigating to valid url', async({page, server}) => {
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should work when navigating to data url', async({page, server}) => { it('should work when navigating to data url', async({page, server}) => {
const response = await page.goto('data:text/html,hello'); const response = await page.goto('data:text/html,hello');
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should work when navigating to 404', async({page, server}) => { it('should work when navigating to 404', async({page, server}) => {
const response = await page.goto(server.PREFIX + '/not-found'); const response = await page.goto(server.PREFIX + '/not-found');
expect(response.ok).toBe(false); expect(response.ok()).toBe(false);
expect(response.status).toBe(404); expect(response.status()).toBe(404);
}); });
it('should return last response in redirect chain', async({page, server}) => { it('should return last response in redirect chain', async({page, server}) => {
server.setRedirect('/redirect/1.html', '/redirect/2.html'); server.setRedirect('/redirect/1.html', '/redirect/2.html');
server.setRedirect('/redirect/2.html', '/redirect/3.html'); server.setRedirect('/redirect/2.html', '/redirect/3.html');
server.setRedirect('/redirect/3.html', server.EMPTY_PAGE); server.setRedirect('/redirect/3.html', server.EMPTY_PAGE);
const response = await page.goto(server.PREFIX + '/redirect/1.html'); const response = await page.goto(server.PREFIX + '/redirect/1.html');
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
expect(response.url).toBe(server.EMPTY_PAGE); expect(response.url()).toBe(server.EMPTY_PAGE);
}); });
it('should wait for network idle to succeed navigation', async({page, server}) => { it('should wait for network idle to succeed navigation', async({page, server}) => {
let responses = []; let responses = [];
@ -1115,7 +1115,7 @@ describe('Page', function() {
const response = await navigationPromise; const response = await navigationPromise;
// Expect navigation to succeed. // Expect navigation to succeed.
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should not leak listeners during navigation', async({page, server}) => { it('should not leak listeners during navigation', async({page, server}) => {
let warning = null; let warning = null;
@ -1140,18 +1140,18 @@ describe('Page', function() {
page.on('request', request => requests.push(request)); page.on('request', 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);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(dataURL); expect(requests[0].url()).toBe(dataURL);
}); });
it('should navigate to URL with hash and fire requests without hash', async({page, server}) => { it('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 => 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);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(server.EMPTY_PAGE); expect(requests[0].url()).toBe(server.EMPTY_PAGE);
}); });
}); });
@ -1163,8 +1163,8 @@ describe('Page', function() {
page.evaluate(url => window.location.href = url, server.PREFIX + '/grid.html') page.evaluate(url => window.location.href = url, server.PREFIX + '/grid.html')
]); ]);
const response = await result; const response = await result;
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
expect(response.url).toContain('grid.html'); expect(response.url()).toContain('grid.html');
}); });
it('should work with both domcontentloaded and load', async({page, server}) => { it('should work with both domcontentloaded and load', async({page, server}) => {
let response = null; let response = null;
@ -1193,12 +1193,12 @@ describe('Page', function() {
await page.goto(server.PREFIX + '/grid.html'); await page.goto(server.PREFIX + '/grid.html');
let response = await page.goBack(); let response = await page.goBack();
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
expect(response.url).toContain(server.EMPTY_PAGE); expect(response.url()).toContain(server.EMPTY_PAGE);
response = await page.goForward(); response = await page.goForward();
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
expect(response.url).toContain('/grid.html'); expect(response.url()).toContain('/grid.html');
response = await page.goForward(); response = await page.goForward();
expect(response).toBe(null); expect(response).toBe(null);
@ -1266,15 +1266,15 @@ describe('Page', function() {
it('should intercept', async({page, server}) => { it('should intercept', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
expect(request.url).toContain('empty.html'); expect(request.url()).toContain('empty.html');
expect(request.headers['user-agent']).toBeTruthy(); expect(request.headers()['user-agent']).toBeTruthy();
expect(request.method).toBe('GET'); expect(request.method()).toBe('GET');
expect(request.postData).toBe(undefined); expect(request.postData()).toBe(undefined);
expect(request.resourceType).toBe('document'); expect(request.resourceType()).toBe('document');
request.continue(); request.continue();
}); });
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should stop intercepting', async({page, server}) => { it('should stop intercepting', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
@ -1289,16 +1289,16 @@ describe('Page', function() {
}); });
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
expect(request.headers['foo']).toBe('bar'); expect(request.headers()['foo']).toBe('bar');
request.continue(); request.continue();
}); });
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should be abortable', async({page, server}) => { it('should be abortable', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
if (request.url.endsWith('.css')) if (request.url().endsWith('.css'))
request.abort(); request.abort();
else else
request.continue(); request.continue();
@ -1306,7 +1306,7 @@ describe('Page', function() {
let failedRequests = 0; let failedRequests = 0;
page.on('requestfailed', event => ++failedRequests); page.on('requestfailed', event => ++failedRequests);
const response = await page.goto(server.PREFIX + '/one-style.html'); const response = await page.goto(server.PREFIX + '/one-style.html');
expect(response.ok).toBe(true); expect(response.ok()).toBe(true);
expect(response.request().failure()).toBe(null); expect(response.request().failure()).toBe(null);
expect(failedRequests).toBe(1); expect(failedRequests).toBe(1);
}); });
@ -1324,7 +1324,7 @@ describe('Page', function() {
it('should amend HTTP headers', async({page, server}) => { it('should amend HTTP headers', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
const headers = Object.assign({}, request.headers); const headers = Object.assign({}, request.headers());
headers['FOO'] = 'bar'; headers['FOO'] = 'bar';
request.continue({ headers }); request.continue({ headers });
}); });
@ -1355,17 +1355,17 @@ describe('Page', function() {
server.setRedirect('/non-existing-page-3.html', '/non-existing-page-4.html'); server.setRedirect('/non-existing-page-3.html', '/non-existing-page-4.html');
server.setRedirect('/non-existing-page-4.html', '/empty.html'); server.setRedirect('/non-existing-page-4.html', '/empty.html');
const response = await page.goto(server.PREFIX + '/non-existing-page.html'); const response = await page.goto(server.PREFIX + '/non-existing-page.html');
expect(response.status).toBe(200); expect(response.status()).toBe(200);
expect(response.url).toContain('empty.html'); expect(response.url()).toContain('empty.html');
expect(requests.length).toBe(5); expect(requests.length).toBe(5);
expect(requests[2].resourceType).toBe('document'); expect(requests[2].resourceType()).toBe('document');
}); });
it('should be able to abort redirects', async({page, server}) => { it('should be able to abort redirects', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
server.setRedirect('/non-existing.json', '/non-existing-2.json'); server.setRedirect('/non-existing.json', '/non-existing-2.json');
server.setRedirect('/non-existing-2.json', '/simple.html'); server.setRedirect('/non-existing-2.json', '/simple.html');
page.on('request', request => { page.on('request', request => {
if (request.url.includes('non-existing-2')) if (request.url().includes('non-existing-2'))
request.abort(); request.abort();
else else
request.continue(); request.continue();
@ -1408,9 +1408,9 @@ describe('Page', function() {
}); });
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);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(dataURL); expect(requests[0].url()).toBe(dataURL);
}); });
it('should abort data server', async({page, server}) => { it('should abort data server', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
@ -1429,10 +1429,10 @@ describe('Page', function() {
request.continue(); request.continue();
}); });
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);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(server.EMPTY_PAGE); expect(requests[0].url()).toBe(server.EMPTY_PAGE);
}); });
it('should work with encoded server', async({page, server}) => { it('should work with encoded server', async({page, server}) => {
// The requestWillBeSent will report encoded URL, whereas interception will // The requestWillBeSent will report encoded URL, whereas interception will
@ -1440,14 +1440,14 @@ describe('Page', function() {
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const response = await page.goto(server.PREFIX + '/some nonexisting page'); const response = await page.goto(server.PREFIX + '/some nonexisting page');
expect(response.status).toBe(404); expect(response.status()).toBe(404);
}); });
it('should work with badly encoded server', async({page, server}) => { it('should work with badly encoded server', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
server.setRoute('/malformed?rnd=%911', (req, res) => res.end()); server.setRoute('/malformed?rnd=%911', (req, res) => res.end());
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const response = await page.goto(server.PREFIX + '/malformed?rnd=%911'); const response = await page.goto(server.PREFIX + '/malformed?rnd=%911');
expect(response.status).toBe(200); expect(response.status()).toBe(200);
}); });
it('should work with encoded server - 2', async({page, server}) => { it('should work with encoded server - 2', async({page, server}) => {
// The requestWillBeSent will report URL as-is, whereas interception will // The requestWillBeSent will report URL as-is, whereas interception will
@ -1459,9 +1459,9 @@ describe('Page', function() {
requests.push(request); requests.push(request);
}); });
const response = await page.goto(`data:text/html,<link rel="stylesheet" href="${server.PREFIX}/fonts?helvetica|arial"/>`); const response = await page.goto(`data:text/html,<link rel="stylesheet" href="${server.PREFIX}/fonts?helvetica|arial"/>`);
expect(response.status).toBe(200); expect(response.status()).toBe(200);
expect(requests.length).toBe(2); expect(requests.length).toBe(2);
expect(requests[1].response().status).toBe(404); expect(requests[1].response().status()).toBe(404);
}); });
it('should not throw "Invalid Interception Id" if the request was cancelled', async({page, server}) => { it('should not throw "Invalid Interception Id" if the request was cancelled', async({page, server}) => {
await page.setContent('<iframe></iframe>'); await page.setContent('<iframe></iframe>');
@ -1504,8 +1504,8 @@ describe('Page', function() {
}); });
}); });
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.status).toBe(201); expect(response.status()).toBe(201);
expect(response.headers.foo).toBe('bar'); expect(response.headers().foo).toBe('bar');
expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!'); expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!');
}); });
it('should allow mocking binary responses', async({page, server}) => { it('should allow mocking binary responses', async({page, server}) => {
@ -1531,7 +1531,7 @@ describe('Page', function() {
describe('Page.Events.Dialog', function() { describe('Page.Events.Dialog', function() {
it('should fire', async({page, server}) => { it('should fire', async({page, server}) => {
page.on('dialog', dialog => { page.on('dialog', dialog => {
expect(dialog.type).toBe('alert'); expect(dialog.type()).toBe('alert');
expect(dialog.defaultValue()).toBe(''); expect(dialog.defaultValue()).toBe('');
expect(dialog.message()).toBe('yo'); expect(dialog.message()).toBe('yo');
dialog.accept(); dialog.accept();
@ -1540,7 +1540,7 @@ describe('Page', function() {
}); });
it('should allow accepting prompts', async({page, server}) => { it('should allow accepting prompts', async({page, server}) => {
page.on('dialog', dialog => { page.on('dialog', dialog => {
expect(dialog.type).toBe('prompt'); expect(dialog.type()).toBe('prompt');
expect(dialog.defaultValue()).toBe('yes.'); expect(dialog.defaultValue()).toBe('yes.');
expect(dialog.message()).toBe('question?'); expect(dialog.message()).toBe('question?');
dialog.accept('answer!'); dialog.accept('answer!');
@ -1573,7 +1573,7 @@ describe('Page', function() {
page.on('request', request => requests.push(request)); page.on('request', request => requests.push(request));
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toContain('empty.html'); expect(requests[0].url()).toContain('empty.html');
}); });
}); });
@ -2350,13 +2350,13 @@ describe('Page', function() {
it('should work', async({page, server}) => { it('should work', async({page, server}) => {
server.setAuth('/empty.html', 'user', 'pass'); server.setAuth('/empty.html', 'user', 'pass');
let response = await page.goto(server.EMPTY_PAGE); let response = await page.goto(server.EMPTY_PAGE);
expect(response.status).toBe(401); expect(response.status()).toBe(401);
await page.authenticate({ await page.authenticate({
username: 'user', username: 'user',
password: 'pass' password: 'pass'
}); });
response = await page.reload(); response = await page.reload();
expect(response.status).toBe(200); expect(response.status()).toBe(200);
}); });
it('should fail if wrong credentials', async({page, server}) => { it('should fail if wrong credentials', async({page, server}) => {
// Use unique user/password since Chrome caches credentials per origin. // Use unique user/password since Chrome caches credentials per origin.
@ -2366,7 +2366,7 @@ describe('Page', function() {
password: 'bar' password: 'bar'
}); });
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.status).toBe(401); expect(response.status()).toBe(401);
}); });
it('should allow disable authentication', async({page, server}) => { it('should allow disable authentication', async({page, server}) => {
// Use unique user/password since Chrome caches credentials per origin. // Use unique user/password since Chrome caches credentials per origin.
@ -2376,11 +2376,11 @@ describe('Page', function() {
password: 'pass3' password: 'pass3'
}); });
let response = await page.goto(server.EMPTY_PAGE); let response = await page.goto(server.EMPTY_PAGE);
expect(response.status).toBe(200); expect(response.status()).toBe(200);
await page.authenticate(null); await page.authenticate(null);
// Navigate to a different origin to bust Chrome's credential caching. // Navigate to a different origin to bust Chrome's credential caching.
response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
expect(response.status).toBe(401); expect(response.status()).toBe(401);
}); });
}); });
@ -2412,9 +2412,9 @@ describe('Page', function() {
page.on('request', request => requests.push(request)); page.on('request', request => requests.push(request));
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(server.EMPTY_PAGE); expect(requests[0].url()).toBe(server.EMPTY_PAGE);
expect(requests[0].resourceType).toBe('document'); expect(requests[0].resourceType()).toBe('document');
expect(requests[0].method).toBe('GET'); expect(requests[0].method()).toBe('GET');
expect(requests[0].response()).toBeTruthy(); expect(requests[0].response()).toBeTruthy();
}); });
it('Page.Events.Request should report post data', async({page, server}) => { it('Page.Events.Request should report post data', async({page, server}) => {
@ -2424,16 +2424,16 @@ describe('Page', function() {
page.on('request', r => request = r); page.on('request', r => request = r);
await page.evaluate(() => fetch('./post', { method: 'POST', body: JSON.stringify({foo: 'bar'})})); await page.evaluate(() => fetch('./post', { method: 'POST', body: JSON.stringify({foo: 'bar'})}));
expect(request).toBeTruthy(); expect(request).toBeTruthy();
expect(request.postData).toBe('{"foo":"bar"}'); expect(request.postData()).toBe('{"foo":"bar"}');
}); });
it('Page.Events.Response', async({page, server}) => { it('Page.Events.Response', async({page, server}) => {
const responses = []; const responses = [];
page.on('response', response => responses.push(response)); page.on('response', response => responses.push(response));
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
expect(responses.length).toBe(1); expect(responses.length).toBe(1);
expect(responses[0].url).toBe(server.EMPTY_PAGE); expect(responses[0].url()).toBe(server.EMPTY_PAGE);
expect(responses[0].status).toBe(200); expect(responses[0].status()).toBe(200);
expect(responses[0].ok).toBe(true); expect(responses[0].ok()).toBe(true);
expect(responses[0].request()).toBeTruthy(); expect(responses[0].request()).toBeTruthy();
}); });
it('Page.Events.Response should provide body', async({page, server}) => { it('Page.Events.Response should provide body', async({page, server}) => {
@ -2465,7 +2465,7 @@ describe('Page', function() {
expect(serverResponse).toBeTruthy(); expect(serverResponse).toBeTruthy();
expect(pageResponse).toBeTruthy(); expect(pageResponse).toBeTruthy();
expect(pageResponse.status).toBe(200); expect(pageResponse.status()).toBe(200);
expect(requestFinished).toBe(false); expect(requestFinished).toBe(false);
const responseText = pageResponse.text(); const responseText = pageResponse.text();
@ -2478,7 +2478,7 @@ describe('Page', function() {
it('Page.Events.RequestFailed', async({page, server}) => { it('Page.Events.RequestFailed', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
if (request.url.endsWith('css')) if (request.url().endsWith('css'))
request.abort(); request.abort();
else else
request.continue(); request.continue();
@ -2487,9 +2487,9 @@ describe('Page', function() {
page.on('requestfailed', request => failedRequests.push(request)); page.on('requestfailed', request => failedRequests.push(request));
await page.goto(server.PREFIX + '/one-style.html'); await page.goto(server.PREFIX + '/one-style.html');
expect(failedRequests.length).toBe(1); expect(failedRequests.length).toBe(1);
expect(failedRequests[0].url).toContain('one-style.css'); expect(failedRequests[0].url()).toContain('one-style.css');
expect(failedRequests[0].response()).toBe(null); expect(failedRequests[0].response()).toBe(null);
expect(failedRequests[0].resourceType).toBe('stylesheet'); expect(failedRequests[0].resourceType()).toBe('stylesheet');
expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED'); expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
}); });
it('Page.Events.RequestFinished', async({page, server}) => { it('Page.Events.RequestFinished', async({page, server}) => {
@ -2497,7 +2497,7 @@ describe('Page', function() {
page.on('requestfinished', request => requests.push(request)); page.on('requestfinished', request => requests.push(request));
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(server.EMPTY_PAGE); expect(requests[0].url()).toBe(server.EMPTY_PAGE);
expect(requests[0].response()).toBeTruthy(); expect(requests[0].response()).toBeTruthy();
}); });
it('should fire events in proper order', async({page, server}) => { it('should fire events in proper order', async({page, server}) => {
@ -2510,10 +2510,10 @@ describe('Page', function() {
}); });
it('should support redirects', async({page, server}) => { it('should support redirects', async({page, server}) => {
const events = []; const events = [];
page.on('request', request => events.push(`${request.method} ${request.url}`)); page.on('request', request => events.push(`${request.method()} ${request.url()}`));
page.on('response', response => events.push(`${response.status} ${response.url}`)); page.on('response', response => events.push(`${response.status()} ${response.url()}`));
page.on('requestfinished', request => events.push(`DONE ${request.url}`)); page.on('requestfinished', request => events.push(`DONE ${request.url()}`));
page.on('requestfailed', request => events.push(`FAIL ${request.url}`)); page.on('requestfailed', request => events.push(`FAIL ${request.url()}`));
server.setRedirect('/foo.html', '/empty.html'); server.setRedirect('/foo.html', '/empty.html');
const FOO_URL = server.PREFIX + '/foo.html'; const FOO_URL = server.PREFIX + '/foo.html';
await page.goto(FOO_URL); await page.goto(FOO_URL);