Skip to content

Commit 6cec2df

Browse files
authored
docs: add assertions doc (microsoft#2585)
* docs: add assertions doc * docs: assertions and verification split
1 parent 6870678 commit 6cec2df

File tree

4 files changed

+245
-114
lines changed

4 files changed

+245
-114
lines changed

docs/README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
- [Pages and frames](./core-concepts.md#pages-and-frames)
1717
- [Selectors](./core-concepts.md#selectors)
1818
- [Auto-waiting](./core-concepts.md#auto-waiting)
19-
- [Node.js and browser execution contexts](./core-concepts.md#nodejs-and-browser-execution-contexts)
19+
- [Execution contexts: Node.js and Browser](./core-concepts.md#execution-contexts-nodejs-and-browser)
2020
- [Object & element handles](./core-concepts.md#object--element-handles)
2121
1. [Input](./input.md)
2222
- [Text input](./input.md#text-input)
@@ -43,18 +43,25 @@
4343
- [Handle requests](./network.md#handle-requests)
4444
- [Modify requests](./network.md#modify-requests)
4545
- [Abort requests](./network.md#abort-requests)
46-
1. [Scraping and Verification](./verification.md)
47-
- [Evaluating JavaScript](./verification.md#evaluating-javascript)
48-
- [Capturing screenshot](./verification.md#capturing-screenshot)
46+
1. [Assertions](./assertions.md)
47+
- [Common patterns](./assertions.md#common-patterns)
48+
- [Element Handles](./assertions.md#element-handles)
49+
- [Custom assertions](./assertions.md#custom-assertions)
50+
1. [Verification](./verification.md)
51+
- [Screenshots](./verification.md#screenshots)
52+
- [Console logs](./verification.md#console-logs)
53+
- [Page errors](./verification.md#page-errors)
4954
- [Page events](./verification.md#page-events)
50-
- [Handling exceptions](./verification.md#handling-exceptions)
5155
1. [Navigation and Loading](./loading.md)
5256
- [Overview](./loading.md#)
5357
- [Common scenarios](./loading.md#common-scenarios)
5458
- [Loading a popup](./loading.md#loading-a-popup)
5559
- [Client-side redirects](./loading.md#unusual-client-side-redirects)
5660
- [Navigation after a timeout](./loading.md#click-triggers-navigation-after-a-timeout)
57-
1. [Actionability](./actionability.md)
61+
1. [Test runners](./test-runners.md)
62+
- [Jest / Jasmine](./test-runners.md#jest--jasmine)
63+
- [AVA](./test-runners.md#ava)
64+
- [Mocha](./test-runners.md#mocha)
5865
1. [Continuous Integration](./ci.md)
5966
- [Docker](./ci.md#docker)
6067
- [GitHub Actions](./ci.md#github-actions)
@@ -63,11 +70,8 @@
6370
- [CircleCI](./ci.md#circleci)
6471
- [AppVeyor](./ci.md#appveyor)
6572
- [Troubleshooting](./troubleshooting.md)
66-
1. [Test runners](./test-runners.md)
67-
- [Jest / Jasmine](./test-runners.md#jest--jasmine)
68-
- [AVA](./test-runners.md#ava)
69-
- [Mocha](./test-runners.md#mocha)
7073
1. [Selector engines](./selectors.md)
74+
1. [Actionability](./actionability.md)
7175
1. [Extensibility](./extensibility.md)
7276
- [Custom selector engines](./extensibility.md#custom-selector-engines)
7377
1. [API Reference](./api.md)

docs/assertions.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Assertions
2+
3+
The Playwright API can be used to read element contents and properties for test assertions. These values are fetched from the browser page and asserted in
4+
Node.js.
5+
6+
The examples in this guide use the built-in [`assert` module](https://nodejs.org/api/assert.html), but they can be used with any assertion library (like [Expect](https://www.npmjs.com/package/expect) or [Chai](https://www.npmjs.com/package/chai)). See [Test runners](test-runners.md) for more info.
7+
8+
<!-- GEN:toc-top-level -->
9+
- [Common patterns](#common-patterns)
10+
- [Element Handles](#element-handles)
11+
- [Custom assertions](#custom-assertions)
12+
<!-- GEN:stop -->
13+
14+
<br/>
15+
16+
## Common patterns
17+
18+
Playwright provides convenience APIs for common assertion tasks, like finding the
19+
text content of an element. These APIs require a [selector](selectors.md) to locate
20+
the element.
21+
22+
```js
23+
// Assert text content
24+
const content = await page.textContent('nav:first-child');
25+
assert(content === 'home');
26+
27+
// Assert inner text
28+
const text = await page.innerText('.selected');
29+
assert(text === 'value');
30+
31+
// Assert inner HTML
32+
const html = await page.innerHTML('div.result');
33+
assert(html === '<p>Result</p>')
34+
35+
// Assert `checked` attribute
36+
const checked = await page.getAttribute('input', 'checked');
37+
assert(checked);
38+
```
39+
40+
#### API reference
41+
42+
- [page.textContent(selector[, options])](api.md#pagetextcontentselector-options)
43+
- [page.innerText(selector[, options])](api.md#pageinnertextselector-options)
44+
- [page.innerHTML(selector[, options])](api.md#pageinnerhtmlselector-options)
45+
- [page.getAttribute(selector, name[, options])](api.md#pagegetattributeselector-name-options)
46+
- [frame.textContent(selector[, options])](api.md#frametextcontentselector-options)
47+
- [frame.innerText(selector[, options])](api.md#frameinnertextselector-options)
48+
- [frame.innerHTML(selector[, options])](api.md#frameinnerhtmlselector-options)
49+
- [frame.getAttribute(selector, name[, options])](api.md#framegetattributeselector-name-options)
50+
51+
<br/>
52+
53+
## Element Handles
54+
55+
[ElementHandle](api.md#class-elementhandle) objects represent in-page DOM
56+
elements. They can be used to assert for multiple properties of the element.
57+
58+
It is recommended to fetch the `ElementHandle` object with
59+
[`page.waitForSelector`](api.md#pagewaitforselectorselector-options) or
60+
[`frame.waitForSelector`](api.md#framewaitforselectorselector-options). These
61+
APIs wait for the element to be visible and then return an `ElementHandle`.
62+
63+
```js
64+
// Get the element handle
65+
const elementHandle = page.waitForSelector('#box');
66+
67+
// Assert bounding box for the element
68+
const boundingBox = await elementHandle.boundingBox();
69+
assert(boundingBox.width === 100);
70+
71+
// Assert attribute for the element
72+
const classNames = await elementHandle.getAttribute('class');
73+
assert(classNames.includes('highlighted'));
74+
```
75+
76+
#### API reference
77+
78+
- [elementHandle.textContent()](api.md#elementhandletextcontent)
79+
- [elementHandle.innerText()](api.md#elementhandleinnertext)
80+
- [elementHandle.innerHTML()](api.md#elementhandleinnerhtml)
81+
- [elementHandle.getAttribute(name)](api.md#elementhandlegetattributename)
82+
- [elementHandle.boundingBox()](api.md#elementhandleboundingbox)
83+
84+
<br/>
85+
86+
## Custom assertions
87+
88+
With Playwright, you can also write custom JavaScript to run in the context of
89+
the browser. This is useful in situations where you want to assert for values
90+
that are not covered by the convenience APIs above.
91+
92+
The following APIs do not auto-wait for the element. It is recommended to use
93+
[`page.waitForSelector`](api.md#pagewaitforselectorselector-options) or
94+
[`frame.waitForSelector`](api.md#framewaitforselectorselector-options).
95+
96+
```js
97+
// Assert local storage value
98+
const userId = page.evaluate(() => window.localStorage.getItem('userId'));
99+
assert(userId);
100+
101+
// Assert value for input element
102+
await page.waitForSelector('#search');
103+
const value = await page.$eval('#search', el => el.value);
104+
assert(value === 'query');
105+
106+
// Assert computed style
107+
const fontSize = await page.$eval('div', el => window.getComputedStyle(el).fontSize);
108+
assert(fontSize === '16px');
109+
110+
// Assert list length
111+
const length = await page.$$eval('li.selected', (items) => items.length);
112+
assert(length === 3);
113+
```
114+
115+
#### API reference
116+
117+
- [page.evaluate(pageFunction[, arg])](api.md#pageevaluatepagefunction-arg)
118+
- [page.$eval(selector, pageFunction[, arg])](api.md#pageevalselector-pagefunction-arg)
119+
- [page.$$eval(selector, pageFunction[, arg])](api.md#pageevalselector-pagefunction-arg-1)
120+
- [frame.evaluate(pageFunction[, arg])](api.md#frameevaluatepagefunction-arg)
121+
- [frame.$eval(selector, pageFunction[, arg])](api.md#frameevalselector-pagefunction-arg)
122+
- [frame.$$eval(selector, pageFunction[, arg])](api.md#frameevalselector-pagefunction-arg-1)
123+
- [elementHandle.$eval(selector, pageFunction[, arg])](api.md#elementhandleevalselector-pagefunction-arg)
124+
- [elementHandle.$$eval(selector, pageFunction[, arg])](api.md#elementhandleevalselector-pagefunction-arg-1)

docs/core-concepts.md

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ the following primitives.
1414
- [Pages and frames](#pages-and-frames)
1515
- [Selectors](#selectors)
1616
- [Auto-waiting](#auto-waiting)
17-
- [Node.js and browser execution contexts](#nodejs-and-browser-execution-contexts)
18-
- [Object & element handles](#object--element-handles)
17+
- [Execution contexts: Node.js and Browser](#execution-contexts-nodejs-and-browser)
18+
- [Object & Element handles](#object--element-handles)
1919
<!-- GEN:stop -->
2020

2121
<br/>
@@ -227,15 +227,30 @@ await page.waitForSelector('#promo', { state: 'detached' });
227227

228228
<br/>
229229

230-
## Node.js and browser execution contexts
230+
## Execution contexts: Node.js and Browser
231231

232-
Playwright scripts run in your Node.js environment. You page scripts run in the page environment. Those environments don't intersect, they are running in different virtual machines in different processes and potentially on different computers.
233-
234-
IMAGE PLACEHOLDER
232+
Playwright scripts run in your Node.js environment. You page scripts run in the browser page environment. Those environments don't intersect, they are running in different virtual machines in different processes and even potentially on different computers.
235233

236234
The [`page.evaluate`](https://github.com/microsoft/playwright/blob/master/docs/api.md#pageevaluatepagefunction-arg) API can run a JavaScript function in the context
237-
of the web page and bring results back to the Node.js environment. Globals like
238-
`window` and `document` along with the web page runtime can be used in `evaluate`.
235+
of the web page and bring results back to the Node.js environment. Browser globals like
236+
`window` and `document` can be used in `evaluate`.
237+
238+
```js
239+
const href = await page.evaluate(() => document.location.href);
240+
```
241+
242+
If the result is a Promise or if the function is asynchronous evaluate will automatically wait until it's resolved:
243+
```js
244+
const status = await page.evaluate(async () => {
245+
const response = await fetch(location.href);
246+
return response.status;
247+
});
248+
```
249+
250+
### Evaluation
251+
252+
Functions passed inside `page.evaluate` can accept parameters. These parameters are
253+
serialized and sent into your web page over the wire. You can pass primitive types, JSON-alike objects and remote object handles received from the page.
239254

240255
Right:
241256

@@ -257,55 +272,81 @@ const result = await page.evaluate(() => {
257272
});
258273
```
259274

260-
Evaluation parameters are serialized and sent into your web page over the wire.
261-
You can pass primitive types, JSON-alike objects and remote object handles received from the page.
275+
#### API reference
262276

263-
<br/>
277+
- [`page.evaluate(pageFunction[, arg])`](api.md#pageevaluatepagefunction-arg)
278+
- [`frame.evaluate(pageFunction[, arg])`](api.md#frameevaluatepagefunction-arg)
264279

265-
## Object & element handles
280+
<br/>
266281

267-
Playwright has an API to create Node-side handles to the page DOM elements or any other objects inside the page.
268-
These handles live in the Node.js process, whereas the actual objects reside in browser.
282+
## Object & Element handles
269283

270-
IMAGE PLACEHOLDER
284+
Playwright can create Node-side handles to the page DOM elements or any other objects inside the page. These handles live in the Node.js process, whereas the actual objects reside in browser.
271285

272286
There are two types of handles:
273-
- [`JSHandle`](./api.md#class-jshandle) to reference any javascript objects in the page
287+
- [`JSHandle`](./api.md#class-jshandle) to reference any JavaScript objects in the page
274288
- [`ElementHandle`](./api.md#class-elementhandle) to reference DOM elements in the page
275289

276-
Note that since any DOM element in the page is also a javascript object,
290+
Note that since any DOM element in the page is also a JavaScript object,
277291
Playwright's [`ElementHandle`](./api.md#class-elementhandle) extends
278292
[`JSHandle`](./api.md#class-jshandle).
279293

280-
Handles Lifetime:
294+
### Handles Lifecycle
281295
- Handles can be acquired using the page methods [`page.evaluateHandle`](./api.md#pageevaluatehandlepagefunction-arg), [`page.$`](./api.md#pageselector) or [`page.$$`](./api.md#pageselector-1) or
282296
their frame counterparts [`frame.evaluateHandle`](./api.md#frameevaluatehandlepagefunction-arg), [`frame.$`](./api.md#frameselector) or [`frame.$$`](./api.md#frameselector-1).
283-
- Once created, handles will retain object from [garbage collection](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)
297+
- Once created, handles will retain object from [garbage collection](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management).
284298
- Handles will be **automatically disposed** once the page or frame they belong to navigates or closes.
285299
- Handles can be **manually disposed** using [`jsHandle.dispose`](./api.md#jshandledispose) method.
286300

287-
Here is how you can use these handles:
301+
### Example: ElementHandle
288302

289303
```js
290304
// The first parameter of the elementHandle.evaluate callback is the element handle points to.
291305
const ulElementHandle = await page.$('ul');
292306
await ulElementHandle.evaluate(ulElement => getComputedStyle(ulElement).getPropertyValue('display'));
293307
```
294308

295-
Alternatively, handles can be passed as arguments to [`page.evaluate`](./api.md#pageevaluatepagefunction-arg) function:
309+
Handles can also be passed as arguments to [`page.evaluate`](./api.md#pageevaluatepagefunction-arg) function:
296310

297311
```js
298312
// In the page API, you can pass handle as a parameter.
299313
const ulElementHandle = await page.$('ul');
300314
await page.evaluate(uiElement => getComputedStyle(uiElement).getPropertyValue('display'), uiElement);
301315
```
302316

317+
### Example: JSHandle
318+
319+
```js
320+
// Create a new array in the page, write a reference to it in
321+
// window.myArray and get a handle to it.
322+
const myArrayHandle = await page.evaluateHandle(() => {
323+
window.myArray = [1];
324+
return myArray;
325+
});
326+
327+
// Get current length of the array using the handle.
328+
const length = await page.evaluate(
329+
(arg) => arg.myArray.length,
330+
{ myArray: myArrayHandle }
331+
);
332+
333+
// Add one more element to the array using the handle
334+
await page.evaluate((arg) => arg.myArray.push(arg.newElement), {
335+
myArray: myArrayHandle,
336+
newElement: 2
337+
});
338+
339+
// Get current length of the array using window.myArray reference.
340+
const newLength = await page.evaluate(() => window.myArray.length);
341+
342+
// Release the object when it's no longer needed.
343+
await myArrayHandle.dispose();
344+
```
345+
303346
#### API reference
304347
- [class `JSHandle`](./api.md#class-jshandle)
305348
- [class `ElementHandle`](./api.md#class-elementhandle)
306349
- [`page.evaluateHandle`](./api.md#pageevaluatehandlepagefunction-arg)
307350
- [`page.$`](./api.md#pageselector)
308351
- [`page.$$`](./api.md#pageselector-1)
309352
- [`jsHandle.evaluate`](./api.md#jshandleevaluatepagefunction-arg)
310-
311-
<br/>

0 commit comments

Comments
 (0)