playwright-ruby-client 0.9.0 → 1.14.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/accessibility.md +51 -1
- data/documentation/docs/api/browser_context.md +28 -0
- data/documentation/docs/api/element_handle.md +4 -5
- data/documentation/docs/api/experimental/android.md +15 -2
- data/documentation/docs/api/frame.md +66 -97
- data/documentation/docs/api/locator.md +28 -41
- data/documentation/docs/api/mouse.md +3 -4
- data/documentation/docs/api/page.md +41 -1
- data/documentation/docs/api/request.md +15 -19
- data/documentation/docs/api/touchscreen.md +8 -0
- data/documentation/docs/api/tracing.md +13 -12
- data/documentation/docs/api/worker.md +46 -8
- 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/documentation/docs/include/api_coverage.md +13 -13
- data/lib/playwright/accessibility_impl.rb +50 -0
- data/lib/playwright/channel_owners/browser_context.rb +45 -0
- data/lib/playwright/channel_owners/frame.rb +9 -0
- data/lib/playwright/channel_owners/page.rb +31 -2
- data/lib/playwright/channel_owners/request.rb +8 -8
- data/lib/playwright/channel_owners/worker.rb +23 -0
- data/lib/playwright/locator_impl.rb +3 -3
- data/lib/playwright/touchscreen_impl.rb +7 -0
- data/lib/playwright/tracing_impl.rb +9 -8
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright_api/accessibility.rb +1 -1
- data/lib/playwright_api/android.rb +15 -2
- data/lib/playwright_api/browser_context.rb +8 -8
- data/lib/playwright_api/element_handle.rb +1 -1
- data/lib/playwright_api/frame.rb +5 -3
- data/lib/playwright_api/locator.rb +3 -3
- data/lib/playwright_api/page.rb +8 -6
- data/lib/playwright_api/touchscreen.rb +1 -1
- data/lib/playwright_api/worker.rb +13 -3
- metadata +4 -2
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
|
@@ -4,4 +4,54 @@ sidebar_position: 10
|
|
4
4
|
|
5
5
|
# Accessibility
|
6
6
|
|
7
|
-
|
7
|
+
The Accessibility class provides methods for inspecting Chromium's accessibility tree. The accessibility tree is used by
|
8
|
+
assistive technology such as [screen readers](https://en.wikipedia.org/wiki/Screen_reader) or
|
9
|
+
[switches](https://en.wikipedia.org/wiki/Switch_access).
|
10
|
+
|
11
|
+
Accessibility is a very platform-specific thing. On different platforms, there are different screen readers that might
|
12
|
+
have wildly different output.
|
13
|
+
|
14
|
+
Rendering engines of Chromium, Firefox and WebKit have a concept of "accessibility tree", which is then translated into
|
15
|
+
different platform-specific APIs. Accessibility namespace gives access to this Accessibility Tree.
|
16
|
+
|
17
|
+
Most of the accessibility tree gets filtered out when converting from internal browser AX Tree to Platform-specific
|
18
|
+
AX-Tree or by assistive technologies themselves. By default, Playwright tries to approximate this filtering, exposing
|
19
|
+
only the "interesting" nodes of the tree.
|
20
|
+
|
21
|
+
## snapshot
|
22
|
+
|
23
|
+
```
|
24
|
+
def snapshot(interestingOnly: nil, root: nil)
|
25
|
+
```
|
26
|
+
|
27
|
+
Captures the current state of the accessibility tree. The returned object represents the root accessible node of the
|
28
|
+
page.
|
29
|
+
|
30
|
+
> NOTE: The Chromium accessibility tree contains nodes that go unused on most platforms and by most screen readers.
|
31
|
+
Playwright will discard them as well for an easier to process tree, unless `interestingOnly` is set to `false`.
|
32
|
+
|
33
|
+
An example of dumping the entire accessibility tree:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
snapshot = page.accessibility.snapshot
|
37
|
+
puts snapshot
|
38
|
+
```
|
39
|
+
|
40
|
+
An example of logging the focused node's name:
|
41
|
+
|
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
|
54
|
+
node = find_focused_node(snapshot)
|
55
|
+
puts node['name']
|
56
|
+
```
|
57
|
+
|
@@ -67,6 +67,16 @@ browser_context.add_init_script(path: "preload.js")
|
|
67
67
|
> NOTE: The order of evaluation of multiple scripts installed via [BrowserContext#add_init_script](./browser_context#add_init_script) and
|
68
68
|
[Page#add_init_script](./page#add_init_script) is not defined.
|
69
69
|
|
70
|
+
## background_pages
|
71
|
+
|
72
|
+
```
|
73
|
+
def background_pages
|
74
|
+
```
|
75
|
+
|
76
|
+
> NOTE: Background pages are only supported on Chromium-based browsers.
|
77
|
+
|
78
|
+
All existing background pages in the context.
|
79
|
+
|
70
80
|
## browser
|
71
81
|
|
72
82
|
```
|
@@ -301,6 +311,16 @@ To remove a route with its handler you can use [BrowserContext#unroute](./browse
|
|
301
311
|
|
302
312
|
> NOTE: Enabling routing disables http cache.
|
303
313
|
|
314
|
+
## service_workers
|
315
|
+
|
316
|
+
```
|
317
|
+
def service_workers
|
318
|
+
```
|
319
|
+
|
320
|
+
> NOTE: Service workers are only supported on Chromium-based browsers.
|
321
|
+
|
322
|
+
All existing service workers in the context.
|
323
|
+
|
304
324
|
## set_default_navigation_timeout
|
305
325
|
|
306
326
|
```
|
@@ -369,6 +389,14 @@ alias: `offline=`
|
|
369
389
|
|
370
390
|
|
371
391
|
|
392
|
+
## storage_state
|
393
|
+
|
394
|
+
```
|
395
|
+
def storage_state(path: nil)
|
396
|
+
```
|
397
|
+
|
398
|
+
Returns storage state for this browser context, contains current cookies and local storage snapshot.
|
399
|
+
|
372
400
|
## unroute
|
373
401
|
|
374
402
|
```
|
@@ -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
|
-
```
|
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.
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
-
```
|
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
|
-
```
|
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
|
-
```
|
287
|
-
result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
|
288
|
-
|
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
|
-
```
|
295
|
-
|
282
|
+
```ruby
|
283
|
+
puts frame.evaluate("1 + 2") # => 3
|
296
284
|
x = 10
|
297
|
-
|
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
|
-
```
|
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
|
-
```
|
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
|
-
```
|
395
|
-
frame_element = frame.frame_element
|
396
|
-
content_frame = frame_element.content_frame
|
397
|
-
|
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
|
|
@@ -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
|
|
@@ -656,14 +640,13 @@ Returns the array of option values that have been successfully selected.
|
|
656
640
|
|
657
641
|
Triggers a `change` and `input` event once all the provided options have been selected.
|
658
642
|
|
659
|
-
```
|
643
|
+
```ruby
|
660
644
|
# single selection matching the value
|
661
|
-
frame.select_option("select#colors", "blue")
|
645
|
+
frame.select_option("select#colors", value: "blue")
|
662
646
|
# single selection matching both the label
|
663
|
-
frame.select_option("select#colors", label
|
647
|
+
frame.select_option("select#colors", label: "blue")
|
664
648
|
# multiple selection
|
665
|
-
frame.select_option("select#colors", value
|
666
|
-
|
649
|
+
frame.select_option("select#colors", value: ["red", "green", "blue"])
|
667
650
|
```
|
668
651
|
|
669
652
|
|
@@ -754,10 +737,9 @@ send fine-grained keyboard events. To fill values in form fields, use [Frame#fil
|
|
754
737
|
|
755
738
|
To press a special key, like `Control` or `ArrowDown`, use [Keyboard#press](./keyboard#press).
|
756
739
|
|
757
|
-
```
|
740
|
+
```ruby
|
758
741
|
frame.type("#mytextarea", "hello") # types instantly
|
759
|
-
frame.type("#mytextarea", "world", delay
|
760
|
-
|
742
|
+
frame.type("#mytextarea", "world", delay: 100) # types slower, like a user
|
761
743
|
```
|
762
744
|
|
763
745
|
|
@@ -807,28 +789,16 @@ Returns when the `expression` returns a truthy value, returns that value.
|
|
807
789
|
|
808
790
|
The [Frame#wait_for_function](./frame#wait_for_function) can be used to observe viewport size change:
|
809
791
|
|
810
|
-
```
|
811
|
-
|
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
|
-
|
792
|
+
```ruby
|
793
|
+
frame.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
|
794
|
+
frame.wait_for_function("() => window.x > 0")
|
824
795
|
```
|
825
796
|
|
826
797
|
To pass an argument to the predicate of `frame.waitForFunction` function:
|
827
798
|
|
828
|
-
```
|
799
|
+
```ruby
|
829
800
|
selector = ".foo"
|
830
|
-
frame.wait_for_function("selector => !!document.querySelector(selector)", selector)
|
831
|
-
|
801
|
+
frame.wait_for_function("selector => !!document.querySelector(selector)", arg: selector)
|
832
802
|
```
|
833
803
|
|
834
804
|
|
@@ -844,10 +814,9 @@ Waits for the required load state to be reached.
|
|
844
814
|
This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
|
845
815
|
when this method is called. If current document has already reached the required state, resolves immediately.
|
846
816
|
|
847
|
-
```
|
817
|
+
```ruby
|
848
818
|
frame.click("button") # click triggers navigation.
|
849
|
-
frame.wait_for_load_state
|
850
|
-
|
819
|
+
frame.wait_for_load_state # the promise resolves after "load" event.
|
851
820
|
```
|
852
821
|
|
853
822
|
|
@@ -865,11 +834,10 @@ History API usage, the navigation will resolve with `null`.
|
|
865
834
|
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
835
|
the frame to navigate. Consider this example:
|
867
836
|
|
868
|
-
```
|
869
|
-
|
870
|
-
|
871
|
-
# Resolves after navigation has finished
|
872
|
-
|
837
|
+
```ruby
|
838
|
+
frame.expect_navigation do
|
839
|
+
frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
|
840
|
+
end # Resolves after navigation has finished
|
873
841
|
```
|
874
842
|
|
875
843
|
> NOTE: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
|
@@ -890,25 +858,27 @@ selector doesn't satisfy the condition for the `timeout` milliseconds, the funct
|
|
890
858
|
|
891
859
|
This method works across navigations:
|
892
860
|
|
893
|
-
```
|
894
|
-
|
861
|
+
```ruby
|
862
|
+
%w[https://google.com https://bbc.com].each do |current_url|
|
863
|
+
page.goto(current_url, waitUntil: "domcontentloaded")
|
864
|
+
frame = page.main_frame
|
865
|
+
element = frame.wait_for_selector("img")
|
866
|
+
puts "Loaded image: #{element["src"]}"
|
867
|
+
end
|
868
|
+
```
|
869
|
+
|
895
870
|
|
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
871
|
|
906
|
-
|
907
|
-
run(playwright)
|
872
|
+
## wait_for_timeout
|
908
873
|
|
874
|
+
```
|
875
|
+
def wait_for_timeout(timeout)
|
909
876
|
```
|
910
877
|
|
878
|
+
Waits for the given `timeout` in milliseconds.
|
911
879
|
|
880
|
+
Note that `frame.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going to
|
881
|
+
be flaky. Use signals such as network events, selectors becoming visible and others instead.
|
912
882
|
|
913
883
|
## wait_for_url
|
914
884
|
|
@@ -918,10 +888,9 @@ def wait_for_url(url, timeout: nil, waitUntil: nil)
|
|
918
888
|
|
919
889
|
Waits for the frame to navigate to the given URL.
|
920
890
|
|
921
|
-
```
|
891
|
+
```ruby
|
922
892
|
frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
|
923
893
|
frame.wait_for_url("**/target.html")
|
924
|
-
|
925
894
|
```
|
926
895
|
|
927
896
|
|