From 08c8a74e0951275d0358d0b9219b6855731f500b Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 16 Apr 2020 10:48:38 -0700 Subject: [PATCH] docs(network): polish network docs (#1826) --- docs/input.md | 46 +++++++++---------- docs/network.md | 114 ++++++++++++++++++++++++++++++++++++++++-------- src/network.ts | 4 +- 3 files changed, 119 insertions(+), 45 deletions(-) diff --git a/docs/input.md b/docs/input.md index 0740adde50..64ec68d057 100644 --- a/docs/input.md +++ b/docs/input.md @@ -1,4 +1,4 @@ -# Input cheat sheet +# Working with input ## Fill out the form, enter text ```js @@ -23,11 +23,10 @@ await page.fill('#local', '2020-03-02T05:15'); #### API reference -- [`page.fill(selector, value[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pagefillselector-value-options) — on the main frame -- [`frame.fill(selector, value[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#framefillselector-value-options) — on a specific frame -- [`elementHandle.fill(value[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#elementhandlefillvalue-options) — on a particular element +- [`page.fill(selector, value[, options])`](./api.md#pagefillselector-value-options) — on the main frame +- [`frame.fill(selector, value[, options])`](./api.md#framefillselector-value-options) — on a specific frame +- [`elementHandle.fill(value[, options])`](./api.md#elementhandlefillvalue-options) — on a particular element -

## Check / uncheck the checkbox @@ -44,14 +43,13 @@ This is the easiest way to check and uncheck a checkbox. This method can be used #### API reference -- [`page.check(selector[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pagecheckselector-options) — on the main frame -- [`page.uncheck(selector[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pageuncheckselector-options) — on the main frame -- [`frame.check(selector[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#framecheckselector-options) — on a specific frame -- [`frame.uncheck(selector[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#frameuncheckselector-options) — on a specific frame -- [`elementHandle.check(value[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#elementhandleuncheckoptions) — on a particular element -- [`elementHandle.uncheck(value[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#elementhandleuncheckoptions) — on a particular element +- [`page.check(selector[, options])`](./api.md#pagecheckselector-options) — on the main frame +- [`page.uncheck(selector[, options])`](./api.md#pageuncheckselector-options) — on the main frame +- [`frame.check(selector[, options])`](./api.md#framecheckselector-options) — on a specific frame +- [`frame.uncheck(selector[, options])`](./api.md#frameuncheckselector-options) — on a specific frame +- [`elementHandle.check(value[, options])`](./api.md#elementhandleuncheckoptions) — on a particular element +- [`elementHandle.uncheck(value[, options])`](./api.md#elementhandleuncheckoptions) — on a particular element -

## Select an option @@ -88,11 +86,10 @@ page.selectOption('select#colors', option); #### API reference -- [`page.selectOption(selector, values[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pageselectoptionselector-values-options) — on the main frame -- [`frame.selectOption(selector, values[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#frameselectoptionselector-values-options) — on a specific frame -- [`elementHandle.selectOption(values[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#elementhandleselectoptionvalues-options) — on a particular element +- [`page.selectOption(selector, values[, options])`](./api.md#pageselectoptionselector-values-options) — on the main frame +- [`frame.selectOption(selector, values[, options])`](./api.md#frameselectoptionselector-values-options) — on a specific frame +- [`elementHandle.selectOption(values[, options])`](./api.md#elementhandleselectoptionvalues-options) — on a particular element -

## Type character by character @@ -106,12 +103,11 @@ Sometimes it is important to type into the focused field character by character, #### API reference -- [`page.type(selector, text[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pagetypeselector-text-options) — on the main frame -- [`frame.type(selector, text[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#frametypeselector-text-options) — on a specific frame -- [`elementHandle.type(text[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#elementhandletypetext-options) — on a particular element -- [`keyboard.type(text[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#keyboardtypetext-options) — wherever the current focus is +- [`page.type(selector, text[, options])`](./api.md#pagetypeselector-text-options) — on the main frame +- [`frame.type(selector, text[, options])`](./api.md#frametypeselector-text-options) — on a specific frame +- [`elementHandle.type(text[, options])`](./api.md#elementhandletypetext-options) — on a particular element +- [`keyboard.type(text[, options])`](./api.md#keyboardtypetext-options) — wherever the current focus is -

## Press a key, enter keyboard shortcut @@ -165,7 +161,7 @@ Note that you still need to specify the capital `A` in `Shift-A` to produce the #### API reference -- [`page.press(selector, key[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pagepressselector-key-options) — on the main frame -- [`frame.press(selector, key[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#framepressselector-key-options) — on a specific frame -- [`elementHandle.press(key[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#elementhandlepresskey-options) — on a particular element -- [`keyboard.press(key[, options])`](https://github.com/microsoft/playwright/blob/master/docs/api.md#keyboardpresskey-options) — wherever the current focus is +- [`page.press(selector, key[, options])`](./api.md#pagepressselector-key-options) — on the main frame +- [`frame.press(selector, key[, options])`](./api.md#framepressselector-key-options) — on a specific frame +- [`elementHandle.press(key[, options])`](./api.md#elementhandlepresskey-options) — on a particular element +- [`keyboard.press(key[, options])`](./api.md#keyboardpresskey-options) — wherever the current focus is diff --git a/docs/network.md b/docs/network.md index f55b0402e3..326b06018a 100644 --- a/docs/network.md +++ b/docs/network.md @@ -1,7 +1,5 @@ # Working With Network -![playwright network](https://user-images.githubusercontent.com/746130/79428385-f0264900-7f7a-11ea-86e6-cd03190b8de7.png) - Playwright provides APIs to **monitor** and **modify** network traffic, both HTTP and HTTPS. Any requests that page does, including [XHRs](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) and [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests, can be tracked and modified. @@ -13,26 +11,56 @@ Any requests that page does, including [XHRs](https://developer.mozilla.org/en-U ## Monitor all network activity in page ```js -const page = await browser.newPage(); -page.on('request', request => console.log('>>', request.method(), request.url())); -page.on('response', response => console.log('<<', response.status(), response.url())); -await page.goto('https://example.com'); +const { chromium, webkit, firefox } = require('playwright'); + +(async () => { + const browser = await chromium.launch(); + const page = await browser.newPage(); + + // Subscribe to 'request' and 'response' events.S + page.on('request', request => + console.log('>>', request.method(), request.url())); + page.on('response', response => + console.log('<<', response.status(), response.url())); + await page.goto('https://example.com'); + + await browser.close(); +})(); ``` #### API reference +- [`Request`](./api.md#class-request) +- [`Response`](./api.md#class-response) - [`event: 'request'`](./api.md#event-request) - [`event: 'response'`](./api.md#event-response) -- [`request.method()`](./api.md#requestmethod) -- [`request.url()`](./api.md#requesturl) +
-## Wait for a response from API endpoint after button click +## Wait for a network response after the button click ```js const [response] = await Promise.all([ page.waitForResponse('/api/fetch_data'), - page.click('button[type=submit]'), + page.click('button#update'), +]); +``` + +The snippet above clicks a button and waits for the network response that matches the given pattern. + +#### Variations + +```js +// User glob URL pattern +const [response] = await Promise.all([ + page.waitForResponse('**/*'), + page.click('button#update'), +]); + +// User pattern predicate +const [response] = await Promise.all([ + page.waitForResponse(url => url.includes(token)), + page.click('button#update'), ]); ``` @@ -41,9 +69,9 @@ const [response] = await Promise.all([ - [`page.waitForRequest(urlOrPredicate[, options])`](./api.md#pagewaitforrequesturlorpredicate-options) - [`page.waitForResponse(urlOrPredicate[, options])`](./api.md#pagewaitforresponseurlorpredicate-options) +
- -## Mock API endpoint with test data +## Mock API endpoint with the test data ```js await page.route('/api/fetch_data', route => route.fulfill({ @@ -56,15 +84,30 @@ await page.goto('https://example.com'); You can also use [`browserContext.route`](./api.md#browsercontextrouteurl-handler) to mock API endpoints for all the pages in the context. +#### Variations + +```js +// Set up route on the entire browser context. +// It will apply to popup windows and opened links. + +await browserContext.route('/api/login', route => route.fulfill({ + status: 200, + body: 'accept', +})); +await page.goto('https://example.com'); +``` + #### API reference -- [`page.route(url, handler)`](./api.md#pagerouteurl-handler) - [`browserContext.route(url, handler)`](./api.md#browsercontextrouteurl-handler) -- [`route.fulfill(response)`](./api.md#routefulfillresponse) +- [`browserContext.unroute(url[, handler])`](./api.md#browsercontextunrouteurl-handler) +- [`page.route(url, handler)`](./api.md#pagerouteurl-handler) +- [`page.unroute(url[, handler])`](./api.md#pageunrouteurl-handler) +- [`Route`](./api.md#class-route) +
- -## Abort all images to speedup page load +## Abort selected requests ```js const page = await browser.newPage(); @@ -72,8 +115,17 @@ await page.route('**/*.{png,jpg,jpeg}', route => route.abort()); await page.goto('https://example.com'); ``` -You can also use [`browserContext.route`](./api.md#browsercontextrouteurl-handler) to abort -images for all pages in the context, including popups. +#### Variations + +```js +// Abort requests based on their type. + +await page.route('**/*', route => { + return route.request().resourceType() === 'image' ? + route.abort() : route.continue(); +}); +await page.goto('https://chromium.org'); +``` #### API reference @@ -81,7 +133,33 @@ images for all pages in the context, including popups. - [`browserContext.route(url, handler)`](./api.md#browsercontextrouteurl-handler) - [`route.abort([errorCode])`](./api.md#routeaborterrorcode) +
+## Modify selected requests + + +```js +await page.route('**/*', route => { + const headers = route.request().headers(); + delete headers['X-Secret']; + route.continue({headers}); +}); +await page.goto('https://chromium.org'); +``` + +You can continue requests with modifications. Example above removes an HTTP header from the outgoing requests. + +#### Variations + +```js +// Continue requests as POST. + +await page.route('**/*', route => + route.continue({method: 'POST'})); +await page.goto('https://chromium.org'); +``` + +
## Setup [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) diff --git a/src/network.ts b/src/network.ts index 99a76d8427..5e9efcacdd 100644 --- a/src/network.ts +++ b/src/network.ts @@ -151,7 +151,7 @@ export class Request { } headers(): {[key: string]: string} { - return this._headers; + return { ...this._headers }; } response(): Promise { @@ -291,7 +291,7 @@ export class Response { } headers(): object { - return this._headers; + return { ...this._headers }; } finished(): Promise {