playwright-ruby-client 1.14.beta1 → 1.15.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/accessibility.md +16 -17
  3. data/documentation/docs/api/browser.md +2 -0
  4. data/documentation/docs/api/browser_type.md +1 -0
  5. data/documentation/docs/api/element_handle.md +4 -5
  6. data/documentation/docs/api/experimental/android.md +15 -2
  7. data/documentation/docs/api/experimental/android_device.md +1 -0
  8. data/documentation/docs/api/frame.md +62 -106
  9. data/documentation/docs/api/locator.md +41 -41
  10. data/documentation/docs/api/mouse.md +3 -4
  11. data/documentation/docs/api/page.md +6 -6
  12. data/documentation/docs/api/request.md +15 -19
  13. data/documentation/docs/api/selectors.md +29 -3
  14. data/documentation/docs/api/tracing.md +13 -12
  15. data/documentation/docs/api/worker.md +12 -11
  16. data/documentation/docs/article/guides/inspector.md +1 -1
  17. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +1 -1
  18. data/documentation/docs/article/guides/semi_automation.md +1 -1
  19. data/documentation/docs/article/guides/use_storage_state.md +78 -0
  20. data/lib/playwright.rb +44 -4
  21. data/lib/playwright/channel_owners/browser_type.rb +0 -1
  22. data/lib/playwright/channel_owners/frame.rb +5 -0
  23. data/lib/playwright/channel_owners/page.rb +4 -0
  24. data/lib/playwright/channel_owners/playwright.rb +9 -0
  25. data/lib/playwright/channel_owners/request.rb +8 -8
  26. data/lib/playwright/connection.rb +3 -8
  27. data/lib/playwright/locator_impl.rb +3 -3
  28. data/lib/playwright/tracing_impl.rb +9 -8
  29. data/lib/playwright/utils.rb +0 -1
  30. data/lib/playwright/version.rb +2 -2
  31. data/lib/playwright_api/android.rb +21 -8
  32. data/lib/playwright_api/android_device.rb +8 -7
  33. data/lib/playwright_api/browser.rb +10 -8
  34. data/lib/playwright_api/browser_context.rb +6 -6
  35. data/lib/playwright_api/browser_type.rb +8 -7
  36. data/lib/playwright_api/cdp_session.rb +6 -6
  37. data/lib/playwright_api/console_message.rb +6 -6
  38. data/lib/playwright_api/dialog.rb +6 -6
  39. data/lib/playwright_api/element_handle.rb +7 -7
  40. data/lib/playwright_api/frame.rb +14 -14
  41. data/lib/playwright_api/js_handle.rb +6 -6
  42. data/lib/playwright_api/locator.rb +16 -3
  43. data/lib/playwright_api/page.rb +13 -13
  44. data/lib/playwright_api/playwright.rb +6 -6
  45. data/lib/playwright_api/request.rb +6 -6
  46. data/lib/playwright_api/response.rb +6 -6
  47. data/lib/playwright_api/route.rb +6 -6
  48. data/lib/playwright_api/selectors.rb +38 -7
  49. data/lib/playwright_api/web_socket.rb +6 -6
  50. data/lib/playwright_api/worker.rb +6 -6
  51. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 301191e26a4aa496f59d5feb5bed3c8438d5de5dfaa3e769dea1dae12dfe091c
4
- data.tar.gz: 19fb694b3528977da5f934eff87432fff83a89072de874531fae3ab489f30e41
3
+ metadata.gz: ae7bd712526c9e50089204c128fc6aff20ff430e2f58d04faea66d429ab53357
4
+ data.tar.gz: 95cb87802b32b1ce4487f6bc7a0fe897c5cdf285cef09700dc9472b8caea46d1
5
5
  SHA512:
6
- metadata.gz: b0c3f28732256000b39c835cc6d38cd1f942c6e9defaa6e1aaf2f4269ba3e121422c0feebb76653ec323b64420bc24418b73ca1fc1fa98a7188e257f6e0ab359
7
- data.tar.gz: 1c7ba51eef58fe196bee1411fd9b3da95f3f1a66cf150ce69a614e51511aad081fb7a18b8befdcc9ce2f7ebacae82e8ecb90f0a099b01530d3b7897f22c12142
6
+ metadata.gz: b6854306d49f2bdf5a2f51bcfc639297043a52d9f0c38b3eb1b8db3931462cd98c42f0d45a35867352dccce25637efcc414b5c14edfe9d332c176d10a9fe9723
7
+ data.tar.gz: 4e1e89f99491cb4d2cc3ef1092b5a95fcd7486b2b19cd45dcc01d2d25ac5884c4ab6ba956172f41017561aee74013c2902ac787d0d5a1d6b71ef5eacf8740056
@@ -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
- ```python sync title=example_2e5019929403491cde0c78bed1e0e18e0c86ab423d7ac8715876c4de4814f483.py
36
- snapshot = page.accessibility.snapshot()
37
- print(snapshot)
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
- ```python sync title=example_df2acadf9e261a7624d83399f0d8b0910293a6a7081c812474715f22f8af7a4a.py
44
- def find_focused_node(node):
45
- if (node.get("focused"))
46
- return node
47
- for child in (node.get("children") or []):
48
- found_node = find_focused_node(child)
49
- return found_node
50
- return None
51
-
52
- snapshot = page.accessibility.snapshot()
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
- if node:
55
- print(node["name"])
56
-
55
+ puts node['name']
57
56
  ```
58
57
 
@@ -99,6 +99,7 @@ def new_context(
99
99
  reducedMotion: nil,
100
100
  screen: nil,
101
101
  storageState: nil,
102
+ strictSelectors: nil,
102
103
  timezoneId: nil,
103
104
  userAgent: nil,
104
105
  viewport: nil,
@@ -148,6 +149,7 @@ def new_page(
148
149
  reducedMotion: nil,
149
150
  screen: nil,
150
151
  storageState: nil,
152
+ strictSelectors: nil,
151
153
  timezoneId: nil,
152
154
  userAgent: nil,
153
155
  viewport: nil,
@@ -137,6 +137,7 @@ def launch_persistent_context(
137
137
  reducedMotion: nil,
138
138
  screen: nil,
139
139
  slowMo: nil,
140
+ strictSelectors: nil,
140
141
  timeout: nil,
141
142
  timezoneId: nil,
142
143
  tracesDir: nil,
@@ -331,7 +331,7 @@ Returns the `element.innerText`.
331
331
  def input_value(timeout: nil)
332
332
  ```
333
333
 
334
- Returns `input.value` for `<input>` or `<textarea>` element. Throws for non-input elements.
334
+ Returns `input.value` for `<input>` or `<textarea>` or `<select>` element. Throws for non-input elements.
335
335
 
336
336
  ## checked?
337
337
 
@@ -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.
@@ -4,8 +4,21 @@ sidebar_position: 10
4
4
 
5
5
  # Android
6
6
 
7
- Playwright has **experimental** support for Android automation. See [here](https://playwright.dev/python/docs/mobile) for more information. You can
8
- access android namespace via:
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
 
@@ -50,6 +50,7 @@ def launch_browser(
50
50
  record_video_size: nil,
51
51
  reducedMotion: nil,
52
52
  screen: nil,
53
+ strictSelectors: nil,
53
54
  timezoneId: nil,
54
55
  userAgent: nil,
55
56
  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
- ```python sync title=example_a4a9e01d1e0879958d591c4bc9061574f5c035e821a94214e650d15564d77bf4.py
20
- from playwright.sync_api import sync_playwright
21
-
22
- def run(playwright):
23
- firefox = playwright.firefox
24
- browser = firefox.launch()
25
- page = browser.new_page()
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
- ```python sync title=example_de439a4f4839a9b1bc72dbe0890d6b989c437620ba1b88a2150faa79f98184fc.py
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
- ```python sync title=example_5410f49339561b3cc9d91c7548c8195a570c8be704bb62f45d90c68f869d450d.py
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", { "dataTransfer": data_transfer })
202
-
191
+ frame.dispatch_event("#source", "dragstart", eventInit: { dataTransfer: data_transfer })
203
192
  ```
204
193
 
205
194
 
@@ -212,7 +201,9 @@ def drag_and_drop(
212
201
  target,
213
202
  force: nil,
214
203
  noWaitAfter: nil,
204
+ sourcePosition: nil,
215
205
  strict: nil,
206
+ targetPosition: nil,
216
207
  timeout: nil,
217
208
  trial: nil)
218
209
  ```
@@ -236,11 +227,10 @@ return its value.
236
227
 
237
228
  Examples:
238
229
 
239
- ```python sync title=example_6814d0e91763f4d27a0d6a380c36d62b551e4c3e902d1157012dde0a49122abe.py
230
+ ```ruby
240
231
  search_value = frame.eval_on_selector("#search", "el => el.value")
241
232
  preload_href = frame.eval_on_selector("link[rel=preload]", "el => el.href")
242
- html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello")
243
-
233
+ html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", arg: "hello")
244
234
  ```
245
235
 
246
236
 
@@ -261,9 +251,8 @@ return its value.
261
251
 
262
252
  Examples:
263
253
 
264
- ```python sync title=example_618e7f8f681d1c4a1c0c9b8d23892e37cbbef013bf3d8906fd4311c51d9819d7.py
265
- divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
266
-
254
+ ```ruby
255
+ divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", arg: 10)
267
256
  ```
268
257
 
269
258
 
@@ -283,28 +272,25 @@ If the function passed to the [Frame#evaluate](./frame#evaluate) returns a non-[
283
272
  [Frame#evaluate](./frame#evaluate) returns `undefined`. Playwright also supports transferring some additional values that are
284
273
  not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
285
274
 
286
- ```python sync title=example_15a235841cd1bc56fad6e3c8aaea2a30e352fedd8238017f22f97fc70e058d2b.py
287
- result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
288
- print(result) # prints "56"
289
-
275
+ ```ruby
276
+ result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", arg: [7, 8])
277
+ puts result # => "56"
290
278
  ```
291
279
 
292
280
  A string can also be passed in instead of a function.
293
281
 
294
- ```python sync title=example_9c73167b900498bca191abc2ce2627e063f84b0abc8ce3a117416cb734602760.py
295
- print(frame.evaluate("1 + 2")) # prints "3"
282
+ ```ruby
283
+ puts frame.evaluate("1 + 2") # => 3
296
284
  x = 10
297
- print(frame.evaluate(f"1 + {x}")) # prints "11"
298
-
285
+ puts frame.evaluate("1 + #{x}") # => "11"
299
286
  ```
300
287
 
301
288
  [ElementHandle](./element_handle) instances can be passed as an argument to the [Frame#evaluate](./frame#evaluate):
302
289
 
303
- ```python sync title=example_05568c81173717fa6841099571d8a66e14fc0853e01684630d1622baedc25f67.py
290
+ ```ruby
304
291
  body_handle = frame.query_selector("body")
305
- html = frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
306
- body_handle.dispose()
307
-
292
+ html = frame.evaluate("([body, suffix]) => body.innerHTML + suffix", arg: [body_handle, "hello"])
293
+ body_handle.dispose
308
294
  ```
309
295
 
310
296
 
@@ -323,10 +309,9 @@ The only difference between [Frame#evaluate](./frame#evaluate) and [Frame#evalua
323
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
324
310
  [Frame#evaluate_handle](./frame#evaluate_handle) would wait for the promise to resolve and return its value.
325
311
 
326
- ```python sync title=example_a1c8e837e826079359d01d6f7eecc64092a45d8c74280d23ee9039c379132c51.py
312
+ ```ruby
327
313
  a_window_handle = frame.evaluate_handle("Promise.resolve(window)")
328
314
  a_window_handle # handle for the window object.
329
-
330
315
  ```
331
316
 
332
317
  A string can also be passed in instead of a function.
@@ -391,11 +376,10 @@ frame.
391
376
 
392
377
  This method throws an error if the frame has been detached before `frameElement()` returns.
393
378
 
394
- ```python sync title=example_e6b4fdef29a401d84b17acfa319bee08f39e1f28e07c435463622220c6a24747.py
395
- frame_element = frame.frame_element()
396
- content_frame = frame_element.content_frame()
397
- assert frame == content_frame
398
-
379
+ ```ruby
380
+ frame_element = frame.frame_element
381
+ content_frame = frame_element.content_frame
382
+ puts frame == content_frame # => true
399
383
  ```
400
384
 
401
385
 
@@ -417,18 +401,18 @@ def goto(url, referer: nil, timeout: nil, waitUntil: nil)
417
401
  Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
418
402
  last redirect.
419
403
 
420
- `frame.goto` will throw an error if:
404
+ The method will throw an error if:
421
405
  - there's an SSL error (e.g. in case of self-signed certificates).
422
406
  - target URL is invalid.
423
407
  - the `timeout` is exceeded during navigation.
424
408
  - the remote server does not respond or is unreachable.
425
409
  - the main resource failed to load.
426
410
 
427
- `frame.goto` will not throw an error when any valid HTTP status code is returned by the remote server, including 404
428
- "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
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
429
413
  [Response#status](./response#status).
430
414
 
431
- > NOTE: `frame.goto` either throws an error or returns a main resource response. The only exceptions are navigation to
415
+ > NOTE: The method either throws an error or returns a main resource response. The only exceptions are navigation to
432
416
  `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
433
417
  > NOTE: Headless mode doesn't support navigation to a PDF document. See the
434
418
  [upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
@@ -479,7 +463,7 @@ Returns `element.innerText`.
479
463
  def input_value(selector, strict: nil, timeout: nil)
480
464
  ```
481
465
 
482
- Returns `input.value` for the selected `<input>` or `<textarea>` element. Throws for non-input elements.
466
+ Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element. Throws for non-input elements.
483
467
 
484
468
  ## checked?
485
469
 
@@ -549,8 +533,6 @@ The method returns an element locator that can be used to perform actions in the
549
533
  element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
550
534
  different DOM elements. That would happen if the DOM structure between those actions has changed.
551
535
 
552
- Note that locator always implies visibility, so it will always be locating visible elements.
553
-
554
536
  ## name
555
537
 
556
538
  ```
@@ -656,14 +638,13 @@ Returns the array of option values that have been successfully selected.
656
638
 
657
639
  Triggers a `change` and `input` event once all the provided options have been selected.
658
640
 
659
- ```python sync title=example_230c12044664b222bf35d6163b1e415c011d87d9911a4d39648c7f601b344a31.py
641
+ ```ruby
660
642
  # single selection matching the value
661
- frame.select_option("select#colors", "blue")
643
+ frame.select_option("select#colors", value: "blue")
662
644
  # single selection matching both the label
663
- frame.select_option("select#colors", label="blue")
645
+ frame.select_option("select#colors", label: "blue")
664
646
  # multiple selection
665
- frame.select_option("select#colors", value=["red", "green", "blue"])
666
-
647
+ frame.select_option("select#colors", value: ["red", "green", "blue"])
667
648
  ```
668
649
 
669
650
 
@@ -754,10 +735,9 @@ send fine-grained keyboard events. To fill values in form fields, use [Frame#fil
754
735
 
755
736
  To press a special key, like `Control` or `ArrowDown`, use [Keyboard#press](./keyboard#press).
756
737
 
757
- ```python sync title=example_beae7f0d11663c3c98b9d3a8e6ab76b762578cf2856e3b04ad8e42bfb23bb1e1.py
738
+ ```ruby
758
739
  frame.type("#mytextarea", "hello") # types instantly
759
- frame.type("#mytextarea", "world", delay=100) # types slower, like a user
760
-
740
+ frame.type("#mytextarea", "world", delay: 100) # types slower, like a user
761
741
  ```
762
742
 
763
743
 
@@ -807,28 +787,16 @@ Returns when the `expression` returns a truthy value, returns that value.
807
787
 
808
788
  The [Frame#wait_for_function](./frame#wait_for_function) can be used to observe viewport size change:
809
789
 
810
- ```python sync title=example_2f82dcf15fa9338be87a4faf7fe7de3c542040924db1e1ad1c98468ec0f425ce.py
811
- from playwright.sync_api import sync_playwright
812
-
813
- def run(playwright):
814
- webkit = playwright.webkit
815
- browser = webkit.launch()
816
- page = browser.new_page()
817
- page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
818
- page.main_frame.wait_for_function("() => window.x > 0")
819
- browser.close()
820
-
821
- with sync_playwright() as playwright:
822
- run(playwright)
823
-
790
+ ```ruby
791
+ frame.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
792
+ frame.wait_for_function("() => window.x > 0")
824
793
  ```
825
794
 
826
795
  To pass an argument to the predicate of `frame.waitForFunction` function:
827
796
 
828
- ```python sync title=example_8b95be0fb4d149890f7817d9473428a50dc631d3a75baf89846648ca6a157562.py
797
+ ```ruby
829
798
  selector = ".foo"
830
- frame.wait_for_function("selector => !!document.querySelector(selector)", selector)
831
-
799
+ frame.wait_for_function("selector => !!document.querySelector(selector)", arg: selector)
832
800
  ```
833
801
 
834
802
 
@@ -844,10 +812,9 @@ Waits for the required load state to be reached.
844
812
  This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
845
813
  when this method is called. If current document has already reached the required state, resolves immediately.
846
814
 
847
- ```python sync title=example_fe41b79b58d046cda4673ededd4d216cb97a63204fcba69375ce8a84ea3f6894.py
815
+ ```ruby
848
816
  frame.click("button") # click triggers navigation.
849
- frame.wait_for_load_state() # the promise resolves after "load" event.
850
-
817
+ frame.wait_for_load_state # the promise resolves after "load" event.
851
818
  ```
852
819
 
853
820
 
@@ -865,11 +832,10 @@ History API usage, the navigation will resolve with `null`.
865
832
  This method waits for the frame to navigate to a new URL. It is useful for when you run code which will indirectly cause
866
833
  the frame to navigate. Consider this example:
867
834
 
868
- ```python sync title=example_03f0ac17eb6c1ce8780cfa83c4ae15a9ddbfde3f96c96f36fdf3fbf9aac721f7.py
869
- with frame.expect_navigation():
870
- frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
871
- # Resolves after navigation has finished
872
-
835
+ ```ruby
836
+ frame.expect_navigation do
837
+ frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
838
+ end # Resolves after navigation has finished
873
839
  ```
874
840
 
875
841
  > NOTE: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
@@ -890,22 +856,13 @@ selector doesn't satisfy the condition for the `timeout` milliseconds, the funct
890
856
 
891
857
  This method works across navigations:
892
858
 
893
- ```python sync title=example_a5b9dd4745d45ac630e5953be1c1815ae8e8ab03399fb35f45ea77c434f17eea.py
894
- from playwright.sync_api import sync_playwright
895
-
896
- def run(playwright):
897
- chromium = playwright.chromium
898
- browser = chromium.launch()
899
- page = browser.new_page()
900
- for current_url in ["https://google.com", "https://bbc.com"]:
901
- page.goto(current_url, wait_until="domcontentloaded")
902
- element = page.main_frame.wait_for_selector("img")
903
- print("Loaded image: " + str(element.get_attribute("src")))
904
- browser.close()
905
-
906
- with sync_playwright() as playwright:
907
- run(playwright)
908
-
859
+ ```ruby
860
+ %w[https://google.com https://bbc.com].each do |current_url|
861
+ page.goto(current_url, waitUntil: "domcontentloaded")
862
+ frame = page.main_frame
863
+ element = frame.wait_for_selector("img")
864
+ puts "Loaded image: #{element["src"]}"
865
+ end
909
866
  ```
910
867
 
911
868
 
@@ -929,10 +886,9 @@ def wait_for_url(url, timeout: nil, waitUntil: nil)
929
886
 
930
887
  Waits for the frame to navigate to the given URL.
931
888
 
932
- ```python sync title=example_86a9a19ec4c41e1a5ac302fbca9a3d3d6dca3fe3314e065b8062ddf5f75abfbd.py
889
+ ```ruby
933
890
  frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
934
891
  frame.wait_for_url("**/target.html")
935
-
936
892
  ```
937
893
 
938
894