playwright-ruby-client 1.26.0 → 1.28.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/api_request_context.md +86 -0
  3. data/documentation/docs/api/browser_context.md +3 -3
  4. data/documentation/docs/api/download.md +1 -1
  5. data/documentation/docs/api/element_handle.md +2 -1
  6. data/documentation/docs/api/file_chooser.md +1 -1
  7. data/documentation/docs/api/frame.md +151 -4
  8. data/documentation/docs/api/frame_locator.md +151 -4
  9. data/documentation/docs/api/js_handle.md +5 -3
  10. data/documentation/docs/api/keyboard.md +1 -1
  11. data/documentation/docs/api/locator.md +191 -6
  12. data/documentation/docs/api/page.md +166 -9
  13. data/documentation/docs/api/request.md +1 -1
  14. data/documentation/docs/api/tracing.md +1 -1
  15. data/documentation/docs/article/guides/rails_integration.md +1 -0
  16. data/documentation/docs/article/guides/rails_integration_with_null_driver.md +59 -0
  17. data/documentation/docs/include/api_coverage.md +32 -0
  18. data/lib/playwright/channel_owner.rb +41 -0
  19. data/lib/playwright/channel_owners/browser_context.rb +6 -0
  20. data/lib/playwright/channel_owners/element_handle.rb +8 -1
  21. data/lib/playwright/channel_owners/frame.rb +6 -0
  22. data/lib/playwright/channel_owners/page.rb +25 -28
  23. data/lib/playwright/channel_owners/selectors.rb +4 -0
  24. data/lib/playwright/connection.rb +4 -1
  25. data/lib/playwright/frame_locator_impl.rb +6 -2
  26. data/lib/playwright/locator_impl.rb +21 -31
  27. data/lib/playwright/locator_utils.rb +136 -0
  28. data/lib/playwright/utils.rb +6 -0
  29. data/lib/playwright/version.rb +2 -2
  30. data/lib/playwright_api/android.rb +12 -6
  31. data/lib/playwright_api/android_device.rb +6 -6
  32. data/lib/playwright_api/api_request_context.rb +86 -8
  33. data/lib/playwright_api/browser.rb +6 -6
  34. data/lib/playwright_api/browser_context.rb +9 -9
  35. data/lib/playwright_api/browser_type.rb +6 -6
  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/download.rb +1 -1
  40. data/lib/playwright_api/element_handle.rb +9 -8
  41. data/lib/playwright_api/file_chooser.rb +1 -1
  42. data/lib/playwright_api/frame.rb +119 -11
  43. data/lib/playwright_api/frame_locator.rb +113 -5
  44. data/lib/playwright_api/js_handle.rb +7 -7
  45. data/lib/playwright_api/keyboard.rb +1 -1
  46. data/lib/playwright_api/locator.rb +145 -6
  47. data/lib/playwright_api/page.rb +133 -16
  48. data/lib/playwright_api/playwright.rb +6 -6
  49. data/lib/playwright_api/request.rb +9 -9
  50. data/lib/playwright_api/response.rb +8 -8
  51. data/lib/playwright_api/route.rb +6 -6
  52. data/lib/playwright_api/selectors.rb +14 -3
  53. data/lib/playwright_api/tracing.rb +7 -7
  54. data/lib/playwright_api/web_socket.rb +6 -6
  55. data/lib/playwright_api/worker.rb +8 -8
  56. metadata +5 -4
@@ -4,7 +4,7 @@ module Playwright
4
4
  # [`method: Locator.frameLocator`] method.
5
5
  #
6
6
  # ```python sync
7
- # locator = page.frame_locator("my-frame").locator("text=Submit")
7
+ # locator = page.frame_locator("my-frame").get_by_text("Submit")
8
8
  # locator.click()
9
9
  # ```
10
10
  #
@@ -15,10 +15,10 @@ module Playwright
15
15
  #
16
16
  # ```python sync
17
17
  # # Throws if there are several frames in DOM:
18
- # page.frame_locator('.result-frame').locator('button').click()
18
+ # page.frame_locator('.result-frame').get_by_role('button').click()
19
19
  #
20
20
  # # Works because we explicitly tell locator to pick the first frame:
21
- # page.frame_locator('.result-frame').first.locator('button').click()
21
+ # page.frame_locator('.result-frame').first.get_by_role('button').click()
22
22
  # ```
23
23
  #
24
24
  # **Converting Locator to FrameLocator**
@@ -27,7 +27,7 @@ module Playwright
27
27
  # [`:scope`](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) CSS selector:
28
28
  #
29
29
  # ```python sync
30
- # frameLocator = locator.frame_locator(":scope");
30
+ # frameLocator = locator.frame_locator(":scope")
31
31
  # ```
32
32
  class FrameLocator < PlaywrightApi
33
33
 
@@ -42,12 +42,120 @@ module Playwright
42
42
  wrap_impl(@impl.frame_locator(unwrap_impl(selector)))
43
43
  end
44
44
 
45
+ # Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
46
+ #
47
+ # ```html
48
+ # <img alt='Castle'>
49
+ # ```
50
+ def get_by_alt_text(text, exact: nil)
51
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
52
+ end
53
+
54
+ # Allows locating input elements by the text of the associated label. For example, this method will find the input by
55
+ # label text "Password" in the following DOM:
56
+ #
57
+ # ```html
58
+ # <label for="password-input">Password:</label>
59
+ # <input id="password-input">
60
+ # ```
61
+ def get_by_label(text, exact: nil)
62
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
63
+ end
64
+
65
+ # Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
66
+ # "Country":
67
+ #
68
+ # ```html
69
+ # <input placeholder="Country">
70
+ # ```
71
+ def get_by_placeholder(text, exact: nil)
72
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
73
+ end
74
+
75
+ # Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles),
76
+ # [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and
77
+ # [accessible name](https://w3c.github.io/accname/#dfn-accessible-name). Note that role selector **does not replace**
78
+ # accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
79
+ #
80
+ # Note that many html elements have an implicitly
81
+ # [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings) that is recognized by the role selector. You
82
+ # can find all the [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not
83
+ # recommend** duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
84
+ def get_by_role(
85
+ role,
86
+ checked: nil,
87
+ disabled: nil,
88
+ exact: nil,
89
+ expanded: nil,
90
+ includeHidden: nil,
91
+ level: nil,
92
+ name: nil,
93
+ pressed: nil,
94
+ selected: nil)
95
+ wrap_impl(@impl.get_by_role(unwrap_impl(role), checked: unwrap_impl(checked), disabled: unwrap_impl(disabled), exact: unwrap_impl(exact), expanded: unwrap_impl(expanded), includeHidden: unwrap_impl(includeHidden), level: unwrap_impl(level), name: unwrap_impl(name), pressed: unwrap_impl(pressed), selected: unwrap_impl(selected)))
96
+ end
97
+
98
+ # Locate element by the test id. By default, the `data-testid` attribute is used as a test id. Use
99
+ # [`method: Selectors.setTestIdAttribute`] to configure a different test id attribute if necessary.
100
+ def get_by_test_id(testId)
101
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
102
+ end
103
+
104
+ # Allows locating elements that contain given text. Consider the following DOM structure:
105
+ #
106
+ # ```html
107
+ # <div>Hello <span>world</span></div>
108
+ # <div>Hello</div>
109
+ # ```
110
+ #
111
+ # You can locate by text substring, exact string, or a regular expression:
112
+ #
113
+ # ```python sync
114
+ # # Matches <span>
115
+ # page.get_by_text("world")
116
+ #
117
+ # # Matches first <div>
118
+ # page.get_by_text("Hello world")
119
+ #
120
+ # # Matches second <div>
121
+ # page.get_by_text("Hello", exact=True)
122
+ #
123
+ # # Matches both <div>s
124
+ # page.get_by_text(re.compile("Hello"))
125
+ #
126
+ # # Matches second <div>
127
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
128
+ # ```
129
+ #
130
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter
131
+ # by the text content.
132
+ #
133
+ # > NOTE: Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
134
+ # one, turns line breaks into spaces and ignores leading and trailing whitespace.
135
+ # > NOTE: Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
136
+ # example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
137
+ def get_by_text(text, exact: nil)
138
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
139
+ end
140
+
141
+ # Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
142
+ #
143
+ # ```html
144
+ # <button title='Place the order'>Order Now</button>
145
+ # ```
146
+ def get_by_title(text, exact: nil)
147
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
148
+ end
149
+
45
150
  # Returns locator to the last matching frame.
46
151
  def last
47
152
  wrap_impl(@impl.last)
48
153
  end
49
154
 
50
- # The method finds an element matching the specified selector in the FrameLocator's subtree.
155
+ # The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options,
156
+ # similar to [`method: Locator.filter`] method.
157
+ #
158
+ # [Learn more about locators](../locators.md).
51
159
  def locator(selector, has: nil, hasText: nil)
52
160
  wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
53
161
  end
@@ -59,7 +59,7 @@ module Playwright
59
59
  # The method returns a map with **own property names** as keys and JSHandle instances for the property values.
60
60
  #
61
61
  # ```python sync
62
- # handle = page.evaluate_handle("{window, document}")
62
+ # handle = page.evaluate_handle("({window, document})")
63
63
  # properties = handle.get_properties()
64
64
  # window_handle = properties.get("window")
65
65
  # document_handle = properties.get("document")
@@ -88,12 +88,6 @@ module Playwright
88
88
  wrap_impl(@impl.to_s)
89
89
  end
90
90
 
91
- # -- inherited from EventEmitter --
92
- # @nodoc
93
- def off(event, callback)
94
- event_emitter_proxy.off(event, callback)
95
- end
96
-
97
91
  # -- inherited from EventEmitter --
98
92
  # @nodoc
99
93
  def once(event, callback)
@@ -106,6 +100,12 @@ module Playwright
106
100
  event_emitter_proxy.on(event, callback)
107
101
  end
108
102
 
103
+ # -- inherited from EventEmitter --
104
+ # @nodoc
105
+ def off(event, callback)
106
+ event_emitter_proxy.off(event, callback)
107
+ end
108
+
109
109
  private def event_emitter_proxy
110
110
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
111
111
  end
@@ -1,6 +1,6 @@
1
1
  module Playwright
2
2
  # Keyboard provides an api for managing a virtual keyboard. The high level api is [`method: Keyboard.type`], which takes
3
- # raw characters and generates proper keydown, keypress/input, and keyup events on your page.
3
+ # raw characters and generates proper `keydown`, `keypress`/`input`, and `keyup` events on your page.
4
4
  #
5
5
  # For finer control, you can use [`method: Keyboard.down`], [`method: Keyboard.up`], and [`method: Keyboard.insertText`]
6
6
  # to manually fire events as if they were generated from a real keyboard.
@@ -15,6 +15,11 @@ module Playwright
15
15
  wrap_impl(@impl.all_text_contents)
16
16
  end
17
17
 
18
+ # Calls [blur](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur) on the element.
19
+ def blur(timeout: nil)
20
+ wrap_impl(@impl.blur(timeout: unwrap_impl(timeout)))
21
+ end
22
+
18
23
  # This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is
19
24
  # calculated relative to the main frame viewport - which is usually the same as the browser window.
20
25
  #
@@ -58,6 +63,17 @@ module Playwright
58
63
  wrap_impl(@impl.check(force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
59
64
  end
60
65
 
66
+ # This method waits for [actionability](../actionability.md) checks, focuses the element, clears it and triggers an
67
+ # `input` event after clearing.
68
+ #
69
+ # If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an error.
70
+ # However, if the element is inside the `<label>` element that has an associated
71
+ # [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), the control will be cleared
72
+ # instead.
73
+ def clear(force: nil, noWaitAfter: nil, timeout: nil)
74
+ wrap_impl(@impl.clear(force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
75
+ end
76
+
61
77
  # This method clicks the element by performing the following steps:
62
78
  # 1. Wait for [actionability](../actionability.md) checks on the element, unless `force` option is set.
63
79
  # 1. Scroll the element into view if needed.
@@ -142,6 +158,21 @@ module Playwright
142
158
  wrap_impl(@impl.dispatch_event(unwrap_impl(type), eventInit: unwrap_impl(eventInit), timeout: unwrap_impl(timeout)))
143
159
  end
144
160
 
161
+ # This method drags the locator to another target locator or target position. It will first move to the source element,
162
+ # perform a `mousedown`, then move to the target element or position and perform a `mouseup`.
163
+ #
164
+ # ```python sync
165
+ # source = page.locator("#source")
166
+ # target = page.locator("#target")
167
+ #
168
+ # source.drag_to(target)
169
+ # # or specify exact positions relative to the top-left corners of the elements:
170
+ # source.drag_to(
171
+ # target,
172
+ # source_position={"x": 34, "y": 7},
173
+ # target_position={"x": 10, "y": 20}
174
+ # )
175
+ # ```
145
176
  def drag_to(
146
177
  target,
147
178
  force: nil,
@@ -232,7 +263,7 @@ module Playwright
232
263
  # # ...
233
264
  # row_locator
234
265
  # .filter(has_text="text in column 1")
235
- # .filter(has=page.locator("tr", has_text="column 2 button"))
266
+ # .filter(has=page.get_by_role("button", name="column 2 button"))
236
267
  # .screenshot()
237
268
  # ```
238
269
  def filter(has: nil, hasText: nil)
@@ -253,7 +284,7 @@ module Playwright
253
284
  # that iframe:
254
285
  #
255
286
  # ```python sync
256
- # locator = page.frame_locator("iframe").locator("text=Submit")
287
+ # locator = page.frame_locator("iframe").get_by_text("Submit")
257
288
  # locator.click()
258
289
  # ```
259
290
  def frame_locator(selector)
@@ -266,6 +297,111 @@ module Playwright
266
297
  end
267
298
  alias_method :[], :get_attribute
268
299
 
300
+ # Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
301
+ #
302
+ # ```html
303
+ # <img alt='Castle'>
304
+ # ```
305
+ def get_by_alt_text(text, exact: nil)
306
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
307
+ end
308
+
309
+ # Allows locating input elements by the text of the associated label. For example, this method will find the input by
310
+ # label text "Password" in the following DOM:
311
+ #
312
+ # ```html
313
+ # <label for="password-input">Password:</label>
314
+ # <input id="password-input">
315
+ # ```
316
+ def get_by_label(text, exact: nil)
317
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
318
+ end
319
+
320
+ # Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
321
+ # "Country":
322
+ #
323
+ # ```html
324
+ # <input placeholder="Country">
325
+ # ```
326
+ def get_by_placeholder(text, exact: nil)
327
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
328
+ end
329
+
330
+ # Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles),
331
+ # [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and
332
+ # [accessible name](https://w3c.github.io/accname/#dfn-accessible-name). Note that role selector **does not replace**
333
+ # accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
334
+ #
335
+ # Note that many html elements have an implicitly
336
+ # [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings) that is recognized by the role selector. You
337
+ # can find all the [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not
338
+ # recommend** duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
339
+ def get_by_role(
340
+ role,
341
+ checked: nil,
342
+ disabled: nil,
343
+ exact: nil,
344
+ expanded: nil,
345
+ includeHidden: nil,
346
+ level: nil,
347
+ name: nil,
348
+ pressed: nil,
349
+ selected: nil)
350
+ wrap_impl(@impl.get_by_role(unwrap_impl(role), checked: unwrap_impl(checked), disabled: unwrap_impl(disabled), exact: unwrap_impl(exact), expanded: unwrap_impl(expanded), includeHidden: unwrap_impl(includeHidden), level: unwrap_impl(level), name: unwrap_impl(name), pressed: unwrap_impl(pressed), selected: unwrap_impl(selected)))
351
+ end
352
+
353
+ # Locate element by the test id. By default, the `data-testid` attribute is used as a test id. Use
354
+ # [`method: Selectors.setTestIdAttribute`] to configure a different test id attribute if necessary.
355
+ def get_by_test_id(testId)
356
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
357
+ end
358
+
359
+ # Allows locating elements that contain given text. Consider the following DOM structure:
360
+ #
361
+ # ```html
362
+ # <div>Hello <span>world</span></div>
363
+ # <div>Hello</div>
364
+ # ```
365
+ #
366
+ # You can locate by text substring, exact string, or a regular expression:
367
+ #
368
+ # ```python sync
369
+ # # Matches <span>
370
+ # page.get_by_text("world")
371
+ #
372
+ # # Matches first <div>
373
+ # page.get_by_text("Hello world")
374
+ #
375
+ # # Matches second <div>
376
+ # page.get_by_text("Hello", exact=True)
377
+ #
378
+ # # Matches both <div>s
379
+ # page.get_by_text(re.compile("Hello"))
380
+ #
381
+ # # Matches second <div>
382
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
383
+ # ```
384
+ #
385
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter
386
+ # by the text content.
387
+ #
388
+ # > NOTE: Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
389
+ # one, turns line breaks into spaces and ignores leading and trailing whitespace.
390
+ # > NOTE: Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
391
+ # example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
392
+ def get_by_text(text, exact: nil)
393
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
394
+ end
395
+
396
+ # Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
397
+ #
398
+ # ```html
399
+ # <button title='Place the order'>Order Now</button>
400
+ # ```
401
+ def get_by_title(text, exact: nil)
402
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
403
+ end
404
+
269
405
  # Highlight the corresponding element(s) on the screen. Useful for debugging, don't commit the code that uses
270
406
  # [`method: Locator.highlight`].
271
407
  def highlight
@@ -285,10 +421,11 @@ module Playwright
285
421
  def hover(
286
422
  force: nil,
287
423
  modifiers: nil,
424
+ noWaitAfter: nil,
288
425
  position: nil,
289
426
  timeout: nil,
290
427
  trial: nil)
291
- wrap_impl(@impl.hover(force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), position: unwrap_impl(position), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
428
+ wrap_impl(@impl.hover(force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
292
429
  end
293
430
 
294
431
  # Returns the `element.innerHTML`.
@@ -344,8 +481,10 @@ module Playwright
344
481
  wrap_impl(@impl.last)
345
482
  end
346
483
 
347
- # The method finds an element matching the specified selector in the `Locator`'s subtree. It also accepts filter options,
484
+ # The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options,
348
485
  # similar to [`method: Locator.filter`] method.
486
+ #
487
+ # [Learn more about locators](../locators.md).
349
488
  def locator(selector, has: nil, hasText: nil)
350
489
  wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
351
490
  end
@@ -524,8 +663,8 @@ module Playwright
524
663
  # An example of typing into a text field and then submitting the form:
525
664
  #
526
665
  # ```python sync
527
- # element = page.locator("input")
528
- # element.type("some text")
666
+ # element = page.get_by_label("Password")
667
+ # element.type("my password")
529
668
  # element.press("Enter")
530
669
  # ```
531
670
  def type(text, delay: nil, noWaitAfter: nil, timeout: nil)
@@ -250,6 +250,19 @@ module Playwright
250
250
  wrap_impl(@impl.dispatch_event(unwrap_impl(selector), unwrap_impl(type), eventInit: unwrap_impl(eventInit), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
251
251
  end
252
252
 
253
+ # This method drags the source element to the target element. It will first move to the source element, perform a
254
+ # `mousedown`, then move to the target element and perform a `mouseup`.
255
+ #
256
+ # ```python sync
257
+ # page.drag_and_drop("#source", "#target")
258
+ # # or specify exact positions relative to the top-left corners of the elements:
259
+ # page.drag_and_drop(
260
+ # "#source",
261
+ # "#target",
262
+ # source_position={"x": 34, "y": 7},
263
+ # target_position={"x": 10, "y": 20}
264
+ # )
265
+ # ```
253
266
  def drag_and_drop(
254
267
  source,
255
268
  target,
@@ -553,7 +566,7 @@ module Playwright
553
566
  # id="my-frame">`:
554
567
  #
555
568
  # ```python sync
556
- # locator = page.frame_locator("#my-iframe").locator("text=Submit")
569
+ # locator = page.frame_locator("#my-iframe").get_by_text("Submit")
557
570
  # locator.click()
558
571
  # ```
559
572
  def frame_locator(selector)
@@ -570,6 +583,111 @@ module Playwright
570
583
  wrap_impl(@impl.get_attribute(unwrap_impl(selector), unwrap_impl(name), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
571
584
  end
572
585
 
586
+ # Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
587
+ #
588
+ # ```html
589
+ # <img alt='Castle'>
590
+ # ```
591
+ def get_by_alt_text(text, exact: nil)
592
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
593
+ end
594
+
595
+ # Allows locating input elements by the text of the associated label. For example, this method will find the input by
596
+ # label text "Password" in the following DOM:
597
+ #
598
+ # ```html
599
+ # <label for="password-input">Password:</label>
600
+ # <input id="password-input">
601
+ # ```
602
+ def get_by_label(text, exact: nil)
603
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
604
+ end
605
+
606
+ # Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
607
+ # "Country":
608
+ #
609
+ # ```html
610
+ # <input placeholder="Country">
611
+ # ```
612
+ def get_by_placeholder(text, exact: nil)
613
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
614
+ end
615
+
616
+ # Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles),
617
+ # [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and
618
+ # [accessible name](https://w3c.github.io/accname/#dfn-accessible-name). Note that role selector **does not replace**
619
+ # accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
620
+ #
621
+ # Note that many html elements have an implicitly
622
+ # [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings) that is recognized by the role selector. You
623
+ # can find all the [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not
624
+ # recommend** duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
625
+ def get_by_role(
626
+ role,
627
+ checked: nil,
628
+ disabled: nil,
629
+ exact: nil,
630
+ expanded: nil,
631
+ includeHidden: nil,
632
+ level: nil,
633
+ name: nil,
634
+ pressed: nil,
635
+ selected: nil)
636
+ wrap_impl(@impl.get_by_role(unwrap_impl(role), checked: unwrap_impl(checked), disabled: unwrap_impl(disabled), exact: unwrap_impl(exact), expanded: unwrap_impl(expanded), includeHidden: unwrap_impl(includeHidden), level: unwrap_impl(level), name: unwrap_impl(name), pressed: unwrap_impl(pressed), selected: unwrap_impl(selected)))
637
+ end
638
+
639
+ # Locate element by the test id. By default, the `data-testid` attribute is used as a test id. Use
640
+ # [`method: Selectors.setTestIdAttribute`] to configure a different test id attribute if necessary.
641
+ def get_by_test_id(testId)
642
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
643
+ end
644
+
645
+ # Allows locating elements that contain given text. Consider the following DOM structure:
646
+ #
647
+ # ```html
648
+ # <div>Hello <span>world</span></div>
649
+ # <div>Hello</div>
650
+ # ```
651
+ #
652
+ # You can locate by text substring, exact string, or a regular expression:
653
+ #
654
+ # ```python sync
655
+ # # Matches <span>
656
+ # page.get_by_text("world")
657
+ #
658
+ # # Matches first <div>
659
+ # page.get_by_text("Hello world")
660
+ #
661
+ # # Matches second <div>
662
+ # page.get_by_text("Hello", exact=True)
663
+ #
664
+ # # Matches both <div>s
665
+ # page.get_by_text(re.compile("Hello"))
666
+ #
667
+ # # Matches second <div>
668
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
669
+ # ```
670
+ #
671
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter
672
+ # by the text content.
673
+ #
674
+ # > NOTE: Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
675
+ # one, turns line breaks into spaces and ignores leading and trailing whitespace.
676
+ # > NOTE: Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
677
+ # example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
678
+ def get_by_text(text, exact: nil)
679
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
680
+ end
681
+
682
+ # Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
683
+ #
684
+ # ```html
685
+ # <button title='Place the order'>Order Now</button>
686
+ # ```
687
+ def get_by_title(text, exact: nil)
688
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
689
+ end
690
+
573
691
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
574
692
  # last redirect. If can not go back, returns `null`.
575
693
  #
@@ -626,11 +744,12 @@ module Playwright
626
744
  selector,
627
745
  force: nil,
628
746
  modifiers: nil,
747
+ noWaitAfter: nil,
629
748
  position: nil,
630
749
  strict: nil,
631
750
  timeout: nil,
632
751
  trial: nil)
633
- wrap_impl(@impl.hover(unwrap_impl(selector), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
752
+ wrap_impl(@impl.hover(unwrap_impl(selector), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
634
753
  end
635
754
 
636
755
  # Returns `element.innerHTML`.
@@ -688,13 +807,11 @@ module Playwright
688
807
  wrap_impl(@impl.visible?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
689
808
  end
690
809
 
691
- # The method returns an element locator that can be used to perform actions on the page. Locator is resolved to the
692
- # element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
693
- # different DOM elements. That would happen if the DOM structure between those actions has changed.
810
+ # The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved to
811
+ # the element immediately before performing an action, so a series of actions on the same locator can in fact be performed
812
+ # on different DOM elements. That would happen if the DOM structure between those actions has changed.
694
813
  #
695
814
  # [Learn more about locators](../locators.md).
696
- #
697
- # Shortcut for main frame's [`method: Frame.locator`].
698
815
  def locator(selector, has: nil, hasText: nil)
699
816
  wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
700
817
  end
@@ -1177,7 +1294,7 @@ module Playwright
1177
1294
  #
1178
1295
  # ```python sync
1179
1296
  # with page.expect_event("framenavigated") as event_info:
1180
- # page.click("button")
1297
+ # page.get_by_role("button")
1181
1298
  # frame = event_info.value
1182
1299
  # ```
1183
1300
  def expect_event(event, predicate: nil, timeout: nil, &block)
@@ -1228,13 +1345,13 @@ module Playwright
1228
1345
  # when this method is called. If current document has already reached the required state, resolves immediately.
1229
1346
  #
1230
1347
  # ```python sync
1231
- # page.click("button") # click triggers navigation.
1348
+ # page.get_by_role("button").click() # click triggers navigation.
1232
1349
  # page.wait_for_load_state() # the promise resolves after "load" event.
1233
1350
  # ```
1234
1351
  #
1235
1352
  # ```python sync
1236
1353
  # with page.expect_popup() as page_info:
1237
- # page.click("button") # click triggers a popup.
1354
+ # page.get_by_role("button").click() # click triggers a popup.
1238
1355
  # popup = page_info.value
1239
1356
  # # Following resolves after "domcontentloaded" event.
1240
1357
  # popup.wait_for_load_state("domcontentloaded")
@@ -1437,12 +1554,6 @@ module Playwright
1437
1554
  wrap_impl(@impl.stop_css_coverage)
1438
1555
  end
1439
1556
 
1440
- # -- inherited from EventEmitter --
1441
- # @nodoc
1442
- def off(event, callback)
1443
- event_emitter_proxy.off(event, callback)
1444
- end
1445
-
1446
1557
  # -- inherited from EventEmitter --
1447
1558
  # @nodoc
1448
1559
  def once(event, callback)
@@ -1455,6 +1566,12 @@ module Playwright
1455
1566
  event_emitter_proxy.on(event, callback)
1456
1567
  end
1457
1568
 
1569
+ # -- inherited from EventEmitter --
1570
+ # @nodoc
1571
+ def off(event, callback)
1572
+ event_emitter_proxy.off(event, callback)
1573
+ end
1574
+
1458
1575
  private def event_emitter_proxy
1459
1576
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
1460
1577
  end
@@ -96,12 +96,6 @@ module Playwright
96
96
  wrap_impl(@impl.electron)
97
97
  end
98
98
 
99
- # -- inherited from EventEmitter --
100
- # @nodoc
101
- def off(event, callback)
102
- event_emitter_proxy.off(event, callback)
103
- end
104
-
105
99
  # -- inherited from EventEmitter --
106
100
  # @nodoc
107
101
  def once(event, callback)
@@ -114,6 +108,12 @@ module Playwright
114
108
  event_emitter_proxy.on(event, callback)
115
109
  end
116
110
 
111
+ # -- inherited from EventEmitter --
112
+ # @nodoc
113
+ def off(event, callback)
114
+ event_emitter_proxy.off(event, callback)
115
+ end
116
+
117
117
  private def event_emitter_proxy
118
118
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
119
119
  end