playwright-ruby-client 1.14.beta3 → 1.14.0
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/documentation/docs/api/element_handle.md +3 -4
- data/documentation/docs/api/locator.md +25 -38
- data/documentation/docs/api/worker.md +12 -11
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +1 -1
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/article/guides/use_storage_state.md +78 -0
- data/lib/playwright/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6f164b2d4296ab3f30bfb22cd5fbec86ab522df916913ab19731dd452c55efa
|
4
|
+
data.tar.gz: 56371e88f29c8a7e7e398582a7cda693f45d8ebbb5bf6ce6e3fa0e748a2175bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d97fd45d76a1cf4202be4aae7527974b01d8f90fd1de5e4fb4ed1267d3d3eeb601d5dddc49eb70559688c6bc816df82bc8c667e6aec7d2226ce078a2e0182a25
|
7
|
+
data.tar.gz: 602c97a88eb16aab95590391ae26f7ba777904668d4e270e3e24fe05122606d3f23d68901e529bb28b23a91458cdf7ce165de0c87621e0ad4ef9f8a711ccaf5f
|
@@ -641,12 +641,11 @@ become visible/hidden). If at the moment of calling the method `selector` alread
|
|
641
641
|
will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the function will
|
642
642
|
throw.
|
643
643
|
|
644
|
-
```
|
645
|
-
page.
|
644
|
+
```ruby
|
645
|
+
page.content = "<div><span></span></div>"
|
646
646
|
div = page.query_selector("div")
|
647
647
|
# waiting for the "span" selector relative to the div.
|
648
|
-
span = div.wait_for_selector("span", state
|
649
|
-
|
648
|
+
span = div.wait_for_selector("span", state: "attached")
|
650
649
|
```
|
651
650
|
|
652
651
|
> NOTE: This method does not work across navigations, use [Page#wait_for_selector](./page#wait_for_selector) instead.
|
@@ -7,10 +7,9 @@ sidebar_position: 10
|
|
7
7
|
Locator represents a view to the element(s) on the page. It captures the logic sufficient to retrieve the element at any
|
8
8
|
given moment. Locator can be created with the [Page#locator](./page#locator) method.
|
9
9
|
|
10
|
-
```
|
10
|
+
```ruby
|
11
11
|
locator = page.locator("text=Submit")
|
12
|
-
locator.click
|
13
|
-
|
12
|
+
locator.click
|
14
13
|
```
|
15
14
|
|
16
15
|
The difference between the Locator and [ElementHandle](./element_handle) is that the latter points to a particular element, while Locator
|
@@ -72,10 +71,12 @@ Elements from child frames return the bounding box relative to the main frame, u
|
|
72
71
|
Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the following
|
73
72
|
snippet should click the center of the element.
|
74
73
|
|
75
|
-
```
|
76
|
-
box = element.bounding_box
|
77
|
-
page.mouse.click(
|
78
|
-
|
74
|
+
```ruby
|
75
|
+
box = element.bounding_box
|
76
|
+
page.mouse.click(
|
77
|
+
box["x"] + box["width"] / 2,
|
78
|
+
box["y"] + box["height"] / 2,
|
79
|
+
)
|
79
80
|
```
|
80
81
|
|
81
82
|
|
@@ -177,9 +178,8 @@ The snippet below dispatches the `click` event on the element. Regardless of the
|
|
177
178
|
`click` is dispatched. This is equivalent to calling
|
178
179
|
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
|
179
180
|
|
180
|
-
```
|
181
|
+
```ruby
|
181
182
|
element.dispatch_event("click")
|
182
|
-
|
183
183
|
```
|
184
184
|
|
185
185
|
Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
|
@@ -196,11 +196,10 @@ Since `eventInit` is event-specific, please refer to the events documentation fo
|
|
196
196
|
|
197
197
|
You can also specify [JSHandle](./js_handle) as the property value if you want live objects to be passed into the event:
|
198
198
|
|
199
|
-
```
|
199
|
+
```ruby
|
200
200
|
# note you can only create data_transfer in chromium and firefox
|
201
201
|
data_transfer = page.evaluate_handle("new DataTransfer()")
|
202
|
-
element.dispatch_event("
|
203
|
-
|
202
|
+
element.dispatch_event("dragstart", eventInit: { dataTransfer: data_transfer })
|
204
203
|
```
|
205
204
|
|
206
205
|
|
@@ -236,10 +235,9 @@ If `expression` returns a [Promise](https://developer.mozilla.org/en-US/docs/Web
|
|
236
235
|
|
237
236
|
Examples:
|
238
237
|
|
239
|
-
```
|
240
|
-
|
241
|
-
|
242
|
-
|
238
|
+
```ruby
|
239
|
+
tweet = page.query_selector(".tweet .retweets")
|
240
|
+
tweet.evaluate("node => node.innerText") # => "10 retweets"
|
243
241
|
```
|
244
242
|
|
245
243
|
|
@@ -258,10 +256,9 @@ return its value.
|
|
258
256
|
|
259
257
|
Examples:
|
260
258
|
|
261
|
-
```
|
259
|
+
```ruby
|
262
260
|
elements = page.locator("div")
|
263
|
-
|
264
|
-
|
261
|
+
elements.evaluate_all("(divs, min) => divs.length >= min", arg: 10)
|
265
262
|
```
|
266
263
|
|
267
264
|
|
@@ -518,26 +515,18 @@ Returns the array of option values that have been successfully selected.
|
|
518
515
|
|
519
516
|
Triggers a `change` and `input` event once all the provided options have been selected.
|
520
517
|
|
521
|
-
```
|
518
|
+
```ruby
|
522
519
|
# single selection matching the value
|
523
|
-
element.select_option("blue")
|
520
|
+
element.select_option(value: "blue")
|
524
521
|
# single selection matching both the label
|
525
|
-
element.select_option(label
|
522
|
+
element.select_option(label: "blue")
|
526
523
|
# multiple selection
|
527
|
-
element.select_option(value
|
528
|
-
|
524
|
+
element.select_option(value: ["red", "green", "blue"])
|
529
525
|
```
|
530
526
|
|
531
|
-
```
|
532
|
-
# single selection matching the value
|
533
|
-
element.select_option("blue")
|
534
|
-
# single selection matching both the value and the label
|
535
|
-
element.select_option(label="blue")
|
536
|
-
# multiple selection
|
537
|
-
element.select_option("red", "green", "blue")
|
527
|
+
```ruby
|
538
528
|
# multiple selection for blue, red and second option
|
539
|
-
element.select_option(value
|
540
|
-
|
529
|
+
element.select_option(value: "blue", index: 2, label: "red")
|
541
530
|
```
|
542
531
|
|
543
532
|
|
@@ -607,19 +596,17 @@ Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup`
|
|
607
596
|
|
608
597
|
To press a special key, like `Control` or `ArrowDown`, use [Locator#press](./locator#press).
|
609
598
|
|
610
|
-
```
|
599
|
+
```ruby
|
611
600
|
element.type("hello") # types instantly
|
612
|
-
element.type("world", delay
|
613
|
-
|
601
|
+
element.type("world", delay: 100) # types slower, like a user
|
614
602
|
```
|
615
603
|
|
616
604
|
An example of typing into a text field and then submitting the form:
|
617
605
|
|
618
|
-
```
|
606
|
+
```ruby
|
619
607
|
element = page.locator("input")
|
620
608
|
element.type("some text")
|
621
609
|
element.press("Enter")
|
622
|
-
|
623
610
|
```
|
624
611
|
|
625
612
|
|
@@ -8,17 +8,18 @@ The Worker class represents a [WebWorker](https://developer.mozilla.org/en-US/do
|
|
8
8
|
event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker object when the
|
9
9
|
worker is gone.
|
10
10
|
|
11
|
-
```
|
12
|
-
def handle_worker(worker)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
```ruby
|
12
|
+
def handle_worker(worker)
|
13
|
+
puts "worker created: #{worker.url}"
|
14
|
+
worker.once("close", -> (w) { puts "worker destroyed: #{w.url}" })
|
15
|
+
end
|
16
|
+
|
17
|
+
page.on('worker', method(:handle_worker))
|
18
|
+
|
19
|
+
puts "current workers:"
|
20
|
+
page.workers.each do |worker|
|
21
|
+
puts " #{worker.url}"
|
22
|
+
end
|
22
23
|
```
|
23
24
|
|
24
25
|
|
@@ -10,7 +10,7 @@ This allow us to intermediate into automation, for example
|
|
10
10
|
* Authenticate with OAuth2 manually before automation
|
11
11
|
* Testing a page after some chrome extensions are installed manually
|
12
12
|
|
13
|
-
Keep in mind repeatedly that persistent browser context is NOT RECOMMENDED for most cases because it would bring many side effects.
|
13
|
+
Keep in mind repeatedly that persistent browser context is NOT RECOMMENDED for most cases because it would bring many side effects. Consider [reusing cookie and local storage](./use_storage_state) when you just want to keep authenticated across browser contexts.
|
14
14
|
|
15
15
|
## Pause automation for manual operation
|
16
16
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
---
|
2
|
+
sidebar_position: 6
|
3
|
+
---
|
4
|
+
|
5
|
+
# Reuse Cookie and LocalStorage
|
6
|
+
|
7
|
+
In most cases, authentication state is stored in cookie or local storage. When we just want to keep authenticated, it is a good solution to dump/load 'storage state' (= Cookie + LocalStorage).
|
8
|
+
https://playwright.dev/docs/next/auth#reuse-authentication-state
|
9
|
+
|
10
|
+
* Dump storage state using [BrowserContext#storage_state](/docs/api/browser_context#storage_state) with `path: /path/to/state.json`
|
11
|
+
* Load storage state by specifying the parameter `storageState: /path/to/state.json` into [Browser#new_context](/docs/api/browser#new_context) or [Browser#new_page](/docs/api/browser#new_page)
|
12
|
+
|
13
|
+
## Example
|
14
|
+
|
15
|
+
Generally in browser automation, it is very difficult to bypass 2FA or reCAPTCHA in login screen. In such cases, we would consider
|
16
|
+
|
17
|
+
* Authenticate manually by hand
|
18
|
+
* Resume automation with the authentication result
|
19
|
+
|
20
|
+
|
21
|
+
```ruby {16,21}
|
22
|
+
require 'playwright'
|
23
|
+
require 'pry'
|
24
|
+
|
25
|
+
force_login = !File.exist?('github_state.json')
|
26
|
+
|
27
|
+
Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwright|
|
28
|
+
if force_login
|
29
|
+
# Use headful mode for manual operation.
|
30
|
+
playwright.chromium.launch(headless: false, channel: 'chrome') do |browser|
|
31
|
+
page = browser.new_page
|
32
|
+
page.goto('https://github.com/login')
|
33
|
+
|
34
|
+
# Login manually.
|
35
|
+
binding.pry
|
36
|
+
|
37
|
+
page.context.storage_state(path: 'github_state.json')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
playwright.chromium.launch do |browser|
|
42
|
+
page = browser.new_page(storageState: 'github_state.json')
|
43
|
+
page.goto('https://github.com/notifications')
|
44
|
+
page.screenshot(path: 'github_notification.png')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
When we execute this script at the first time (without github_state.json), login screen is shown:
|
50
|
+
|
51
|
+

|
52
|
+
|
53
|
+
and input credentials manually:
|
54
|
+
|
55
|
+

|
56
|
+
|
57
|
+
and hit `exit` in Pry console.
|
58
|
+
|
59
|
+
```
|
60
|
+
|
61
|
+
9:
|
62
|
+
10: # Login manually. Hit `exit` in Pry console after authenticated.
|
63
|
+
11: require 'pry'
|
64
|
+
12: binding.pry
|
65
|
+
13:
|
66
|
+
=> 14: page.context.storage_state(path: 'github_state.json')
|
67
|
+
15: end if force_login
|
68
|
+
16:
|
69
|
+
17: playwright.chromium.launch do |browser|
|
70
|
+
18: page = browser.new_page(storageState: 'github_state.json')
|
71
|
+
19: page.goto('https://github.com/notifications')
|
72
|
+
|
73
|
+
[1] pry(main)> exit
|
74
|
+
```
|
75
|
+
|
76
|
+
then we can enjoy automation with keeping authenticated. Login screen is never shown until github_state.json is deleted :)
|
77
|
+
|
78
|
+

|
data/lib/playwright/version.rb
CHANGED
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.14.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-08-
|
11
|
+
date: 2021-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -250,6 +250,7 @@ files:
|
|
250
250
|
- documentation/docs/article/guides/rails_integration.md
|
251
251
|
- documentation/docs/article/guides/recording_video.md
|
252
252
|
- documentation/docs/article/guides/semi_automation.md
|
253
|
+
- documentation/docs/article/guides/use_storage_state.md
|
253
254
|
- documentation/docs/include/api_coverage.md
|
254
255
|
- documentation/docusaurus.config.js
|
255
256
|
- documentation/package.json
|
@@ -371,9 +372,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
371
372
|
version: '2.4'
|
372
373
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
373
374
|
requirements:
|
374
|
-
- - "
|
375
|
+
- - ">="
|
375
376
|
- !ruby/object:Gem::Version
|
376
|
-
version:
|
377
|
+
version: '0'
|
377
378
|
requirements: []
|
378
379
|
rubygems_version: 3.2.22
|
379
380
|
signing_key:
|