playwright-ruby-client 1.14.beta3 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88c8fbe4451b00ed8eba172f656e0171fb2580d555eefb4d2aa0cc1a13f86fc4
4
- data.tar.gz: 3d307147cc4a23356d561f9528ef95343984bf4623ad77ebb6e479ce4f4f9462
3
+ metadata.gz: d6f164b2d4296ab3f30bfb22cd5fbec86ab522df916913ab19731dd452c55efa
4
+ data.tar.gz: 56371e88f29c8a7e7e398582a7cda693f45d8ebbb5bf6ce6e3fa0e748a2175bc
5
5
  SHA512:
6
- metadata.gz: 647702705f820c268e5b858a1cd587b0e8f32f16415df2fd7b91505a221cadc20400fc9f2db188964fe4759f4734c8b30bc15c265434d2ac2b78e0683228c192
7
- data.tar.gz: b4af0552e547d28be8c9390441bb7131d61fcea36fb5d3d293fd6985d6b47d3925e1c3bf27aa5f4e59243fc03ad751355acc20cb4e63b6e7489c47abb55b1864
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
- ```python sync title=example_3b0f6c6573db513b7b707a39d6c5bbf5ce5896b4785466d80f525968cfbd0be7.py
645
- page.set_content("<div><span></span></div>")
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="attached")
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
- ```python sync title=example_9f72eed0cd4b2405e6a115b812b36ff2624e889f9086925c47665333a7edabbc.py
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
- ```python sync title=example_4d635e937854fa2ee56b7c43151ded535940f0bbafc00cf48e8214bed86715eb.py
76
- box = element.bounding_box()
77
- page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)
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
- ```python sync title=example_8d92b900a98c237ffdcb102ddc35660e37101bde7d107dc64d97a7edeed62a43.py
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
- ```python sync title=example_e369442a3ff291ab476da408ef63a63dacf47984dc766ff7189d82008ae2848b.py
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("#source", "dragstart", {"dataTransfer": data_transfer})
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
- ```python sync title=example_df39b3df921f81e7cfb71cd873b76a5e91e46b4aa41e1f164128cb322aa38305.py
240
- tweets = page.locator(".tweet .retweets")
241
- assert tweets.evaluate("node => node.innerText") == "10 retweets"
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
- ```python sync title=example_32478e941514ed28b6ac221e6d54b55cf117038ecac6f4191db676480ab68d44.py
259
+ ```ruby
262
260
  elements = page.locator("div")
263
- div_counts = elements("(divs, min) => divs.length >= min", 10)
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
- ```python sync title=example_2825b0a50091868d1ce3ea0752d94ba32d826d504c1ac6842522796ca405913e.py
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="blue")
522
+ element.select_option(label: "blue")
526
523
  # multiple selection
527
- element.select_option(value=["red", "green", "blue"])
528
-
524
+ element.select_option(value: ["red", "green", "blue"])
529
525
  ```
530
526
 
531
- ```python sync title=example_3aaff4985dc38e64fad34696c88a6a68a633e26aabee6fc749125f3ee1784e34.py
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="blue", { index: 2 }, "red")
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
- ```python sync title=example_fa1712c0b6ceb96fcaa74790d33f2c2eefe2bd1f06e61b78e0bb84a6f22c7961.py
599
+ ```ruby
611
600
  element.type("hello") # types instantly
612
- element.type("world", delay=100) # types slower, like a user
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
- ```python sync title=example_adefe90dee78708d4375c20f081f12f2b71f2becb472a2e0d4fdc8cc49c37809.py
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
- ```py title=example_29716fdd4471a97923a64eebeee96330ab508226a496ae8fd13f12eb07d55ee6.py
12
- def handle_worker(worker):
13
- print("worker created: " + worker.url)
14
- worker.on("close", lambda: print("worker destroyed: " + worker.url))
15
-
16
- page.on('worker', handle_worker)
17
-
18
- print("current workers:")
19
- for worker in page.workers:
20
- print(" " + worker.url)
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
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- sidebar_position: 6
2
+ sidebar_position: 7
3
3
  ---
4
4
 
5
5
  # Playwright inspector
@@ -1,5 +1,5 @@
1
1
  ---
2
- sidebar_position: 7
2
+ sidebar_position: 8
3
3
  ---
4
4
 
5
5
  # Playwright on Alpine Linux
@@ -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
+ ![login screen is shown](https://user-images.githubusercontent.com/11763113/129394130-7a248f6a-56f0-40b0-a4dd-f0f65d71b3a9.png)
52
+
53
+ and input credentials manually:
54
+
55
+ ![input credentials manually](https://user-images.githubusercontent.com/11763113/129394155-fccc280e-5e6b-46c7-8a4d-a99d7db02c7f.png)
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
+ ![github_notification.png](https://user-images.githubusercontent.com/11763113/129394879-838797eb-135f-41ab-b965-8d6fabde6109.png)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '1.14.beta3'
4
+ VERSION = '1.14.0'
5
5
  COMPATIBLE_PLAYWRIGHT_VERSION = '1.14.0'
6
6
  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.14.beta3
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-12 00:00:00.000000000 Z
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: 1.3.1
377
+ version: '0'
377
378
  requirements: []
378
379
  rubygems_version: 3.2.22
379
380
  signing_key: