Skip to content

Commit c0e9282

Browse files
Updated part 3 instructions
1 parent 06cb78b commit c0e9282

File tree

2 files changed

+51
-40
lines changed

2 files changed

+51
-40
lines changed

tests/test_search.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
These tests cover DuckDuckGo searches.
33
"""
44

5-
from playwright.sync_api import Page
5+
from playwright.sync_api import expect, Page
66

77

88
def test_basic_duckduckgo_search(page: Page) -> None:
9+
910
# Given the DuckDuckGo home page is displayed
1011
page.goto('https://www.duckduckgo.com')
1112

@@ -14,13 +15,13 @@ def test_basic_duckduckgo_search(page: Page) -> None:
1415
page.locator('#search_button_homepage').click()
1516

1617
# Then the search result query is the phrase
17-
assert 'panda' == page.input_value('#search_form_input')
18+
expect(page.locator('#search_form_input')).to_have_value('panda')
1819

1920
# And the search result links pertain to the phrase
20-
page.locator('.result__title a.result__a >> nth=4').wait_for()
21+
page.locator('.result__title a.result__a').nth(4).wait_for()
2122
titles = page.locator('.result__title a.result__a').all_text_contents()
2223
matches = [t for t in titles if 'panda' in t.lower()]
2324
assert len(matches) > 0
2425

2526
# And the search result title contains the phrase
26-
assert 'panda' in page.title()
27+
expect(page).to_have_title('panda at DuckDuckGo')

tutorial/3-assertions.md

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,30 @@ Here's the inspection panel for the search input element on the result page:
1717
This element also has an ID,
1818
so we can use the `#search_form_input` selector to uniquely identify it.
1919

20-
To get the textual value inside this input element,
21-
you might think that we should use the
22-
[`inner_text`](https://playwright.dev/python/docs/api/class-page#page-inner-text) method
23-
or the [`text_content`](https://playwright.dev/python/docs/api/class-page#page-text-content) method.
24-
However, neither of these are correct.
25-
To get the value of an input element, you need to get its `value` attribute.
26-
Thankfully, Playwright provides a convenient method named
27-
[`input_value`](https://playwright.dev/python/docs/api/class-page#page-input-value) to get this.
20+
To verify the textual value inside this input element,
21+
we should use Playwright's `expect` function.
22+
`expect` connects page and locator calls to Playwright's assertions.
2823

29-
Add the following line to the test case:
24+
Import the `expect` function like this:
3025

3126
```python
32-
assert 'panda' == page.input_value('#search_form_input')
27+
from playwright.sync_api import expect, Page
28+
```
29+
30+
Then, add the following line to the test case:
31+
32+
```python
33+
expect(page.locator('#search_form_input')).to_have_value('panda')
3334
```
3435

3536
This line will get the input value from the target element and assert that it is equal to the original search phrase.
3637

3738
The full test case should now look like this:
3839

3940
```python
40-
def test_basic_duckduckgo_search(page):
41+
from playwright.sync_api import expect, Page
42+
43+
def test_basic_duckduckgo_search(page: Page) -> None:
4144

4245
# Given the DuckDuckGo home page is displayed
4346
page.goto('https://www.duckduckgo.com')
@@ -47,7 +50,7 @@ def test_basic_duckduckgo_search(page):
4750
page.click('#search_button_homepage')
4851

4952
# Then the search result query is the phrase
50-
assert 'panda' == page.input_value('#search_form_input')
53+
expect(page.locator('#search_form_input')).to_have_value('panda')
5154

5255
# And the search result links pertain to the phrase
5356
# And the search result title contains the phrase
@@ -63,10 +66,18 @@ Is this a problem?
6366
Thankfully, in this case, there is no problem.
6467
Playwright automatically waits for elements to be ready before interacting with them.
6568
So, even though the test does not perform any *explicit* waiting for the result page,
66-
the `input_value` method performs *implicit* waiting for the element to be ready.
69+
the `expect` function performs *implicit* waiting for the element to satisfy the `to_have_value` condition.
6770
Check the [Auto-waiting](https://playwright.dev/python/docs/actionability) page
6871
for a full list of actionability checks for each interaction.
6972

73+
> You could use the following assert statement for this verification:
74+
>
75+
> `assert 'panda' == page.input_value('#search_form_input')`
76+
>
77+
> However, while this call will wait for the element to appear,
78+
> it will not wait for the input value to become `'panda'`.
79+
> The recommended practice is to use `expect` with locator objects.
80+
7081
Rerun the test using the same pytest command (`python3 -m pytest tests --headed --slowmo 1000`).
7182
This time, you should see the result page for a good second or two before the browser window closes.
7283
The test should still pass.
@@ -110,7 +121,7 @@ Explicit waiting will be tricky.
110121
Add the following line to the test:
111122

112123
```python
113-
page.locator('.result__title a.result__a >> nth=4').wait_for()
124+
page.locator('.result__title a.result__a').nth(4).wait_for()
114125
```
115126

116127
Let's break this down:
@@ -120,9 +131,9 @@ Let's break this down:
120131
A `Locator` object can make many of the same calls as a page, like clicking and getting text.
121132
However, it can also make calls for explicit waiting and calls that target multiple elements.
122133
2. `.result__title a.result__a` is the selector for the result links.
123-
3. `>> nth=4` is an [N-th element selector](https://playwright.dev/python/docs/selectors#n-th-element-selector).
124-
N-th element selectors are zero-indexed and may be appended to any selector.
125-
In this `locator` call, it will fetch the fifth result link element.
134+
3. `nth(4)` is an [N-th element](https://playwright.dev/python/docs/api/class-locator#locator-nth) fetcher.
135+
N-th element fetchers are zero-indexed and may be appended to any selector.
136+
In this call, it will fetch the fifth result link element.
126137
4. [`wait_for`](https://playwright.dev/python/docs/api/class-locator#locator-wait-for)
127138
is a method that will wait for the target element to be visible.
128139

@@ -168,20 +179,22 @@ Add this assertion to the test:
168179
The full test case should now look like this:
169180

170181
```python
171-
def test_basic_duckduckgo_search(page):
182+
from playwright.sync_api import expect, Page
172183

184+
def test_basic_duckduckgo_search(page: Page) -> None:
185+
173186
# Given the DuckDuckGo home page is displayed
174187
page.goto('https://www.duckduckgo.com')
175188

176189
# When the user searches for a phrase
177-
page.fill('#search_form_input_homepage', 'panda')
178-
page.click('#search_button_homepage')
190+
page.locator('#search_form_input_homepage').fill('panda')
191+
page.locator('#search_button_homepage').click()
179192

180193
# Then the search result query is the phrase
181-
assert 'panda' == page.input_value('#search_form_input')
194+
expect(page.locator('#search_form_input')).to_have_value('panda')
182195

183196
# And the search result links pertain to the phrase
184-
page.locator('.result__title a.result__a >> nth=4').wait_for()
197+
page.locator('.result__title a.result__a').nth(4).wait_for()
185198
titles = page.locator('.result__title a.result__a').all_text_contents()
186199
matches = [t for t in titles if 'panda' in t.lower()]
187200
assert len(matches) > 0
@@ -201,13 +214,13 @@ Thankfully, this one will be short.
201214

202215
The page title is an attribute of the page.
203216
It is not associated with any element on the page.
204-
We can use the [`title`](https://playwright.dev/python/docs/api/class-page#page-title) method
205-
to access it directly.
217+
We can use the [`title`](https://playwright.dev/python/docs/api/class-page#page-title) method to access it directly.
218+
For assertions, we should use `expect` with the `to_have_title` condition.
206219

207220
Add the following line to the test:
208221

209222
```python
210-
assert 'panda' in page.title()
223+
expect(page).to_have_title('panda at DuckDuckGo')
211224
```
212225

213226
This will make sure the search phrase appears in the page title.
@@ -217,26 +230,28 @@ Make sure the page is fully loaded first.
217230
The full test case should now look like this:
218231

219232
```python
220-
def test_basic_duckduckgo_search(page):
233+
from playwright.sync_api import expect, Page
221234

235+
def test_basic_duckduckgo_search(page: Page) -> None:
236+
222237
# Given the DuckDuckGo home page is displayed
223238
page.goto('https://www.duckduckgo.com')
224239

225240
# When the user searches for a phrase
226-
page.fill('#search_form_input_homepage', 'panda')
227-
page.click('#search_button_homepage')
241+
page.locator('#search_form_input_homepage').fill('panda')
242+
page.locator('#search_button_homepage').click()
228243

229244
# Then the search result query is the phrase
230-
assert 'panda' == page.input_value('#search_form_input')
245+
expect(page.locator('#search_form_input')).to_have_value('panda')
231246

232247
# And the search result links pertain to the phrase
233-
page.locator('.result__title a.result__a >> nth=4').wait_for()
248+
page.locator('.result__title a.result__a').nth(4).wait_for()
234249
titles = page.locator('.result__title a.result__a').all_text_contents()
235250
matches = [t for t in titles if 'panda' in t.lower()]
236251
assert len(matches) > 0
237252

238253
# And the search result title contains the phrase
239-
assert 'panda' in page.title()
254+
expect(page).to_have_title('panda at DuckDuckGo')
240255
```
241256

242257
We can remove the `pass` statement at the end now.
@@ -245,11 +260,6 @@ Rerun the test again to make sure it works.
245260
If it does, congrats!
246261
You have just completed a full test case in Python using Playwright with pytest.
247262

248-
Playwright's [`Page`](https://playwright.dev/python/docs/api/class-page) class
249-
provides several methods for interacting with pages and getting state from them.
250-
Read the docs to familiarize yourself with them.
251-
`Page` provides methods to interact with *every* type of web element.
252-
253263
Notice how concise this code is.
254264
Unfortunately, it's not very reusable.
255265
If other tests needed to perform DuckDuckGo searches,

0 commit comments

Comments
 (0)