You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/docs/handbook/web-testing/page-element-query-language.md
+43-38Lines changed: 43 additions & 38 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,7 @@ and **reducing test maintenance costs** across your organisation.
12
12
13
13
Serenity/JS Page Element Query Language uses **3 simple, composable abstractions** based on Screenplay [questions](/handbook/design/screenplay-pattern/#questions)
14
14
that help you identify and interact with web elements of interest:
15
+
15
16
-**[`PageElement`](/api/web/class/PageElement)** - models a **single web element**,
16
17
-**[`PageElements`](/api/web/class/PageElements)** - models a **collection of web elements**,
17
18
-**[`By`](/api/web/class/By)** - represents **portable locators** used by your browser to identify web elements of interest.
@@ -22,9 +23,9 @@ For information on how to debug PEQL expressions, see the [debugging guide](/han
22
23
23
24
## Working with individual page elements
24
25
25
-
To show you how to work with **individual page elements**,
26
+
To show you how to work with **individual page elements**,
26
27
I'll use an example shopping basket widget and demonstrate locating its various parts.
27
-
The widget is simple enough to help us focus on the important aspects of PEQL,
28
+
The widget is simple enough to help us focus on the important aspects of PEQL,
28
29
yet sophisticated enough to be representative of other widgets you're likely to come across in the wild:
29
30
30
31
```html
@@ -45,7 +46,7 @@ yet sophisticated enough to be representative of other widgets you're likely to
45
46
46
47
### Identifying individual page elements
47
48
48
-
One of the most common things to implement in a web-based test scenario is an interaction with a web element, like clicking on an button, entering a value into a form field, or asserting on some message
49
+
One of the most common things to implement in a web-based test scenario is an interaction with a web element, like clicking on a button, entering a value into a form field, or asserting on some message
49
50
presented to the end-user.
50
51
51
52
Of course, to interact with an element you need to tell your test how to find it.
@@ -60,11 +61,11 @@ export const basketTotal = () => // <- Function representing a do
60
61
```
61
62
62
63
To define a page element:
64
+
63
65
- Create a [function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions) named after the **domain concept** represented by the UI widget, such as `basketTotal`.
64
66
- Make the function return a [`PageElement`](/api/web/class/PageElement#located), configured to locate the element using one of the built-in [`By` selectors](/api/web/class/By).
65
67
- Give your page element a **human-readable description** to be used when [reporting interactions](/handbook/reporting/) with the element.
66
68
67
-
68
69
:::tip Writing portable test code
69
70
Note how giving your test functions **meaningful names**, such as `basketTotal`, helps to make your code **easier to read** and **understand**. Also note how using the `PageElement` and `By` APIs
70
71
helps your code remain **declarative**, **portable**, and agnostic of low-level integration tool-specific method calls, further improving its **reusability**.
@@ -77,7 +78,7 @@ to help your code achieve polymorphic behaviour and promote code reuse.
77
78
In practice, this means that in order to retrieve a specific attribute of a `PageElement`, you compose the element
78
79
with an [appropriate web question](/api/web).
79
80
80
-
For example, to retrieve the text value of a `PageElement` returned by `Basket.total()`, compose it with a question about its [`Text`](/api/web/class/Text):
81
+
For example, to retrieve the text value of a `PageElement` returned by `basketTotal()`, compose it with a question about its [`Text`](/api/web/class/Text):
81
82
82
83
```typescript
83
84
import { By, PageElement, Text } from'@serenity-js/web'
@@ -97,7 +98,7 @@ and others.
97
98
98
99
### Using selector aliases
99
100
100
-
In scenarios where elements use a consistent pattern allowing them to be easily identified,
101
+
In scenarios where elements use a consistent pattern allowing them to be easily identified,
101
102
such as a `data-test-it`, or a `role` attribute, you might want to implement custom selector aliases
Serenity/JS lets you compose not just the page elements, but also their **descriptions**.
491
-
In our example, description of `Text.of(itemName().of(basketItem()))` will be **derived from individual descriptions** of
492
-
questions in the chain and reported as `text of name of basket item`.
492
+
In our example, the description of `Text.of(itemName().of(basketItem()))` will be **derived from individual descriptions** of
493
+
questions in the chain and reported as `text of name of basket item`.
493
494
Of course, you can set your own description if you prefer using `.describedAs()`, too.
494
495
495
-
You might have also noticed that [`childElement.of(parentElement)`](/api/web/class/PageElement/#of) API
496
+
You might have also noticed that the [`childElement.of(parentElement)`](/api/web/class/PageElement/#of) API
496
497
works only with **individual elements**.
497
-
To map **multiple elements** we need to use `PageElements`[mapping API](/handbook/web-testing/page-element-query-language/#mapping-page-elements-in-a-collection) we'll talk about next.
498
+
To map **multiple elements** we need to use the `PageElements`[mapping API](/handbook/web-testing/page-element-query-language/#mapping-page-elements-in-a-collection), which we'll talk about next.
498
499
499
500
:::tip Serenity/JS PEQL helps you avoid code duplication
500
501
Serenity/JS PEQL lets you **compose** and **reuse** page element definitions,
@@ -508,10 +509,10 @@ especially when the system under test uses a consistent convention to name eleme
508
509
509
510
Similarly to how you [transform answers to individual questions](/handbook/web-testing/page-element-query-language/#transforming-answers-to-questions),
510
511
you can also transform each element in a collection
511
-
using [`PageElements#eachMappedTo`](/api/web/class/PageElements#eachMappedTo) API
512
+
using the [`PageElements#eachMappedTo`](/api/web/class/PageElements#eachMappedTo) API
512
513
and providing a [meta-question](/api/core/interface/MetaQuestion) to be used for the mapping.
513
514
514
-
For example, just how you'd use the meta-question about [`Text`](/api/web/class/Text/) to retrieve the text
515
+
For example, the same way you'd use the meta-question about [`Text`](/api/web/class/Text/) to retrieve the text
While Serenity/JS [expectations](/api/core/class/Expectation) are most commonly used with [assertion](#performing-assertions) and [synchronisation](#waiting-for-condition) statements,
679
-
when used with [`PageElements#where`](/api/web/class/PageElements#where) API they offer a great and reusable alternative to complex CSS selectors and XPath expressions.
680
+
While Serenity/JS [expectations](/api/core/class/Expectation) are most commonly used with [assertion](#performing-assertions) and [synchronisation](#waiting-for-conditions) statements,
681
+
when used with the [`PageElements#where`](/api/web/class/PageElements#where) API they offer a great and reusable alternative to complex CSS selectors and XPath expressions.
680
682
681
683
In this section, I'll show you how to:
684
+
682
685
- query page elements to find those that meet your expectations,
683
686
- find an interactive element based on some property of its sibling,
684
687
- iterate over selected elements to perform a common task.
0 commit comments