playwright-ruby-client 1.14.beta2 → 1.15.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +10 -14
- data/documentation/docs/api/accessibility.md +16 -17
- data/documentation/docs/api/browser.md +4 -0
- data/documentation/docs/api/browser_context.md +5 -1
- data/documentation/docs/api/browser_type.md +2 -0
- data/documentation/docs/api/element_handle.md +30 -5
- data/documentation/docs/api/experimental/android.md +15 -2
- data/documentation/docs/api/experimental/android_device.md +2 -0
- data/documentation/docs/api/frame.md +86 -104
- data/documentation/docs/api/locator.md +69 -40
- data/documentation/docs/api/mouse.md +3 -4
- data/documentation/docs/api/page.md +38 -7
- data/documentation/docs/api/request.md +42 -20
- data/documentation/docs/api/response.md +18 -1
- data/documentation/docs/api/selectors.md +29 -3
- data/documentation/docs/api/tracing.md +51 -16
- data/documentation/docs/api/worker.md +12 -11
- data/documentation/docs/article/getting_started.md +10 -1
- data/documentation/docs/article/guides/download_playwright_driver.md +9 -0
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +56 -3
- data/documentation/docs/article/guides/rails_integration.md +4 -2
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +86 -0
- data/documentation/docs/article/guides/recording_video.md +1 -1
- data/documentation/docs/article/guides/semi_automation.md +2 -2
- data/documentation/docs/article/guides/use_storage_state.md +78 -0
- data/documentation/docs/include/api_coverage.md +11 -0
- data/documentation/docusaurus.config.js +1 -0
- data/documentation/package.json +2 -2
- data/documentation/src/pages/index.js +0 -1
- data/documentation/static/img/playwright-ruby-client.png +0 -0
- data/documentation/yarn.lock +625 -549
- data/lib/playwright/channel.rb +36 -2
- data/lib/playwright/channel_owners/artifact.rb +6 -2
- data/lib/playwright/channel_owners/browser.rb +4 -0
- data/lib/playwright/channel_owners/browser_context.rb +21 -14
- data/lib/playwright/channel_owners/browser_type.rb +0 -1
- data/lib/playwright/channel_owners/element_handle.rb +10 -2
- data/lib/playwright/channel_owners/frame.rb +8 -0
- data/lib/playwright/channel_owners/page.rb +20 -4
- data/lib/playwright/channel_owners/playwright.rb +9 -0
- data/lib/playwright/channel_owners/request.rb +46 -25
- data/lib/playwright/channel_owners/response.rb +41 -5
- data/lib/playwright/connection.rb +8 -11
- data/lib/playwright/http_headers.rb +9 -4
- data/lib/playwright/locator_impl.rb +11 -3
- data/lib/playwright/{route_handler_entry.rb → route_handler.rb} +30 -2
- data/lib/playwright/tracing_impl.rb +18 -7
- data/lib/playwright/transport.rb +2 -0
- data/lib/playwright/utils.rb +8 -1
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/web_socket_transport.rb +2 -0
- data/lib/playwright.rb +45 -5
- data/lib/playwright_api/android.rb +21 -8
- data/lib/playwright_api/android_device.rb +11 -9
- data/lib/playwright_api/browser.rb +12 -8
- data/lib/playwright_api/browser_context.rb +12 -8
- data/lib/playwright_api/browser_type.rb +9 -7
- data/lib/playwright_api/cdp_session.rb +6 -6
- data/lib/playwright_api/console_message.rb +6 -6
- data/lib/playwright_api/dialog.rb +6 -6
- data/lib/playwright_api/element_handle.rb +31 -8
- data/lib/playwright_api/frame.rb +35 -12
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/locator.rb +41 -2
- data/lib/playwright_api/page.rb +43 -15
- data/lib/playwright_api/playwright.rb +6 -6
- data/lib/playwright_api/request.rb +29 -7
- data/lib/playwright_api/response.rb +23 -7
- data/lib/playwright_api/route.rb +6 -6
- data/lib/playwright_api/selectors.rb +38 -7
- data/lib/playwright_api/tracing.rb +33 -4
- data/lib/playwright_api/web_socket.rb +6 -6
- data/lib/playwright_api/worker.rb +8 -8
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2247f39a5fa4881e45ad884606295d7003b3e42ca9db5436b223d921649e5553
|
|
4
|
+
data.tar.gz: f7f57d5044c66e300912578faa1d8114ee98f2eb1de736eac3da698e7851b9d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86b2003368d06755bfef64cebe40c716ef9d0156d6bd21f18fddc79cef07ffee5a48f562294c32b956dd664b5480326587736ee56334c76e80e8a8e2b89dfb72
|
|
7
|
+
data.tar.gz: 20697ed55fb7ce54856d04dc0f9568316d5941b0b103ce5c0138e680a28aeda1b7876a3cf4d358f006a2b5d7115a267ed8e7c689064bf54f65e6797848d69a2f
|
data/README.md
CHANGED
|
@@ -6,19 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
## Getting Started
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
npx playwright install
|
|
9
|
+
```
|
|
10
|
+
gem 'playwright-ruby-client'
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
and then
|
|
16
|
-
|
|
17
|
-
**Prefer npm install instead of npx?**
|
|
18
|
-
|
|
19
|
-
Actually `npx playwright` is a bit slow. We can also use `npm install` to setup.
|
|
13
|
+
and then 'bundle install'.
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
Since playwright-ruby-client doesn't include the playwright driver, **we have to install [playwright](https://github.com/microsoft/playwright) in advance**.
|
|
22
16
|
|
|
23
17
|
```
|
|
24
18
|
npm install playwright
|
|
@@ -29,14 +23,14 @@ And set `playwright_cli_executable_path: './node_modules/.bin/playwright'`
|
|
|
29
23
|
|
|
30
24
|
**Prefer playwrighting without Node.js?**
|
|
31
25
|
|
|
32
|
-
Instead of npm, you can also directly download playwright driver from playwright.azureedge.net/builds/. The URL can be easily detected from [here](https://github.com/microsoft/playwright-python/blob/
|
|
26
|
+
Instead of npm, you can also directly download playwright driver from playwright.azureedge.net/builds/. The URL can be easily detected from [here](https://github.com/microsoft/playwright-python/blob/cb5409934629adaabc0cff1891080de2052fa778/setup.py#L73-L77)
|
|
33
27
|
|
|
34
28
|
### Capture a site
|
|
35
29
|
|
|
36
30
|
```ruby
|
|
37
31
|
require 'playwright'
|
|
38
32
|
|
|
39
|
-
Playwright.create(playwright_cli_executable_path: '
|
|
33
|
+
Playwright.create(playwright_cli_executable_path: './node_modules/.bin/playwright') do |playwright|
|
|
40
34
|
playwright.chromium.launch(headless: false) do |browser|
|
|
41
35
|
page = browser.new_page
|
|
42
36
|
page.goto('https://github.com/YusukeIwaki')
|
|
@@ -52,7 +46,7 @@ end
|
|
|
52
46
|
```ruby
|
|
53
47
|
require 'playwright'
|
|
54
48
|
|
|
55
|
-
Playwright.create(playwright_cli_executable_path: '
|
|
49
|
+
Playwright.create(playwright_cli_executable_path: './node_modules/.bin/playwright') do |playwright|
|
|
56
50
|
playwright.chromium.launch(headless: false) do |browser|
|
|
57
51
|
page = browser.new_page
|
|
58
52
|
page.goto('https://github.com/')
|
|
@@ -94,7 +88,7 @@ $ bundle exec ruby main.rb
|
|
|
94
88
|
```ruby
|
|
95
89
|
require 'playwright'
|
|
96
90
|
|
|
97
|
-
Playwright.create(playwright_cli_executable_path: '
|
|
91
|
+
Playwright.create(playwright_cli_executable_path: './node_modules/.bin/playwright') do |playwright|
|
|
98
92
|
devices = playwright.android.devices
|
|
99
93
|
unless devices.empty?
|
|
100
94
|
device = devices.last
|
|
@@ -185,6 +179,8 @@ end
|
|
|
185
179
|
|
|
186
180
|
When `Playwright.connect_to_playwright_server` is used, playwright_cli_executable_path is not required.
|
|
187
181
|
|
|
182
|
+
For more detailed instraction, refer this article: https://playwright-ruby-client.vercel.app/docs/article/guides/playwright_on_alpine_linux
|
|
183
|
+
|
|
188
184
|
## License
|
|
189
185
|
|
|
190
186
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -32,27 +32,26 @@ Playwright will discard them as well for an easier to process tree, unless `inte
|
|
|
32
32
|
|
|
33
33
|
An example of dumping the entire accessibility tree:
|
|
34
34
|
|
|
35
|
-
```
|
|
36
|
-
snapshot = page.accessibility.snapshot
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
```ruby
|
|
36
|
+
snapshot = page.accessibility.snapshot
|
|
37
|
+
puts snapshot
|
|
39
38
|
```
|
|
40
39
|
|
|
41
40
|
An example of logging the focused node's name:
|
|
42
41
|
|
|
43
|
-
```
|
|
44
|
-
def find_focused_node(node)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
```ruby
|
|
43
|
+
def find_focused_node(node)
|
|
44
|
+
if node['focused']
|
|
45
|
+
node
|
|
46
|
+
else
|
|
47
|
+
node['children']&.find do |child|
|
|
48
|
+
find_focused_node(child)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
snapshot = page.accessibility.snapshot
|
|
53
54
|
node = find_focused_node(snapshot)
|
|
54
|
-
|
|
55
|
-
print(node["name"])
|
|
56
|
-
|
|
55
|
+
puts node['name']
|
|
57
56
|
```
|
|
58
57
|
|
|
@@ -81,6 +81,7 @@ def new_context(
|
|
|
81
81
|
colorScheme: nil,
|
|
82
82
|
deviceScaleFactor: nil,
|
|
83
83
|
extraHTTPHeaders: nil,
|
|
84
|
+
forcedColors: nil,
|
|
84
85
|
geolocation: nil,
|
|
85
86
|
hasTouch: nil,
|
|
86
87
|
httpCredentials: nil,
|
|
@@ -99,6 +100,7 @@ def new_context(
|
|
|
99
100
|
reducedMotion: nil,
|
|
100
101
|
screen: nil,
|
|
101
102
|
storageState: nil,
|
|
103
|
+
strictSelectors: nil,
|
|
102
104
|
timezoneId: nil,
|
|
103
105
|
userAgent: nil,
|
|
104
106
|
viewport: nil,
|
|
@@ -130,6 +132,7 @@ def new_page(
|
|
|
130
132
|
colorScheme: nil,
|
|
131
133
|
deviceScaleFactor: nil,
|
|
132
134
|
extraHTTPHeaders: nil,
|
|
135
|
+
forcedColors: nil,
|
|
133
136
|
geolocation: nil,
|
|
134
137
|
hasTouch: nil,
|
|
135
138
|
httpCredentials: nil,
|
|
@@ -148,6 +151,7 @@ def new_page(
|
|
|
148
151
|
reducedMotion: nil,
|
|
149
152
|
screen: nil,
|
|
150
153
|
storageState: nil,
|
|
154
|
+
strictSelectors: nil,
|
|
151
155
|
timezoneId: nil,
|
|
152
156
|
userAgent: nil,
|
|
153
157
|
viewport: nil,
|
|
@@ -265,12 +265,16 @@ Returns all open pages in the context.
|
|
|
265
265
|
## route
|
|
266
266
|
|
|
267
267
|
```
|
|
268
|
-
def route(url, handler)
|
|
268
|
+
def route(url, handler, times: nil)
|
|
269
269
|
```
|
|
270
270
|
|
|
271
271
|
Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
|
|
272
272
|
is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
|
|
273
273
|
|
|
274
|
+
> NOTE: [Page#route](./page#route) will not intercept requests intercepted by Service Worker. See
|
|
275
|
+
[this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using
|
|
276
|
+
request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);`
|
|
277
|
+
|
|
274
278
|
An example of a naive handler that aborts all image requests:
|
|
275
279
|
|
|
276
280
|
```ruby
|
|
@@ -114,6 +114,7 @@ def launch_persistent_context(
|
|
|
114
114
|
env: nil,
|
|
115
115
|
executablePath: nil,
|
|
116
116
|
extraHTTPHeaders: nil,
|
|
117
|
+
forcedColors: nil,
|
|
117
118
|
geolocation: nil,
|
|
118
119
|
handleSIGHUP: nil,
|
|
119
120
|
handleSIGINT: nil,
|
|
@@ -137,6 +138,7 @@ def launch_persistent_context(
|
|
|
137
138
|
reducedMotion: nil,
|
|
138
139
|
screen: nil,
|
|
139
140
|
slowMo: nil,
|
|
141
|
+
strictSelectors: nil,
|
|
140
142
|
timeout: nil,
|
|
141
143
|
timezoneId: nil,
|
|
142
144
|
tracesDir: nil,
|
|
@@ -510,6 +510,32 @@ def select_text(force: nil, timeout: nil)
|
|
|
510
510
|
This method waits for [actionability](https://playwright.dev/python/docs/actionability) checks, then focuses the element and selects all its text
|
|
511
511
|
content.
|
|
512
512
|
|
|
513
|
+
## set_checked
|
|
514
|
+
|
|
515
|
+
```
|
|
516
|
+
def set_checked(
|
|
517
|
+
checked,
|
|
518
|
+
force: nil,
|
|
519
|
+
noWaitAfter: nil,
|
|
520
|
+
position: nil,
|
|
521
|
+
timeout: nil,
|
|
522
|
+
trial: nil)
|
|
523
|
+
```
|
|
524
|
+
alias: `checked=`
|
|
525
|
+
|
|
526
|
+
This method checks or unchecks an element by performing the following steps:
|
|
527
|
+
1. Ensure that element is a checkbox or a radio input. If not, this method throws.
|
|
528
|
+
1. If the element already has the right checked state, this method returns immediately.
|
|
529
|
+
1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the matched element, unless `force` option is set. If the
|
|
530
|
+
element is detached during the checks, the whole action is retried.
|
|
531
|
+
1. Scroll the element into view if needed.
|
|
532
|
+
1. Use [Page#mouse](./page#mouse) to click in the center of the element.
|
|
533
|
+
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
|
|
534
|
+
1. Ensure that the element is now checked or unchecked. If not, this method throws.
|
|
535
|
+
|
|
536
|
+
When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing
|
|
537
|
+
zero timeout disables this.
|
|
538
|
+
|
|
513
539
|
## set_input_files
|
|
514
540
|
|
|
515
541
|
```
|
|
@@ -630,7 +656,7 @@ If the element does not satisfy the condition for the `timeout` milliseconds, th
|
|
|
630
656
|
## wait_for_selector
|
|
631
657
|
|
|
632
658
|
```
|
|
633
|
-
def wait_for_selector(selector, state: nil, timeout: nil)
|
|
659
|
+
def wait_for_selector(selector, state: nil, strict: nil, timeout: nil)
|
|
634
660
|
```
|
|
635
661
|
|
|
636
662
|
Returns element specified by selector when it satisfies `state` option. Returns `null` if waiting for `hidden` or
|
|
@@ -641,12 +667,11 @@ become visible/hidden). If at the moment of calling the method `selector` alread
|
|
|
641
667
|
will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the function will
|
|
642
668
|
throw.
|
|
643
669
|
|
|
644
|
-
```
|
|
645
|
-
page.
|
|
670
|
+
```ruby
|
|
671
|
+
page.content = "<div><span></span></div>"
|
|
646
672
|
div = page.query_selector("div")
|
|
647
673
|
# waiting for the "span" selector relative to the div.
|
|
648
|
-
span = div.wait_for_selector("span", state
|
|
649
|
-
|
|
674
|
+
span = div.wait_for_selector("span", state: "attached")
|
|
650
675
|
```
|
|
651
676
|
|
|
652
677
|
> NOTE: This method does not work across navigations, use [Page#wait_for_selector](./page#wait_for_selector) instead.
|
|
@@ -4,8 +4,21 @@ sidebar_position: 10
|
|
|
4
4
|
|
|
5
5
|
# Android
|
|
6
6
|
|
|
7
|
-
Playwright has **experimental** support for Android automation.
|
|
8
|
-
|
|
7
|
+
Playwright has **experimental** support for Android automation. This includes Chrome for Android and Android WebView.
|
|
8
|
+
|
|
9
|
+
*Requirements*
|
|
10
|
+
- Android device or AVD Emulator.
|
|
11
|
+
- [ADB daemon](https://developer.android.com/studio/command-line/adb) running and authenticated with your device.
|
|
12
|
+
Typically running `adb devices` is all you need to do.
|
|
13
|
+
- [`Chrome 87`](https://play.google.com/store/apps/details?id=com.android.chrome) or newer installed on the device
|
|
14
|
+
- "Enable command line on non-rooted devices" enabled in `chrome://flags`.
|
|
15
|
+
|
|
16
|
+
*Known limitations*
|
|
17
|
+
- Raw USB operation is not yet supported, so you need ADB.
|
|
18
|
+
- Device needs to be awake to produce screenshots. Enabling "Stay awake" developer mode will help.
|
|
19
|
+
- We didn't run all the tests against the device, so not everything works.
|
|
20
|
+
|
|
21
|
+
*How to run*
|
|
9
22
|
|
|
10
23
|
An example of the Android automation script would be:
|
|
11
24
|
|
|
@@ -34,6 +34,7 @@ def launch_browser(
|
|
|
34
34
|
command: nil,
|
|
35
35
|
deviceScaleFactor: nil,
|
|
36
36
|
extraHTTPHeaders: nil,
|
|
37
|
+
forcedColors: nil,
|
|
37
38
|
geolocation: nil,
|
|
38
39
|
hasTouch: nil,
|
|
39
40
|
httpCredentials: nil,
|
|
@@ -50,6 +51,7 @@ def launch_browser(
|
|
|
50
51
|
record_video_size: nil,
|
|
51
52
|
reducedMotion: nil,
|
|
52
53
|
screen: nil,
|
|
54
|
+
strictSelectors: nil,
|
|
53
55
|
timezoneId: nil,
|
|
54
56
|
userAgent: nil,
|
|
55
57
|
viewport: nil,
|
|
@@ -16,25 +16,16 @@ At every point of time, page exposes its current frame tree via the [Page#main_f
|
|
|
16
16
|
|
|
17
17
|
An example of dumping frame tree:
|
|
18
18
|
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
page.goto("https://www.theverge.com")
|
|
27
|
-
dump_frame_tree(page.main_frame, "")
|
|
28
|
-
browser.close()
|
|
29
|
-
|
|
30
|
-
def dump_frame_tree(frame, indent):
|
|
31
|
-
print(indent + frame.name + '@' + frame.url)
|
|
32
|
-
for child in frame.child_frames:
|
|
33
|
-
dump_frame_tree(child, indent + " ")
|
|
34
|
-
|
|
35
|
-
with sync_playwright() as playwright:
|
|
36
|
-
run(playwright)
|
|
19
|
+
```ruby
|
|
20
|
+
def dump_frame_tree(frame, indent = 0)
|
|
21
|
+
puts "#{' ' * indent}#{frame.name}@#{frame.url}"
|
|
22
|
+
frame.child_frames.each do |child|
|
|
23
|
+
dump_frame_tree(child, indent + 2)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
37
26
|
|
|
27
|
+
page.goto("https://www.theverge.com")
|
|
28
|
+
dump_frame_tree(page.main_frame)
|
|
38
29
|
```
|
|
39
30
|
|
|
40
31
|
|
|
@@ -176,9 +167,8 @@ The snippet below dispatches the `click` event on the element. Regardless of the
|
|
|
176
167
|
`click` is dispatched. This is equivalent to calling
|
|
177
168
|
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
|
|
178
169
|
|
|
179
|
-
```
|
|
170
|
+
```ruby
|
|
180
171
|
frame.dispatch_event("button#submit", "click")
|
|
181
|
-
|
|
182
172
|
```
|
|
183
173
|
|
|
184
174
|
Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
|
|
@@ -195,11 +185,10 @@ Since `eventInit` is event-specific, please refer to the events documentation fo
|
|
|
195
185
|
|
|
196
186
|
You can also specify [JSHandle](./js_handle) as the property value if you want live objects to be passed into the event:
|
|
197
187
|
|
|
198
|
-
```
|
|
188
|
+
```ruby
|
|
199
189
|
# note you can only create data_transfer in chromium and firefox
|
|
200
190
|
data_transfer = frame.evaluate_handle("new DataTransfer()")
|
|
201
|
-
frame.dispatch_event("#source", "dragstart", {
|
|
202
|
-
|
|
191
|
+
frame.dispatch_event("#source", "dragstart", eventInit: { dataTransfer: data_transfer })
|
|
203
192
|
```
|
|
204
193
|
|
|
205
194
|
|
|
@@ -238,11 +227,10 @@ return its value.
|
|
|
238
227
|
|
|
239
228
|
Examples:
|
|
240
229
|
|
|
241
|
-
```
|
|
230
|
+
```ruby
|
|
242
231
|
search_value = frame.eval_on_selector("#search", "el => el.value")
|
|
243
232
|
preload_href = frame.eval_on_selector("link[rel=preload]", "el => el.href")
|
|
244
|
-
html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello")
|
|
245
|
-
|
|
233
|
+
html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", arg: "hello")
|
|
246
234
|
```
|
|
247
235
|
|
|
248
236
|
|
|
@@ -263,9 +251,8 @@ return its value.
|
|
|
263
251
|
|
|
264
252
|
Examples:
|
|
265
253
|
|
|
266
|
-
```
|
|
267
|
-
divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
|
|
268
|
-
|
|
254
|
+
```ruby
|
|
255
|
+
divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", arg: 10)
|
|
269
256
|
```
|
|
270
257
|
|
|
271
258
|
|
|
@@ -285,28 +272,25 @@ If the function passed to the [Frame#evaluate](./frame#evaluate) returns a non-[
|
|
|
285
272
|
[Frame#evaluate](./frame#evaluate) returns `undefined`. Playwright also supports transferring some additional values that are
|
|
286
273
|
not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
|
|
287
274
|
|
|
288
|
-
```
|
|
289
|
-
result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
|
|
290
|
-
|
|
291
|
-
|
|
275
|
+
```ruby
|
|
276
|
+
result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", arg: [7, 8])
|
|
277
|
+
puts result # => "56"
|
|
292
278
|
```
|
|
293
279
|
|
|
294
280
|
A string can also be passed in instead of a function.
|
|
295
281
|
|
|
296
|
-
```
|
|
297
|
-
|
|
282
|
+
```ruby
|
|
283
|
+
puts frame.evaluate("1 + 2") # => 3
|
|
298
284
|
x = 10
|
|
299
|
-
|
|
300
|
-
|
|
285
|
+
puts frame.evaluate("1 + #{x}") # => "11"
|
|
301
286
|
```
|
|
302
287
|
|
|
303
288
|
[ElementHandle](./element_handle) instances can be passed as an argument to the [Frame#evaluate](./frame#evaluate):
|
|
304
289
|
|
|
305
|
-
```
|
|
290
|
+
```ruby
|
|
306
291
|
body_handle = frame.query_selector("body")
|
|
307
|
-
html = frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
|
|
308
|
-
body_handle.dispose
|
|
309
|
-
|
|
292
|
+
html = frame.evaluate("([body, suffix]) => body.innerHTML + suffix", arg: [body_handle, "hello"])
|
|
293
|
+
body_handle.dispose
|
|
310
294
|
```
|
|
311
295
|
|
|
312
296
|
|
|
@@ -325,10 +309,9 @@ The only difference between [Frame#evaluate](./frame#evaluate) and [Frame#evalua
|
|
|
325
309
|
If the function, passed to the [Frame#evaluate_handle](./frame#evaluate_handle), returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then
|
|
326
310
|
[Frame#evaluate_handle](./frame#evaluate_handle) would wait for the promise to resolve and return its value.
|
|
327
311
|
|
|
328
|
-
```
|
|
312
|
+
```ruby
|
|
329
313
|
a_window_handle = frame.evaluate_handle("Promise.resolve(window)")
|
|
330
314
|
a_window_handle # handle for the window object.
|
|
331
|
-
|
|
332
315
|
```
|
|
333
316
|
|
|
334
317
|
A string can also be passed in instead of a function.
|
|
@@ -393,11 +376,10 @@ frame.
|
|
|
393
376
|
|
|
394
377
|
This method throws an error if the frame has been detached before `frameElement()` returns.
|
|
395
378
|
|
|
396
|
-
```
|
|
397
|
-
frame_element = frame.frame_element
|
|
398
|
-
content_frame = frame_element.content_frame
|
|
399
|
-
|
|
400
|
-
|
|
379
|
+
```ruby
|
|
380
|
+
frame_element = frame.frame_element
|
|
381
|
+
content_frame = frame_element.content_frame
|
|
382
|
+
puts frame == content_frame # => true
|
|
401
383
|
```
|
|
402
384
|
|
|
403
385
|
|
|
@@ -419,18 +401,18 @@ def goto(url, referer: nil, timeout: nil, waitUntil: nil)
|
|
|
419
401
|
Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
|
|
420
402
|
last redirect.
|
|
421
403
|
|
|
422
|
-
|
|
404
|
+
The method will throw an error if:
|
|
423
405
|
- there's an SSL error (e.g. in case of self-signed certificates).
|
|
424
406
|
- target URL is invalid.
|
|
425
407
|
- the `timeout` is exceeded during navigation.
|
|
426
408
|
- the remote server does not respond or is unreachable.
|
|
427
409
|
- the main resource failed to load.
|
|
428
410
|
|
|
429
|
-
|
|
430
|
-
|
|
411
|
+
The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404 "Not
|
|
412
|
+
Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
|
|
431
413
|
[Response#status](./response#status).
|
|
432
414
|
|
|
433
|
-
> NOTE:
|
|
415
|
+
> NOTE: The method either throws an error or returns a main resource response. The only exceptions are navigation to
|
|
434
416
|
`about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
|
|
435
417
|
> NOTE: Headless mode doesn't support navigation to a PDF document. See the
|
|
436
418
|
[upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
|
|
@@ -551,8 +533,6 @@ The method returns an element locator that can be used to perform actions in the
|
|
|
551
533
|
element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
|
|
552
534
|
different DOM elements. That would happen if the DOM structure between those actions has changed.
|
|
553
535
|
|
|
554
|
-
Note that locator always implies visibility, so it will always be locating visible elements.
|
|
555
|
-
|
|
556
536
|
## name
|
|
557
537
|
|
|
558
538
|
```
|
|
@@ -658,17 +638,44 @@ Returns the array of option values that have been successfully selected.
|
|
|
658
638
|
|
|
659
639
|
Triggers a `change` and `input` event once all the provided options have been selected.
|
|
660
640
|
|
|
661
|
-
```
|
|
641
|
+
```ruby
|
|
662
642
|
# single selection matching the value
|
|
663
|
-
frame.select_option("select#colors", "blue")
|
|
643
|
+
frame.select_option("select#colors", value: "blue")
|
|
664
644
|
# single selection matching both the label
|
|
665
|
-
frame.select_option("select#colors", label
|
|
645
|
+
frame.select_option("select#colors", label: "blue")
|
|
666
646
|
# multiple selection
|
|
667
|
-
frame.select_option("select#colors", value
|
|
647
|
+
frame.select_option("select#colors", value: ["red", "green", "blue"])
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
## set_checked
|
|
668
653
|
|
|
669
654
|
```
|
|
655
|
+
def set_checked(
|
|
656
|
+
selector,
|
|
657
|
+
checked,
|
|
658
|
+
force: nil,
|
|
659
|
+
noWaitAfter: nil,
|
|
660
|
+
position: nil,
|
|
661
|
+
strict: nil,
|
|
662
|
+
timeout: nil,
|
|
663
|
+
trial: nil)
|
|
664
|
+
```
|
|
670
665
|
|
|
666
|
+
This method checks or unchecks an element matching `selector` by performing the following steps:
|
|
667
|
+
1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
|
|
668
|
+
1. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
|
|
669
|
+
1. If the element already has the right checked state, this method returns immediately.
|
|
670
|
+
1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the matched element, unless `force` option is set. If the
|
|
671
|
+
element is detached during the checks, the whole action is retried.
|
|
672
|
+
1. Scroll the element into view if needed.
|
|
673
|
+
1. Use [Page#mouse](./page#mouse) to click in the center of the element.
|
|
674
|
+
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
|
|
675
|
+
1. Ensure that the element is now checked or unchecked. If not, this method throws.
|
|
671
676
|
|
|
677
|
+
When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing
|
|
678
|
+
zero timeout disables this.
|
|
672
679
|
|
|
673
680
|
## set_content
|
|
674
681
|
|
|
@@ -756,10 +763,9 @@ send fine-grained keyboard events. To fill values in form fields, use [Frame#fil
|
|
|
756
763
|
|
|
757
764
|
To press a special key, like `Control` or `ArrowDown`, use [Keyboard#press](./keyboard#press).
|
|
758
765
|
|
|
759
|
-
```
|
|
766
|
+
```ruby
|
|
760
767
|
frame.type("#mytextarea", "hello") # types instantly
|
|
761
|
-
frame.type("#mytextarea", "world", delay
|
|
762
|
-
|
|
768
|
+
frame.type("#mytextarea", "world", delay: 100) # types slower, like a user
|
|
763
769
|
```
|
|
764
770
|
|
|
765
771
|
|
|
@@ -809,28 +815,16 @@ Returns when the `expression` returns a truthy value, returns that value.
|
|
|
809
815
|
|
|
810
816
|
The [Frame#wait_for_function](./frame#wait_for_function) can be used to observe viewport size change:
|
|
811
817
|
|
|
812
|
-
```
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
def run(playwright):
|
|
816
|
-
webkit = playwright.webkit
|
|
817
|
-
browser = webkit.launch()
|
|
818
|
-
page = browser.new_page()
|
|
819
|
-
page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
|
|
820
|
-
page.main_frame.wait_for_function("() => window.x > 0")
|
|
821
|
-
browser.close()
|
|
822
|
-
|
|
823
|
-
with sync_playwright() as playwright:
|
|
824
|
-
run(playwright)
|
|
825
|
-
|
|
818
|
+
```ruby
|
|
819
|
+
frame.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
|
|
820
|
+
frame.wait_for_function("() => window.x > 0")
|
|
826
821
|
```
|
|
827
822
|
|
|
828
823
|
To pass an argument to the predicate of `frame.waitForFunction` function:
|
|
829
824
|
|
|
830
|
-
```
|
|
825
|
+
```ruby
|
|
831
826
|
selector = ".foo"
|
|
832
|
-
frame.wait_for_function("selector => !!document.querySelector(selector)", selector)
|
|
833
|
-
|
|
827
|
+
frame.wait_for_function("selector => !!document.querySelector(selector)", arg: selector)
|
|
834
828
|
```
|
|
835
829
|
|
|
836
830
|
|
|
@@ -846,10 +840,9 @@ Waits for the required load state to be reached.
|
|
|
846
840
|
This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
|
|
847
841
|
when this method is called. If current document has already reached the required state, resolves immediately.
|
|
848
842
|
|
|
849
|
-
```
|
|
843
|
+
```ruby
|
|
850
844
|
frame.click("button") # click triggers navigation.
|
|
851
|
-
frame.wait_for_load_state
|
|
852
|
-
|
|
845
|
+
frame.wait_for_load_state # the promise resolves after "load" event.
|
|
853
846
|
```
|
|
854
847
|
|
|
855
848
|
|
|
@@ -867,11 +860,10 @@ History API usage, the navigation will resolve with `null`.
|
|
|
867
860
|
This method waits for the frame to navigate to a new URL. It is useful for when you run code which will indirectly cause
|
|
868
861
|
the frame to navigate. Consider this example:
|
|
869
862
|
|
|
870
|
-
```
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
# Resolves after navigation has finished
|
|
874
|
-
|
|
863
|
+
```ruby
|
|
864
|
+
frame.expect_navigation do
|
|
865
|
+
frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
|
|
866
|
+
end # Resolves after navigation has finished
|
|
875
867
|
```
|
|
876
868
|
|
|
877
869
|
> NOTE: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
|
|
@@ -892,22 +884,13 @@ selector doesn't satisfy the condition for the `timeout` milliseconds, the funct
|
|
|
892
884
|
|
|
893
885
|
This method works across navigations:
|
|
894
886
|
|
|
895
|
-
```
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
for current_url in ["https://google.com", "https://bbc.com"]:
|
|
903
|
-
page.goto(current_url, wait_until="domcontentloaded")
|
|
904
|
-
element = page.main_frame.wait_for_selector("img")
|
|
905
|
-
print("Loaded image: " + str(element.get_attribute("src")))
|
|
906
|
-
browser.close()
|
|
907
|
-
|
|
908
|
-
with sync_playwright() as playwright:
|
|
909
|
-
run(playwright)
|
|
910
|
-
|
|
887
|
+
```ruby
|
|
888
|
+
%w[https://google.com https://bbc.com].each do |current_url|
|
|
889
|
+
page.goto(current_url, waitUntil: "domcontentloaded")
|
|
890
|
+
frame = page.main_frame
|
|
891
|
+
element = frame.wait_for_selector("img")
|
|
892
|
+
puts "Loaded image: #{element["src"]}"
|
|
893
|
+
end
|
|
911
894
|
```
|
|
912
895
|
|
|
913
896
|
|
|
@@ -931,10 +914,9 @@ def wait_for_url(url, timeout: nil, waitUntil: nil)
|
|
|
931
914
|
|
|
932
915
|
Waits for the frame to navigate to the given URL.
|
|
933
916
|
|
|
934
|
-
```
|
|
917
|
+
```ruby
|
|
935
918
|
frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
|
|
936
919
|
frame.wait_for_url("**/target.html")
|
|
937
|
-
|
|
938
920
|
```
|
|
939
921
|
|
|
940
922
|
|