playwright-ruby-client 1.43.1 → 1.44.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/documentation/docs/api/api_request_context.md +5 -3
- data/documentation/docs/api/element_handle.md +1 -1
- data/documentation/docs/api/frame.md +4 -1
- data/documentation/docs/api/keyboard.md +4 -2
- data/documentation/docs/api/locator.md +2 -1
- data/documentation/docs/api/locator_assertions.md +77 -0
- data/documentation/docs/api/page.md +6 -1
- data/documentation/docs/api/page_assertions.md +65 -0
- data/documentation/docs/include/api_coverage.md +14 -0
- data/lib/playwright/connection.rb +1 -1
- data/lib/playwright/event_emitter.rb +5 -3
- data/lib/playwright/locator_assertions_impl.rb +46 -0
- data/lib/playwright/page_assertions_impl.rb +149 -0
- data/lib/playwright/test.rb +12 -2
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright_api/api_request_context.rb +7 -6
- data/lib/playwright_api/browser_context.rb +4 -4
- data/lib/playwright_api/cdp_session.rb +1 -1
- data/lib/playwright_api/element_handle.rb +1 -1
- data/lib/playwright_api/frame.rb +4 -1
- data/lib/playwright_api/keyboard.rb +4 -2
- data/lib/playwright_api/locator.rb +2 -1
- data/lib/playwright_api/locator_assertions.rb +59 -0
- data/lib/playwright_api/page.rb +24 -6
- data/lib/playwright_api/page_assertions.rb +60 -0
- data/lib/playwright_api/playwright.rb +4 -4
- data/sig/playwright.rbs +13 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c83d71803d132d79217392a22bcbad5de47673f738badf76692ff178e4ddd27
|
4
|
+
data.tar.gz: 4d25cd84f28d6028f6335b89e4c0324847b3077004e6b21ffb6ed9740cd6ec91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 899c0d792c8021c4560240d9b61ca57b300519f5b2786f58406d65fcb44eb70301d474217c85ec710036c3eeff3119388bbe7255d5f3e6bdbe3debcc0ef425a0
|
7
|
+
data.tar.gz: 0ca7408e7e43818d7afb4660fb6c8df219eeb386f244c9cde5895cad7fa2c3f9ef26d90f99b86c7c937071cb7c66be6db631ecd883186c43064be6501e793fe6
|
@@ -106,10 +106,12 @@ def fetch(
|
|
106
106
|
|
107
107
|
|
108
108
|
Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and update
|
109
|
-
context cookies from the response. The method will automatically follow redirects.
|
109
|
+
context cookies from the response. The method will automatically follow redirects.
|
110
110
|
|
111
111
|
**Usage**
|
112
112
|
|
113
|
+
JSON objects can be passed directly to the request:
|
114
|
+
|
113
115
|
```ruby
|
114
116
|
data = {
|
115
117
|
title: "Book Title",
|
@@ -118,7 +120,7 @@ data = {
|
|
118
120
|
api_request_context.fetch("https://example.com/api/create_book", method: 'post', data: data)
|
119
121
|
```
|
120
122
|
|
121
|
-
The common way to send file(s) in the body of a request is to
|
123
|
+
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use `FormData` to construct request body and pass it to the request as `multipart` parameter:
|
122
124
|
|
123
125
|
```ruby
|
124
126
|
api_request_context.fetch(
|
@@ -252,7 +254,7 @@ form_data = {
|
|
252
254
|
api_request_context.post("https://example.com/api/find_book", form: form_data)
|
253
255
|
```
|
254
256
|
|
255
|
-
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding.
|
257
|
+
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use `FormData` to construct request body and pass it to the request as `multipart` parameter:
|
256
258
|
|
257
259
|
```ruby
|
258
260
|
api_request_context.post(
|
@@ -416,7 +416,7 @@ generate the text for. A superset of the `key` values can be found
|
|
416
416
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
417
417
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
418
418
|
|
419
|
-
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
419
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
420
420
|
|
421
421
|
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
422
422
|
|
@@ -850,7 +850,8 @@ generate the text for. A superset of the `key` values can be found
|
|
850
850
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
851
851
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
852
852
|
|
853
|
-
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
853
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
854
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
854
855
|
|
855
856
|
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
856
857
|
|
@@ -1116,6 +1117,8 @@ Waits for the required load state to be reached.
|
|
1116
1117
|
This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
|
1117
1118
|
when this method is called. If current document has already reached the required state, resolves immediately.
|
1118
1119
|
|
1120
|
+
**NOTE**: Most of the time, this method is not needed because Playwright [auto-waits before every action](https://playwright.dev/python/docs/actionability).
|
1121
|
+
|
1119
1122
|
**Usage**
|
1120
1123
|
|
1121
1124
|
```ruby
|
@@ -57,7 +57,8 @@ generate the text for. A superset of the `key` values can be found
|
|
57
57
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
58
58
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
59
59
|
|
60
|
-
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
60
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
61
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
61
62
|
|
62
63
|
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
63
64
|
|
@@ -107,7 +108,8 @@ generate the text for. A superset of the `key` values can be found
|
|
107
108
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
108
109
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
109
110
|
|
110
|
-
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
111
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
112
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
111
113
|
|
112
114
|
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
113
115
|
|
@@ -1071,7 +1071,8 @@ generate the text for. A superset of the `key` values can be found
|
|
1071
1071
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
1072
1072
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
1073
1073
|
|
1074
|
-
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
1074
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
1075
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
1075
1076
|
|
1076
1077
|
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
1077
1078
|
|
@@ -125,6 +125,24 @@ expect(locator).not_to contain_text(expected, ignoreCase: nil, timeout: nil, use
|
|
125
125
|
|
126
126
|
The opposite of [LocatorAssertions#to_contain_text](./locator_assertions#to_contain_text).
|
127
127
|
|
128
|
+
## not_to_have_accessible_description
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
expect(locator).not_to have_accessible_description(name, ignoreCase: nil, timeout: nil)
|
132
|
+
```
|
133
|
+
|
134
|
+
|
135
|
+
The opposite of [LocatorAssertions#to_have_accessible_description](./locator_assertions#to_have_accessible_description).
|
136
|
+
|
137
|
+
## not_to_have_accessible_name
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
expect(locator).not_to have_accessible_name(name, ignoreCase: nil, timeout: nil)
|
141
|
+
```
|
142
|
+
|
143
|
+
|
144
|
+
The opposite of [LocatorAssertions#to_have_accessible_name](./locator_assertions#to_have_accessible_name).
|
145
|
+
|
128
146
|
## not_to_have_attribute
|
129
147
|
|
130
148
|
```ruby
|
@@ -179,6 +197,15 @@ expect(locator).not_to have_js_property(name, value, timeout: nil)
|
|
179
197
|
|
180
198
|
The opposite of [LocatorAssertions#to_have_js_property](./locator_assertions#to_have_js_property).
|
181
199
|
|
200
|
+
## not_to_have_role
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
expect(locator).not_to have_role(name, timeout: nil)
|
204
|
+
```
|
205
|
+
|
206
|
+
|
207
|
+
The opposite of [LocatorAssertions#to_have_role](./locator_assertions#to_have_role).
|
208
|
+
|
182
209
|
## not_to_have_text
|
183
210
|
|
184
211
|
```ruby
|
@@ -445,6 +472,38 @@ expect(page.locator("ul > li")).to contain_text(["Some 33"])
|
|
445
472
|
expect(page.locator("ul")).to contain_text(["Text 3"])
|
446
473
|
```
|
447
474
|
|
475
|
+
## to_have_accessible_description
|
476
|
+
|
477
|
+
```ruby
|
478
|
+
expect(locator).to have_accessible_description(description, ignoreCase: nil, timeout: nil)
|
479
|
+
```
|
480
|
+
|
481
|
+
|
482
|
+
Ensures the [Locator](./locator) points to an element with a given [accessible description](https://w3c.github.io/accname/#dfn-accessible-description).
|
483
|
+
|
484
|
+
**Usage**
|
485
|
+
|
486
|
+
```ruby
|
487
|
+
locator = page.get_by_test_id("save-button")
|
488
|
+
expect(locator).to have_accessible_description("Save results to disk")
|
489
|
+
```
|
490
|
+
|
491
|
+
## to_have_accessible_name
|
492
|
+
|
493
|
+
```ruby
|
494
|
+
expect(locator).to have_accessible_name(name, ignoreCase: nil, timeout: nil)
|
495
|
+
```
|
496
|
+
|
497
|
+
|
498
|
+
Ensures the [Locator](./locator) points to an element with a given [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
|
499
|
+
|
500
|
+
**Usage**
|
501
|
+
|
502
|
+
```ruby
|
503
|
+
locator = page.get_by_test_id("save-button")
|
504
|
+
expect(locator).to have_accessible_name("Save to disk")
|
505
|
+
```
|
506
|
+
|
448
507
|
## to_have_attribute
|
449
508
|
|
450
509
|
```ruby
|
@@ -555,6 +614,24 @@ locator = page.locator(".component")
|
|
555
614
|
expect(locator).to have_js_property("loaded", true)
|
556
615
|
```
|
557
616
|
|
617
|
+
## to_have_role
|
618
|
+
|
619
|
+
```ruby
|
620
|
+
expect(locator).to have_role(role, timeout: nil)
|
621
|
+
```
|
622
|
+
|
623
|
+
|
624
|
+
Ensures the [Locator](./locator) points to an element with a given [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles).
|
625
|
+
|
626
|
+
Note that role is matched as a string, disregarding the ARIA role hierarchy. For example, asserting a superclass role `"checkbox"` on an element with a subclass role `"switch"` will fail.
|
627
|
+
|
628
|
+
**Usage**
|
629
|
+
|
630
|
+
```ruby
|
631
|
+
locator = page.get_by_test_id("save-button")
|
632
|
+
expect(locator).to have_role("button")
|
633
|
+
```
|
634
|
+
|
558
635
|
## to_have_text
|
559
636
|
|
560
637
|
```ruby
|
@@ -1160,7 +1160,8 @@ generate the text for. A superset of the `key` values can be found
|
|
1160
1160
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
1161
1161
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
1162
1162
|
|
1163
|
-
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
1163
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
1164
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
1164
1165
|
|
1165
1166
|
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
1166
1167
|
|
@@ -1228,6 +1229,8 @@ Once routing is enabled, every request matching the url pattern will stall unles
|
|
1228
1229
|
|
1229
1230
|
**NOTE**: [Page#route](./page#route) will not intercept requests intercepted by Service Worker. See [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using request interception by setting `Browser.newContext.serviceWorkers` to `'block'`.
|
1230
1231
|
|
1232
|
+
**NOTE**: [Page#route](./page#route) will not intercept the first request of a popup page. Use [BrowserContext#route](./browser_context#route) instead.
|
1233
|
+
|
1231
1234
|
**Usage**
|
1232
1235
|
|
1233
1236
|
An example of a naive handler that aborts all image requests:
|
@@ -1683,6 +1686,8 @@ Returns when the required load state has been reached.
|
|
1683
1686
|
This resolves when the page reaches a required load state, `load` by default. The navigation must have been committed
|
1684
1687
|
when this method is called. If current document has already reached the required state, resolves immediately.
|
1685
1688
|
|
1689
|
+
**NOTE**: Most of the time, this method is not needed because Playwright [auto-waits before every action](https://playwright.dev/python/docs/actionability).
|
1690
|
+
|
1686
1691
|
**Usage**
|
1687
1692
|
|
1688
1693
|
```ruby
|
@@ -0,0 +1,65 @@
|
|
1
|
+
---
|
2
|
+
sidebar_position: 10
|
3
|
+
---
|
4
|
+
|
5
|
+
# PageAssertions
|
6
|
+
|
7
|
+
|
8
|
+
The [PageAssertions](./page_assertions) class provides assertion methods that can be used to make assertions about the [Page](./page) state in the tests.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
page.content = <<~HTML
|
12
|
+
<a href="https://example.com/user/login">Sign in</a>
|
13
|
+
HTML
|
14
|
+
|
15
|
+
page.get_by_text("Sign in").click
|
16
|
+
expect(page).to have_url(/.*\/login/)
|
17
|
+
```
|
18
|
+
|
19
|
+
## not_to_have_title
|
20
|
+
|
21
|
+
```
|
22
|
+
def not_to_have_title(titleOrRegExp, timeout: nil)
|
23
|
+
```
|
24
|
+
|
25
|
+
|
26
|
+
The opposite of [PageAssertions#to_have_title](./page_assertions#to_have_title).
|
27
|
+
|
28
|
+
## not_to_have_url
|
29
|
+
|
30
|
+
```
|
31
|
+
def not_to_have_url(urlOrRegExp, timeout: nil)
|
32
|
+
```
|
33
|
+
|
34
|
+
|
35
|
+
The opposite of [PageAssertions#to_have_url](./page_assertions#to_have_url).
|
36
|
+
|
37
|
+
## to_have_title
|
38
|
+
|
39
|
+
```
|
40
|
+
def to_have_title(titleOrRegExp, timeout: nil)
|
41
|
+
```
|
42
|
+
|
43
|
+
|
44
|
+
Ensures the page has the given title.
|
45
|
+
|
46
|
+
**Usage**
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
expect(page).to have_title(/.*checkout/)
|
50
|
+
```
|
51
|
+
|
52
|
+
## to_have_url
|
53
|
+
|
54
|
+
```
|
55
|
+
def to_have_url(urlOrRegExp, ignoreCase: nil, timeout: nil)
|
56
|
+
```
|
57
|
+
|
58
|
+
|
59
|
+
Ensures the page is navigated to the given URL.
|
60
|
+
|
61
|
+
**Usage**
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
expect(page).to have_url(/.*checkout/)
|
65
|
+
```
|
@@ -299,6 +299,7 @@
|
|
299
299
|
* query_selector
|
300
300
|
* query_selector_all
|
301
301
|
* ~~add_locator_handler~~
|
302
|
+
* ~~remove_locator_handler~~
|
302
303
|
* reload
|
303
304
|
* route
|
304
305
|
* route_from_har
|
@@ -545,12 +546,15 @@
|
|
545
546
|
* not_to_be_in_viewport
|
546
547
|
* not_to_be_visible
|
547
548
|
* not_to_contain_text
|
549
|
+
* not_to_have_accessible_description
|
550
|
+
* not_to_have_accessible_name
|
548
551
|
* not_to_have_attribute
|
549
552
|
* not_to_have_class
|
550
553
|
* not_to_have_count
|
551
554
|
* not_to_have_css
|
552
555
|
* not_to_have_id
|
553
556
|
* not_to_have_js_property
|
557
|
+
* not_to_have_role
|
554
558
|
* not_to_have_text
|
555
559
|
* not_to_have_value
|
556
560
|
* not_to_have_values
|
@@ -565,16 +569,26 @@
|
|
565
569
|
* to_be_in_viewport
|
566
570
|
* to_be_visible
|
567
571
|
* to_contain_text
|
572
|
+
* to_have_accessible_description
|
573
|
+
* to_have_accessible_name
|
568
574
|
* to_have_attribute
|
569
575
|
* to_have_class
|
570
576
|
* to_have_count
|
571
577
|
* to_have_css
|
572
578
|
* to_have_id
|
573
579
|
* to_have_js_property
|
580
|
+
* to_have_role
|
574
581
|
* to_have_text
|
575
582
|
* to_have_value
|
576
583
|
* to_have_values
|
577
584
|
|
585
|
+
## PageAssertions
|
586
|
+
|
587
|
+
* not_to_have_title
|
588
|
+
* not_to_have_url
|
589
|
+
* to_have_title
|
590
|
+
* to_have_url
|
591
|
+
|
578
592
|
## Android
|
579
593
|
|
580
594
|
* ~~connect~~
|
@@ -37,9 +37,11 @@ module Playwright
|
|
37
37
|
# @returns [Boolean]
|
38
38
|
def emit(event, *args)
|
39
39
|
handled = false
|
40
|
-
(@__event_emitter ||= {})[event.to_s]
|
41
|
-
|
42
|
-
|
40
|
+
if (callbacks = (@__event_emitter ||= {})[event.to_s])
|
41
|
+
callbacks.dup.each do |callback|
|
42
|
+
perform_event_emitter_callback(event, callback, args)
|
43
|
+
handled = true
|
44
|
+
end
|
43
45
|
end
|
44
46
|
handled
|
45
47
|
end
|
@@ -146,6 +146,34 @@ module Playwright
|
|
146
146
|
end
|
147
147
|
_define_negation :to_contain_text
|
148
148
|
|
149
|
+
def to_have_accessible_name(name, ignoreCase: nil, timeout: nil)
|
150
|
+
expected_text = to_expected_text_values([name], ignore_case: ignoreCase)
|
151
|
+
expect_impl(
|
152
|
+
"to.have.accessible.name",
|
153
|
+
{
|
154
|
+
expectedText: expected_text,
|
155
|
+
timeout: timeout,
|
156
|
+
},
|
157
|
+
name,
|
158
|
+
"Locator expected to have accessible name"
|
159
|
+
)
|
160
|
+
end
|
161
|
+
_define_negation :to_have_accessible_name
|
162
|
+
|
163
|
+
def to_have_accessible_description(name, ignoreCase: nil, timeout: nil)
|
164
|
+
expected_text = to_expected_text_values([name], ignore_case: ignoreCase)
|
165
|
+
expect_impl(
|
166
|
+
"to.have.accessible.description",
|
167
|
+
{
|
168
|
+
expectedText: expected_text,
|
169
|
+
timeout: timeout,
|
170
|
+
},
|
171
|
+
name,
|
172
|
+
"Locator expected to have accessible description"
|
173
|
+
)
|
174
|
+
end
|
175
|
+
_define_negation :to_have_accessible_description
|
176
|
+
|
149
177
|
def to_have_attribute(name, value, ignoreCase: nil, timeout: nil)
|
150
178
|
expected_text = to_expected_text_values([value], ignore_case: ignoreCase)
|
151
179
|
expect_impl(
|
@@ -244,6 +272,24 @@ module Playwright
|
|
244
272
|
end
|
245
273
|
_define_negation :to_have_js_property
|
246
274
|
|
275
|
+
def to_have_role(role, timeout: nil)
|
276
|
+
if role.is_a?(Regexp)
|
277
|
+
raise ArgumentError.new('"role" argument in to_have_role must be a string')
|
278
|
+
end
|
279
|
+
|
280
|
+
expected_text = to_expected_text_values([role])
|
281
|
+
expect_impl(
|
282
|
+
"to.have.role",
|
283
|
+
{
|
284
|
+
expectedText: expected_text,
|
285
|
+
timeout: timeout,
|
286
|
+
},
|
287
|
+
role,
|
288
|
+
"Locator expected to have accessible role",
|
289
|
+
)
|
290
|
+
end
|
291
|
+
_define_negation :to_have_role
|
292
|
+
|
247
293
|
def to_have_value(value, timeout: nil)
|
248
294
|
expected_text = to_expected_text_values([value])
|
249
295
|
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module Playwright
|
2
|
+
# ref: https://github.com/microsoft/playwright-python/blob/main/playwright/_impl/_assertions.py
|
3
|
+
define_api_implementation :PageAssertionsImpl do
|
4
|
+
def self._define_negation(method_name)
|
5
|
+
define_method("not_#{method_name}") do |*args, **kwargs|
|
6
|
+
if kwargs.empty? # for Ruby < 2.7
|
7
|
+
_not.public_send(method_name, *args)
|
8
|
+
else
|
9
|
+
_not.public_send(method_name, *args, **kwargs)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(page, timeout, is_not, message)
|
15
|
+
@page = PlaywrightApi.unwrap(page)
|
16
|
+
@locator = @page.locator(":root")
|
17
|
+
@timeout = timeout
|
18
|
+
@is_not = is_not
|
19
|
+
@custom_message = message
|
20
|
+
end
|
21
|
+
|
22
|
+
private def expect_impl(expression, expect_options, expected, message)
|
23
|
+
expect_options[:timeout] ||= 5000
|
24
|
+
expect_options[:isNot] = @is_not
|
25
|
+
message.gsub!("expected to", "not expected to") if @is_not
|
26
|
+
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
27
|
+
|
28
|
+
result = @locator.expect(expression, expect_options)
|
29
|
+
|
30
|
+
if result["matches"] == @is_not
|
31
|
+
actual = result["received"]
|
32
|
+
|
33
|
+
log =
|
34
|
+
if result.key?("log")
|
35
|
+
log_contents = result["log"].join("\n").strip
|
36
|
+
|
37
|
+
"\nCall log:\n #{log_contents}"
|
38
|
+
else
|
39
|
+
""
|
40
|
+
end
|
41
|
+
|
42
|
+
out_message =
|
43
|
+
if @custom_message && expected
|
44
|
+
"\nExpected value: '#{expected}'"
|
45
|
+
elsif @custom_message
|
46
|
+
@custom_message
|
47
|
+
elsif message != "" && expected
|
48
|
+
"\n#{message} '#{expected}'"
|
49
|
+
else
|
50
|
+
"\n#{message}"
|
51
|
+
end
|
52
|
+
|
53
|
+
out = "#{out_message}\nActual value #{actual} #{log}"
|
54
|
+
raise AssertionError.new(out)
|
55
|
+
else
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private def _not # "not" is reserved in Ruby
|
61
|
+
PageAssertionsImpl.new(
|
62
|
+
@page,
|
63
|
+
@timeout,
|
64
|
+
!@is_not,
|
65
|
+
@message
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
private def expected_regex(pattern, match_substring, normalize_white_space, ignore_case)
|
70
|
+
regex = JavaScript::Regex.new(pattern)
|
71
|
+
expected = {
|
72
|
+
regexSource: regex.source,
|
73
|
+
regexFlags: regex.flag,
|
74
|
+
matchSubstring: match_substring,
|
75
|
+
normalizeWhiteSpace: normalize_white_space,
|
76
|
+
ignoreCase: ignore_case
|
77
|
+
}
|
78
|
+
expected.delete(:ignoreCase) if ignore_case.nil?
|
79
|
+
|
80
|
+
expected
|
81
|
+
end
|
82
|
+
|
83
|
+
private def to_expected_text_values(items, match_substring: false, normalize_white_space: false, ignore_case: false)
|
84
|
+
return [] unless items.respond_to?(:each)
|
85
|
+
|
86
|
+
items.each.with_object([]) do |item, out|
|
87
|
+
out <<
|
88
|
+
if item.is_a?(String) && ignore_case
|
89
|
+
{
|
90
|
+
string: item,
|
91
|
+
matchSubstring: match_substring,
|
92
|
+
normalizeWhiteSpace: normalize_white_space,
|
93
|
+
ignoreCase: ignore_case,
|
94
|
+
}
|
95
|
+
elsif item.is_a?(String)
|
96
|
+
{
|
97
|
+
string: item,
|
98
|
+
matchSubstring: match_substring,
|
99
|
+
normalizeWhiteSpace: normalize_white_space,
|
100
|
+
}
|
101
|
+
elsif item.is_a?(Regexp)
|
102
|
+
expected_regex(item, match_substring, normalize_white_space, ignore_case)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_have_title(title_or_regex, timeout: nil)
|
108
|
+
expected_text = to_expected_text_values(
|
109
|
+
[title_or_regex],
|
110
|
+
normalize_white_space: true,
|
111
|
+
)
|
112
|
+
|
113
|
+
expect_impl(
|
114
|
+
"to.have.title",
|
115
|
+
{
|
116
|
+
expectedText: expected_text,
|
117
|
+
timeout: timeout,
|
118
|
+
},
|
119
|
+
title_or_regex,
|
120
|
+
"Page title expected to be"
|
121
|
+
)
|
122
|
+
end
|
123
|
+
_define_negation :to_have_title
|
124
|
+
|
125
|
+
def to_have_url(url_or_regex, ignoreCase: nil, timeout: nil)
|
126
|
+
base_url = @page.context.send(:base_url)
|
127
|
+
if url_or_regex.is_a?(String) && base_url
|
128
|
+
expected = URI.join(base_url, url_or_regex).to_s
|
129
|
+
else
|
130
|
+
expected = url_or_regex
|
131
|
+
end
|
132
|
+
expected_text = to_expected_text_values(
|
133
|
+
[expected],
|
134
|
+
ignore_case: ignoreCase,
|
135
|
+
)
|
136
|
+
|
137
|
+
expect_impl(
|
138
|
+
"to.have.url",
|
139
|
+
{
|
140
|
+
expectedText: expected_text,
|
141
|
+
timeout: timeout,
|
142
|
+
},
|
143
|
+
expected,
|
144
|
+
"Page URL expected to be"
|
145
|
+
)
|
146
|
+
end
|
147
|
+
_define_negation :to_have_url
|
148
|
+
end
|
149
|
+
end
|
data/lib/playwright/test.rb
CHANGED
@@ -9,7 +9,17 @@ module Playwright
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(actual, message = nil)
|
12
|
-
|
12
|
+
case actual
|
13
|
+
when Page
|
14
|
+
PageAssertions.new(
|
15
|
+
PageAssertionsImpl.new(
|
16
|
+
actual,
|
17
|
+
@timeout_settings.timeout,
|
18
|
+
false,
|
19
|
+
message,
|
20
|
+
)
|
21
|
+
)
|
22
|
+
when Locator
|
13
23
|
LocatorAssertions.new(
|
14
24
|
LocatorAssertionsImpl.new(
|
15
25
|
actual,
|
@@ -52,7 +62,7 @@ module Playwright
|
|
52
62
|
end
|
53
63
|
end
|
54
64
|
|
55
|
-
ALL_ASSERTIONS = LocatorAssertions.instance_methods(false)
|
65
|
+
ALL_ASSERTIONS = PageAssertions.instance_methods(false) + LocatorAssertions.instance_methods(false)
|
56
66
|
|
57
67
|
ALL_ASSERTIONS
|
58
68
|
.map(&:to_s)
|
data/lib/playwright/version.rb
CHANGED
@@ -93,10 +93,12 @@ module Playwright
|
|
93
93
|
|
94
94
|
#
|
95
95
|
# Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and update
|
96
|
-
# context cookies from the response. The method will automatically follow redirects.
|
96
|
+
# context cookies from the response. The method will automatically follow redirects.
|
97
97
|
#
|
98
98
|
# **Usage**
|
99
99
|
#
|
100
|
+
# JSON objects can be passed directly to the request:
|
101
|
+
#
|
100
102
|
# ```python
|
101
103
|
# data = {
|
102
104
|
# "title": "Book Title",
|
@@ -105,12 +107,11 @@ module Playwright
|
|
105
107
|
# api_request_context.fetch("https://example.com/api/createBook", method="post", data=data)
|
106
108
|
# ```
|
107
109
|
#
|
108
|
-
# The common way to send file(s) in the body of a request is to
|
110
|
+
# The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use `FormData` to construct request body and pass it to the request as `multipart` parameter:
|
109
111
|
#
|
110
112
|
# ```python
|
111
113
|
# api_request_context.fetch(
|
112
|
-
# "https://example.com/api/
|
113
|
-
# method="post",
|
114
|
+
# "https://example.com/api/uploadScript", method="post",
|
114
115
|
# multipart={
|
115
116
|
# "fileField": {
|
116
117
|
# "name": "f.js",
|
@@ -227,11 +228,11 @@ module Playwright
|
|
227
228
|
# api_request_context.post("https://example.com/api/findBook", form=formData)
|
228
229
|
# ```
|
229
230
|
#
|
230
|
-
# The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding.
|
231
|
+
# The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use `FormData` to construct request body and pass it to the request as `multipart` parameter:
|
231
232
|
#
|
232
233
|
# ```python
|
233
234
|
# api_request_context.post(
|
234
|
-
# "https://example.com/api/
|
235
|
+
# "https://example.com/api/uploadScript'",
|
235
236
|
# multipart={
|
236
237
|
# "fileField": {
|
237
238
|
# "name": "f.js",
|
@@ -459,13 +459,13 @@ module Playwright
|
|
459
459
|
end
|
460
460
|
|
461
461
|
# @nodoc
|
462
|
-
def
|
463
|
-
wrap_impl(@impl.
|
462
|
+
def options=(req)
|
463
|
+
wrap_impl(@impl.options=(unwrap_impl(req)))
|
464
464
|
end
|
465
465
|
|
466
466
|
# @nodoc
|
467
|
-
def
|
468
|
-
wrap_impl(@impl.
|
467
|
+
def enable_debug_console!
|
468
|
+
wrap_impl(@impl.enable_debug_console!)
|
469
469
|
end
|
470
470
|
|
471
471
|
# @nodoc
|
@@ -16,7 +16,7 @@ module Playwright
|
|
16
16
|
# response = client.send("Animation.getPlaybackRate")
|
17
17
|
# print("playback rate is " + str(response["playbackRate"]))
|
18
18
|
# client.send("Animation.setPlaybackRate", {
|
19
|
-
# playbackRate: response["playbackRate"] / 2
|
19
|
+
# "playbackRate": response["playbackRate"] / 2
|
20
20
|
# })
|
21
21
|
# ```
|
22
22
|
class CDPSession < PlaywrightApi
|
@@ -339,7 +339,7 @@ module Playwright
|
|
339
339
|
# `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
340
340
|
# `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
341
341
|
#
|
342
|
-
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
342
|
+
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
343
343
|
#
|
344
344
|
# Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
345
345
|
#
|
data/lib/playwright_api/frame.rb
CHANGED
@@ -707,7 +707,8 @@ module Playwright
|
|
707
707
|
# `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
708
708
|
# `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
709
709
|
#
|
710
|
-
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
710
|
+
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
711
|
+
# `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
711
712
|
#
|
712
713
|
# Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
713
714
|
#
|
@@ -947,6 +948,8 @@ module Playwright
|
|
947
948
|
# This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
|
948
949
|
# when this method is called. If current document has already reached the required state, resolves immediately.
|
949
950
|
#
|
951
|
+
# **NOTE**: Most of the time, this method is not needed because Playwright [auto-waits before every action](../actionability.md).
|
952
|
+
#
|
950
953
|
# **Usage**
|
951
954
|
#
|
952
955
|
# ```python sync
|
@@ -48,7 +48,8 @@ module Playwright
|
|
48
48
|
# `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
49
49
|
# `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
50
50
|
#
|
51
|
-
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
51
|
+
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
52
|
+
# `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
52
53
|
#
|
53
54
|
# Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
54
55
|
#
|
@@ -92,7 +93,8 @@ module Playwright
|
|
92
93
|
# `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
93
94
|
# `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
94
95
|
#
|
95
|
-
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
96
|
+
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
97
|
+
# `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
96
98
|
#
|
97
99
|
# Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
98
100
|
#
|
@@ -902,7 +902,8 @@ module Playwright
|
|
902
902
|
# `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
903
903
|
# `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
904
904
|
#
|
905
|
-
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
905
|
+
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
906
|
+
# `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
906
907
|
#
|
907
908
|
# Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
908
909
|
#
|
@@ -78,6 +78,18 @@ module Playwright
|
|
78
78
|
wrap_impl(@impl.not_to_contain_text(unwrap_impl(expected), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout), useInnerText: unwrap_impl(useInnerText)))
|
79
79
|
end
|
80
80
|
|
81
|
+
#
|
82
|
+
# The opposite of [`method: LocatorAssertions.toHaveAccessibleDescription`].
|
83
|
+
def not_to_have_accessible_description(name, ignoreCase: nil, timeout: nil)
|
84
|
+
wrap_impl(@impl.not_to_have_accessible_description(unwrap_impl(name), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout)))
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# The opposite of [`method: LocatorAssertions.toHaveAccessibleName`].
|
89
|
+
def not_to_have_accessible_name(name, ignoreCase: nil, timeout: nil)
|
90
|
+
wrap_impl(@impl.not_to_have_accessible_name(unwrap_impl(name), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout)))
|
91
|
+
end
|
92
|
+
|
81
93
|
#
|
82
94
|
# The opposite of [`method: LocatorAssertions.toHaveAttribute`].
|
83
95
|
def not_to_have_attribute(name, value, ignoreCase: nil, timeout: nil)
|
@@ -114,6 +126,12 @@ module Playwright
|
|
114
126
|
wrap_impl(@impl.not_to_have_js_property(unwrap_impl(name), unwrap_impl(value), timeout: unwrap_impl(timeout)))
|
115
127
|
end
|
116
128
|
|
129
|
+
#
|
130
|
+
# The opposite of [`method: LocatorAssertions.toHaveRole`].
|
131
|
+
def not_to_have_role(name, timeout: nil)
|
132
|
+
wrap_impl(@impl.not_to_have_role(unwrap_impl(name), timeout: unwrap_impl(timeout)))
|
133
|
+
end
|
134
|
+
|
117
135
|
#
|
118
136
|
# The opposite of [`method: LocatorAssertions.toHaveText`].
|
119
137
|
def not_to_have_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
|
@@ -354,6 +372,32 @@ module Playwright
|
|
354
372
|
wrap_impl(@impl.to_contain_text(unwrap_impl(expected), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout), useInnerText: unwrap_impl(useInnerText)))
|
355
373
|
end
|
356
374
|
|
375
|
+
#
|
376
|
+
# Ensures the `Locator` points to an element with a given [accessible description](https://w3c.github.io/accname/#dfn-accessible-description).
|
377
|
+
#
|
378
|
+
# **Usage**
|
379
|
+
#
|
380
|
+
# ```python sync
|
381
|
+
# locator = page.get_by_test_id("save-button")
|
382
|
+
# expect(locator).to_have_accessible_description("Save results to disk")
|
383
|
+
# ```
|
384
|
+
def to_have_accessible_description(description, ignoreCase: nil, timeout: nil)
|
385
|
+
wrap_impl(@impl.to_have_accessible_description(unwrap_impl(description), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout)))
|
386
|
+
end
|
387
|
+
|
388
|
+
#
|
389
|
+
# Ensures the `Locator` points to an element with a given [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
|
390
|
+
#
|
391
|
+
# **Usage**
|
392
|
+
#
|
393
|
+
# ```python sync
|
394
|
+
# locator = page.get_by_test_id("save-button")
|
395
|
+
# expect(locator).to_have_accessible_name("Save to disk")
|
396
|
+
# ```
|
397
|
+
def to_have_accessible_name(name, ignoreCase: nil, timeout: nil)
|
398
|
+
wrap_impl(@impl.to_have_accessible_name(unwrap_impl(name), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout)))
|
399
|
+
end
|
400
|
+
|
357
401
|
#
|
358
402
|
# Ensures the `Locator` points to an element with given attribute.
|
359
403
|
#
|
@@ -460,6 +504,21 @@ module Playwright
|
|
460
504
|
wrap_impl(@impl.to_have_js_property(unwrap_impl(name), unwrap_impl(value), timeout: unwrap_impl(timeout)))
|
461
505
|
end
|
462
506
|
|
507
|
+
#
|
508
|
+
# Ensures the `Locator` points to an element with a given [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles).
|
509
|
+
#
|
510
|
+
# Note that role is matched as a string, disregarding the ARIA role hierarchy. For example, asserting a superclass role `"checkbox"` on an element with a subclass role `"switch"` will fail.
|
511
|
+
#
|
512
|
+
# **Usage**
|
513
|
+
#
|
514
|
+
# ```python sync
|
515
|
+
# locator = page.get_by_test_id("save-button")
|
516
|
+
# expect(locator).to_have_role("button")
|
517
|
+
# ```
|
518
|
+
def to_have_role(role, timeout: nil)
|
519
|
+
wrap_impl(@impl.to_have_role(unwrap_impl(role), timeout: unwrap_impl(timeout)))
|
520
|
+
end
|
521
|
+
|
463
522
|
#
|
464
523
|
# Ensures the `Locator` points to an element with the given text. All nested elements will be considered when computing the text content of the element. You can use regular expressions for the value as well.
|
465
524
|
#
|
data/lib/playwright_api/page.rb
CHANGED
@@ -1032,7 +1032,8 @@ module Playwright
|
|
1032
1032
|
# `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
1033
1033
|
# `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
1034
1034
|
#
|
1035
|
-
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
1035
|
+
# Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
1036
|
+
# `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
1036
1037
|
#
|
1037
1038
|
# Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
1038
1039
|
#
|
@@ -1079,8 +1080,6 @@ module Playwright
|
|
1079
1080
|
wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
|
1080
1081
|
end
|
1081
1082
|
|
1082
|
-
#
|
1083
|
-
# **NOTE**: This method is experimental and its behavior may change in the upcoming releases.
|
1084
1083
|
#
|
1085
1084
|
# When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making them tricky to handle in automated tests.
|
1086
1085
|
#
|
@@ -1089,6 +1088,7 @@ module Playwright
|
|
1089
1088
|
# Things to keep in mind:
|
1090
1089
|
# - When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as a part of your normal test flow, instead of using [`method: Page.addLocatorHandler`].
|
1091
1090
|
# - Playwright checks for the overlay every time before executing or retrying an action that requires an [actionability check](../actionability.md), or before performing an auto-waiting assertion check. When overlay is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the handler is only called when you perform an action/assertion - if the overlay becomes visible but you don't perform any actions, the handler will not be triggered.
|
1091
|
+
# - After executing the handler, Playwright will ensure that overlay that triggered the handler is not visible anymore. You can opt-out of this behavior with `noWaitAfter`.
|
1092
1092
|
# - The execution time of the handler counts towards the timeout of the action/assertion that executed the handler. If your handler takes too long, it might cause timeouts.
|
1093
1093
|
# - You can register multiple handlers. However, only a single handler will be running at a time. Make sure the actions within a handler don't depend on another handler.
|
1094
1094
|
#
|
@@ -1128,22 +1128,36 @@ module Playwright
|
|
1128
1128
|
# page.get_by_role("button", name="Start here").click()
|
1129
1129
|
# ```
|
1130
1130
|
#
|
1131
|
-
# An example with a custom callback on every actionability check. It uses a `<body>` locator that is always visible, so the handler is called before every actionability check
|
1131
|
+
# An example with a custom callback on every actionability check. It uses a `<body>` locator that is always visible, so the handler is called before every actionability check. It is important to specify `noWaitAfter`, because the handler does not hide the `<body>` element.
|
1132
1132
|
#
|
1133
1133
|
# ```python sync
|
1134
1134
|
# # Setup the handler.
|
1135
1135
|
# def handler():
|
1136
1136
|
# page.evaluate("window.removeObstructionsForTestIfNeeded()")
|
1137
|
-
# page.add_locator_handler(page.locator("body"), handler)
|
1137
|
+
# page.add_locator_handler(page.locator("body"), handler, no_wait_after=True)
|
1138
1138
|
#
|
1139
1139
|
# # Write the test as usual.
|
1140
1140
|
# page.goto("https://example.com")
|
1141
1141
|
# page.get_by_role("button", name="Start here").click()
|
1142
1142
|
# ```
|
1143
|
-
|
1143
|
+
#
|
1144
|
+
# Handler takes the original locator as an argument. You can also automatically remove the handler after a number of invocations by setting `times`:
|
1145
|
+
#
|
1146
|
+
# ```python sync
|
1147
|
+
# def handler(locator):
|
1148
|
+
# locator.click()
|
1149
|
+
# page.add_locator_handler(page.get_by_label("Close"), handler, times=1)
|
1150
|
+
# ```
|
1151
|
+
def add_locator_handler(locator, handler, noWaitAfter: nil, times: nil)
|
1144
1152
|
raise NotImplementedError.new('add_locator_handler is not implemented yet.')
|
1145
1153
|
end
|
1146
1154
|
|
1155
|
+
#
|
1156
|
+
# Removes all locator handlers added by [`method: Page.addLocatorHandler`] for a specific locator.
|
1157
|
+
def remove_locator_handler(locator)
|
1158
|
+
raise NotImplementedError.new('remove_locator_handler is not implemented yet.')
|
1159
|
+
end
|
1160
|
+
|
1147
1161
|
#
|
1148
1162
|
# This method reloads the current page, in the same way as if the user had triggered a browser refresh.
|
1149
1163
|
# Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
|
@@ -1161,6 +1175,8 @@ module Playwright
|
|
1161
1175
|
#
|
1162
1176
|
# **NOTE**: [`method: Page.route`] will not intercept requests intercepted by Service Worker. See [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using request interception by setting `Browser.newContext.serviceWorkers` to `'block'`.
|
1163
1177
|
#
|
1178
|
+
# **NOTE**: [`method: Page.route`] will not intercept the first request of a popup page. Use [`method: BrowserContext.route`] instead.
|
1179
|
+
#
|
1164
1180
|
# **Usage**
|
1165
1181
|
#
|
1166
1182
|
# An example of a naive handler that aborts all image requests:
|
@@ -1548,6 +1564,8 @@ module Playwright
|
|
1548
1564
|
# This resolves when the page reaches a required load state, `load` by default. The navigation must have been committed
|
1549
1565
|
# when this method is called. If current document has already reached the required state, resolves immediately.
|
1550
1566
|
#
|
1567
|
+
# **NOTE**: Most of the time, this method is not needed because Playwright [auto-waits before every action](../actionability.md).
|
1568
|
+
#
|
1551
1569
|
# **Usage**
|
1552
1570
|
#
|
1553
1571
|
# ```python sync
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Playwright
|
2
|
+
#
|
3
|
+
# The `PageAssertions` class provides assertion methods that can be used to make assertions about the `Page` state in the tests.
|
4
|
+
#
|
5
|
+
# ```python sync
|
6
|
+
# import re
|
7
|
+
# from playwright.sync_api import Page, expect
|
8
|
+
#
|
9
|
+
# def test_navigates_to_login_page(page: Page) -> None:
|
10
|
+
# # ..
|
11
|
+
# page.get_by_text("Sign in").click()
|
12
|
+
# expect(page).to_have_url(re.compile(r".*/login"))
|
13
|
+
# ```
|
14
|
+
class PageAssertions < PlaywrightApi
|
15
|
+
|
16
|
+
#
|
17
|
+
# The opposite of [`method: PageAssertions.toHaveTitle`].
|
18
|
+
def not_to_have_title(titleOrRegExp, timeout: nil)
|
19
|
+
wrap_impl(@impl.not_to_have_title(unwrap_impl(titleOrRegExp), timeout: unwrap_impl(timeout)))
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# The opposite of [`method: PageAssertions.toHaveURL`].
|
24
|
+
def not_to_have_url(urlOrRegExp, timeout: nil)
|
25
|
+
wrap_impl(@impl.not_to_have_url(unwrap_impl(urlOrRegExp), timeout: unwrap_impl(timeout)))
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Ensures the page has the given title.
|
30
|
+
#
|
31
|
+
# **Usage**
|
32
|
+
#
|
33
|
+
# ```python sync
|
34
|
+
# import re
|
35
|
+
# from playwright.sync_api import expect
|
36
|
+
#
|
37
|
+
# # ...
|
38
|
+
# expect(page).to_have_title(re.compile(r".*checkout"))
|
39
|
+
# ```
|
40
|
+
def to_have_title(titleOrRegExp, timeout: nil)
|
41
|
+
wrap_impl(@impl.to_have_title(unwrap_impl(titleOrRegExp), timeout: unwrap_impl(timeout)))
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Ensures the page is navigated to the given URL.
|
46
|
+
#
|
47
|
+
# **Usage**
|
48
|
+
#
|
49
|
+
# ```python sync
|
50
|
+
# import re
|
51
|
+
# from playwright.sync_api import expect
|
52
|
+
#
|
53
|
+
# # ...
|
54
|
+
# expect(page).to_have_url(re.compile(".*checkout"))
|
55
|
+
# ```
|
56
|
+
def to_have_url(urlOrRegExp, ignoreCase: nil, timeout: nil)
|
57
|
+
wrap_impl(@impl.to_have_url(unwrap_impl(urlOrRegExp), ignoreCase: unwrap_impl(ignoreCase), timeout: unwrap_impl(timeout)))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -94,13 +94,13 @@ module Playwright
|
|
94
94
|
end
|
95
95
|
|
96
96
|
# @nodoc
|
97
|
-
def
|
98
|
-
wrap_impl(@impl.
|
97
|
+
def electron
|
98
|
+
wrap_impl(@impl.electron)
|
99
99
|
end
|
100
100
|
|
101
101
|
# @nodoc
|
102
|
-
def
|
103
|
-
wrap_impl(@impl.
|
102
|
+
def android
|
103
|
+
wrap_impl(@impl.android)
|
104
104
|
end
|
105
105
|
|
106
106
|
# -- inherited from EventEmitter --
|
data/sig/playwright.rbs
CHANGED
@@ -554,12 +554,15 @@ module Playwright
|
|
554
554
|
def not_to_be_in_viewport: (?ratio: Float, ?timeout: Float) -> void
|
555
555
|
def not_to_be_visible: (?timeout: Float, ?visible: bool) -> void
|
556
556
|
def not_to_contain_text: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?ignoreCase: bool, ?timeout: Float, ?useInnerText: bool) -> void
|
557
|
+
def not_to_have_accessible_description: ((String | Regexp) name, ?ignoreCase: bool, ?timeout: Float) -> void
|
558
|
+
def not_to_have_accessible_name: ((String | Regexp) name, ?ignoreCase: bool, ?timeout: Float) -> void
|
557
559
|
def not_to_have_attribute: (String name, (String | Regexp) value, ?ignoreCase: bool, ?timeout: Float) -> void
|
558
560
|
def not_to_have_class: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?timeout: Float) -> void
|
559
561
|
def not_to_have_count: (Integer count, ?timeout: Float) -> void
|
560
562
|
def not_to_have_css: (String name, (String | Regexp) value, ?timeout: Float) -> void
|
561
563
|
def not_to_have_id: ((String | Regexp) id, ?timeout: Float) -> void
|
562
564
|
def not_to_have_js_property: (String name, untyped value, ?timeout: Float) -> void
|
565
|
+
def not_to_have_role: ((String | Regexp) name, ?timeout: Float) -> void
|
563
566
|
def not_to_have_text: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?ignoreCase: bool, ?timeout: Float, ?useInnerText: bool) -> void
|
564
567
|
def not_to_have_value: ((String | Regexp) value, ?timeout: Float) -> void
|
565
568
|
def not_to_have_values: ((Array[untyped] | Array[untyped] | Array[untyped]) values, ?timeout: Float) -> void
|
@@ -574,17 +577,27 @@ module Playwright
|
|
574
577
|
def to_be_in_viewport: (?ratio: Float, ?timeout: Float) -> void
|
575
578
|
def to_be_visible: (?timeout: Float, ?visible: bool) -> void
|
576
579
|
def to_contain_text: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?ignoreCase: bool, ?timeout: Float, ?useInnerText: bool) -> void
|
580
|
+
def to_have_accessible_description: ((String | Regexp) description, ?ignoreCase: bool, ?timeout: Float) -> void
|
581
|
+
def to_have_accessible_name: ((String | Regexp) name, ?ignoreCase: bool, ?timeout: Float) -> void
|
577
582
|
def to_have_attribute: (String name, (String | Regexp) value, ?ignoreCase: bool, ?timeout: Float) -> void
|
578
583
|
def to_have_class: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?timeout: Float) -> void
|
579
584
|
def to_have_count: (Integer count, ?timeout: Float) -> void
|
580
585
|
def to_have_css: (String name, (String | Regexp) value, ?timeout: Float) -> void
|
581
586
|
def to_have_id: ((String | Regexp) id, ?timeout: Float) -> void
|
582
587
|
def to_have_js_property: (String name, untyped value, ?timeout: Float) -> void
|
588
|
+
def to_have_role: (("alert" | "alertdialog" | "application" | "article" | "banner" | "blockquote" | "button" | "caption" | "cell" | "checkbox" | "code" | "columnheader" | "combobox" | "complementary" | "contentinfo" | "definition" | "deletion" | "dialog" | "directory" | "document" | "emphasis" | "feed" | "figure" | "form" | "generic" | "grid" | "gridcell" | "group" | "heading" | "img" | "insertion" | "link" | "list" | "listbox" | "listitem" | "log" | "main" | "marquee" | "math" | "meter" | "menu" | "menubar" | "menuitem" | "menuitemcheckbox" | "menuitemradio" | "navigation" | "none" | "note" | "option" | "paragraph" | "presentation" | "progressbar" | "radio" | "radiogroup" | "region" | "row" | "rowgroup" | "rowheader" | "scrollbar" | "search" | "searchbox" | "separator" | "slider" | "spinbutton" | "status" | "strong" | "subscript" | "superscript" | "switch" | "tab" | "table" | "tablist" | "tabpanel" | "term" | "textbox" | "time" | "timer" | "toolbar" | "tooltip" | "tree" | "treegrid" | "treeitem") role, ?timeout: Float) -> void
|
583
589
|
def to_have_text: ((String | Regexp | Array[untyped] | Array[untyped] | Array[untyped]) expected, ?ignoreCase: bool, ?timeout: Float, ?useInnerText: bool) -> void
|
584
590
|
def to_have_value: ((String | Regexp) value, ?timeout: Float) -> void
|
585
591
|
def to_have_values: ((Array[untyped] | Array[untyped] | Array[untyped]) values, ?timeout: Float) -> void
|
586
592
|
end
|
587
593
|
|
594
|
+
class PageAssertions
|
595
|
+
def not_to_have_title: ((String | Regexp) titleOrRegExp, ?timeout: Float) -> void
|
596
|
+
def not_to_have_url: ((String | Regexp) urlOrRegExp, ?timeout: Float) -> void
|
597
|
+
def to_have_title: ((String | Regexp) titleOrRegExp, ?timeout: Float) -> void
|
598
|
+
def to_have_url: ((String | Regexp) urlOrRegExp, ?ignoreCase: bool, ?timeout: Float) -> void
|
599
|
+
end
|
600
|
+
|
588
601
|
class Android
|
589
602
|
def devices: (?host: String, ?omitDriverInstall: bool, ?port: Integer) -> Array[untyped]
|
590
603
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: playwright-ruby-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.44.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -236,6 +236,7 @@ files:
|
|
236
236
|
- documentation/docs/api/locator_assertions.md
|
237
237
|
- documentation/docs/api/mouse.md
|
238
238
|
- documentation/docs/api/page.md
|
239
|
+
- documentation/docs/api/page_assertions.md
|
239
240
|
- documentation/docs/api/playwright.md
|
240
241
|
- documentation/docs/api/request.md
|
241
242
|
- documentation/docs/api/response.md
|
@@ -333,6 +334,7 @@ files:
|
|
333
334
|
- lib/playwright/locator_impl.rb
|
334
335
|
- lib/playwright/locator_utils.rb
|
335
336
|
- lib/playwright/mouse_impl.rb
|
337
|
+
- lib/playwright/page_assertions_impl.rb
|
336
338
|
- lib/playwright/playwright_api.rb
|
337
339
|
- lib/playwright/raw_headers.rb
|
338
340
|
- lib/playwright/route_handler.rb
|
@@ -374,6 +376,7 @@ files:
|
|
374
376
|
- lib/playwright_api/locator_assertions.rb
|
375
377
|
- lib/playwright_api/mouse.rb
|
376
378
|
- lib/playwright_api/page.rb
|
379
|
+
- lib/playwright_api/page_assertions.rb
|
377
380
|
- lib/playwright_api/playwright.rb
|
378
381
|
- lib/playwright_api/request.rb
|
379
382
|
- lib/playwright_api/response.rb
|
@@ -407,5 +410,5 @@ requirements: []
|
|
407
410
|
rubygems_version: 3.3.27
|
408
411
|
signing_key:
|
409
412
|
specification_version: 4
|
410
|
-
summary: The Ruby binding of playwright driver 1.
|
413
|
+
summary: The Ruby binding of playwright driver 1.44.0
|
411
414
|
test_files: []
|