Skip to content

Commit 4d8c057

Browse files
committed
docs(selectors&ci): brush up respective sections
1 parent 621df5d commit 4d8c057

File tree

4 files changed

+72
-71
lines changed

4 files changed

+72
-71
lines changed

docs/README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,20 @@
3434
1. Scraping and verification
3535
- Screenshots
3636
- Evaluation
37-
1. Selector engines
38-
- Built-in engines
39-
- Custom engines
37+
1. [Continuous integration](./ci.md)
38+
- [Docker](./ci.md#docker)
39+
- [GitHub Actions](./ci.md#github-actions)
40+
- [Azure Pipelines](./ci.md#azure-pipelines)
41+
- [Travis CI](./ci.md#travis-ci)
42+
- [CircleCI](./ci.md#circleci)
43+
- [AppVeyor](./ci.md#appveyor)
4044
1. Test runners
4145
- Jest
4246
- Mocha
4347
- Karma
4448
- Jasmine
4549
- Jasmine
4650
- Storybooks
47-
1. Continuous integration
48-
- Git Hub Action
49-
- Docker images
50-
- Troubleshooting
51+
1. [Extensibility](./extensibility.md)
52+
- [Custom selector engines](./extensibility.md#custom-selector-engines)
53+

docs/ci.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
# Getting started on CI
1+
# Continuous integration.md
22

33
Playwright tests can be executed to run on your CI environments. To simplify this, we have created sample configurations for common CI providers that can be used to bootstrap your setup.
44

5+
#### Contents
56
- [Docker](#docker)
6-
- [GitHub](#github-actions)
7+
- [GitHub Actions](#github-actions)
78
- [Azure Pipelines](#azure-pipelines)
89
- [Travis CI](#travis-ci)
910
- [CircleCI](#circleci)
1011
- [AppVeyor](#appveyor)
1112

1213
Broadly, configuration on CI involves **ensuring system dependencies** are in place, **installing Playwright and browsers** (typically with `npm install`), and **running tests** (typically with `npm test`). Windows and macOS build agents do not require any additional system dependencies. Linux build agents can require additional dependencies, depending on the Linux distribution.
1314

15+
<br/>
16+
1417
## Docker
1518

1619
We have a [pre-built Docker image](docker/README.md) which can either be used directly, or as a reference to update your existing Docker definitions.

docs/core-concepts.md

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,31 +109,57 @@ await frame.fill('#username-input', 'John');
109109

110110
## Selectors
111111

112-
Playwright APIs that interact with elements accept selectors as the first argument, used to search for the element. Playwright can search for elements with CSS selectors, XPath, HTML attributes like `id`, `data-test-id` and text content.
112+
Playwright can search for elements using CSS selectors, XPath selectors, HTML attributes like `id`, `data-test-id` and even text content.
113113

114-
Note that all selectors except for XPath pierce shadow DOM automatically.
114+
You can explicitly specify the selector engine you are using or let Playwright detect it.
115+
116+
All selector engines except for XPath pierce shadow DOM by default. If you want to enforce regular DOM selection, you can use the `*:light` versions of the selectors. You don't typically need to though.
117+
118+
Learn more about selectors and selector engines [here](./selectors.md).
119+
120+
Some examples below:
121+
122+
```js
123+
// Using data-test-id= selector engine
124+
await page.click('data-test-id=foo');
125+
```
115126

116127
```js
117-
// Auto-detected CSS notation
128+
// CSS and XPath selector engines are automatically detected
118129
await page.click('div');
130+
await page.click('//html/body/div');
131+
```
119132

120-
// Explicit CSS notation
121-
await page.click('css=div');
133+
```js
134+
// Find node by text substring
135+
await page.click('text=Hello w');
136+
```
122137

123-
// Auto-detected XPath notation
138+
```js
139+
// Explicit CSS and XPath notation
140+
await page.click('css=div');
124141
await page.click('xpath=//html/body/div');
142+
```
125143

126-
// Explicit XPath notation
127-
await page.click('//html/body/div');
144+
```js
145+
// Only search light DOM, outside WebComponent shadow DOM:
146+
await page.click('css:light=div');
147+
```
128148

129-
// Auto-detected text notation
130-
await page.click('"Login"');
149+
Selectors using the same or different engines can be combined using the `>>` separator. For example,
131150

132-
// Explicit text notation
133-
await page.click('text="Login"');
151+
```js
152+
await page.click('css=article >> css=.bar > .baz >> css=span[attr=value]');
134153
```
135154

136-
Selectors using different engines can be combined using the `>>` separator. Learn more about selectors and selector engines [here](./selectors.md).
155+
is equivalent to
156+
157+
```js
158+
document
159+
.querySelector('article')
160+
.querySelector('.bar > .baz')
161+
.querySelector('span[attr=value]')
162+
```
137163

138164
<br/>
139165

@@ -148,17 +174,32 @@ Actions like `click` and `fill` auto-wait for the element to be visible and acti
148174

149175

150176
```js
151-
// Will wait for #search element to be in DOM
177+
// Playwright waits for #search element to be in DOM
152178
await page.fill('#search', 'query');
153-
154-
// Will wait for it to stop animating and accept clicks
179+
```
180+
```js
181+
// Playwright waits for element to stop animating
182+
// and accept clicks.
155183
await page.click('#search');
156184
```
157185

186+
You can explicitly wait for element to become available in DOM and to become visible:
187+
188+
```js
189+
await page.waitForSelector('#search', { waitFor: 'visible' });
190+
```
191+
192+
... or to become hidden or detached
193+
194+
```js
195+
await page.waitForSelector('#search', { waitFor: 'detached' });
196+
```
197+
158198
#### API reference
159199

160200
- [page.click(selector[, options])](./api.md#pageclickselector-options)
161201
- [page.fill(selector, value[, options])](./api.md#pagefillselector-value-options)
202+
- [page.waitForSelector(selector[, options])](./api.md#pagewaitforselectorselector-options)
162203

163204
<br/>
164205

docs/selectors.md

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -120,49 +120,3 @@ Malformed selector starting with `"` is assumed to be a text selector. For examp
120120
### id, data-testid, data-test-id, data-test and their :light counterparts
121121

122122
Attribute engines are selecting based on the corresponding atrribute value. For example: `data-test-id=foo` is equivalent to `css=[data-test-id="foo"]`, and `id:light=foo` is equivalent to `css:light=[id="foo"]`.
123-
124-
## Custom selector engines
125-
126-
Playwright supports custom selector engines, registered with [selectors.register(name, script[, options])](api.md#selectorsregistername-script-options).
127-
128-
Selector engine should have the following properties:
129-
130-
- `create` function to create a relative selector from `root` (root is either a `Document`, `ShadowRoot` or `Element`) to a `target` element.
131-
- `query` function to query first element matching `selector` relative to the `root`.
132-
- `queryAll` function to query all elements matching `selector` relative to the `root`.
133-
134-
By default the engine is run directly in the frame's JavaScript context and, for example, can call an application-defined function. To isolate the engine from any JavaScript in the frame, but leave access to the DOM, resgister the engine with `{contentScript: true}` option. Content script engine is safer because it is protected from any tampering with the global objects, for example altering `Node.prototype` methods. All built-in selector engines run as content scripts. Note that running as a content script is not guaranteed when the engine is used together with other custom engines.
135-
136-
An example of registering selector engine that queries elements based on a tag name:
137-
```js
138-
// Must be a function that evaluates to a selector engine instance.
139-
const createTagNameEngine = () => ({
140-
// Creates a selector that matches given target when queried at the root.
141-
// Can return undefined if unable to create one.
142-
create(root, target) {
143-
return root.querySelector(target.tagName) === target ? target.tagName : undefined;
144-
},
145-
146-
// Returns the first element matching given selector in the root's subtree.
147-
query(root, selector) {
148-
return root.querySelector(selector);
149-
},
150-
151-
// Returns all elements matching given selector in the root's subtree.
152-
queryAll(root, selector) {
153-
return Array.from(root.querySelectorAll(selector));
154-
}
155-
});
156-
157-
// Register the engine. Selectors will be prefixed with "tag=".
158-
await selectors.register('tag', createTagNameEngine);
159-
160-
// Now we can use 'tag=' selectors.
161-
const button = await page.$('tag=button');
162-
163-
// We can combine it with other selector engines using `>>` combinator.
164-
await page.click('tag=div >> span >> "Click me"');
165-
166-
// We can use it in any methods supporting selectors.
167-
const buttonCount = await page.$$eval('tag=button', buttons => buttons.length);
168-
```

0 commit comments

Comments
 (0)