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
@@ -91,6 +91,32 @@ module Playwright
91
91
 
92
92
  # Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and update
93
93
  # context cookies from the response. The method will automatically follow redirects.
94
+ #
95
+ # JSON objects can be passed directly to the request:
96
+ #
97
+ # ```python
98
+ # data = {
99
+ # "title": "Book Title",
100
+ # "body": "John Doe",
101
+ # }
102
+ # api_request_context.fetch("https://example.com/api/createBook", method="post", data=data)
103
+ # ```
104
+ #
105
+ # The common way to send file(s) in the body of a request is to encode it as form fields with `multipart/form-data`
106
+ # encoding. You can achieve that with Playwright API like this:
107
+ #
108
+ # ```python
109
+ # api_request_context.fetch(
110
+ # "https://example.com/api/uploadScrip'",
111
+ # method="post",
112
+ # multipart={
113
+ # "fileField": {
114
+ # "name": "f.js",
115
+ # "mimeType": "text/javascript",
116
+ # "buffer": b"console.log(2022);",
117
+ # },
118
+ # })
119
+ # ```
94
120
  def fetch(
95
121
  urlOrRequest,
96
122
  data: nil,
@@ -109,15 +135,28 @@ module Playwright
109
135
  # Sends HTTP(S) [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) request and returns its response. The
110
136
  # method will populate request cookies from the context and update context cookies from the response. The method will
111
137
  # automatically follow redirects.
138
+ #
139
+ # Request parameters can be configured with `params` option, they will be serialized into the URL search parameters:
140
+ #
141
+ # ```python
142
+ # query_params = {
143
+ # "isbn": "1234",
144
+ # "page": "23"
145
+ # }
146
+ # api_request_context.get("https://example.com/api/getText", params=query_params)
147
+ # ```
112
148
  def get(
113
149
  url,
150
+ data: nil,
114
151
  failOnStatusCode: nil,
152
+ form: nil,
115
153
  headers: nil,
116
154
  ignoreHTTPSErrors: nil,
117
155
  maxRedirects: nil,
156
+ multipart: nil,
118
157
  params: nil,
119
158
  timeout: nil)
120
- wrap_impl(@impl.get(unwrap_impl(url), failOnStatusCode: unwrap_impl(failOnStatusCode), headers: unwrap_impl(headers), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), maxRedirects: unwrap_impl(maxRedirects), params: unwrap_impl(params), timeout: unwrap_impl(timeout)))
159
+ wrap_impl(@impl.get(unwrap_impl(url), data: unwrap_impl(data), failOnStatusCode: unwrap_impl(failOnStatusCode), form: unwrap_impl(form), headers: unwrap_impl(headers), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), maxRedirects: unwrap_impl(maxRedirects), multipart: unwrap_impl(multipart), params: unwrap_impl(params), timeout: unwrap_impl(timeout)))
121
160
  end
122
161
 
123
162
  # Sends HTTP(S) [HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) request and returns its response.
@@ -125,13 +164,16 @@ module Playwright
125
164
  # automatically follow redirects.
126
165
  def head(
127
166
  url,
167
+ data: nil,
128
168
  failOnStatusCode: nil,
169
+ form: nil,
129
170
  headers: nil,
130
171
  ignoreHTTPSErrors: nil,
131
172
  maxRedirects: nil,
173
+ multipart: nil,
132
174
  params: nil,
133
175
  timeout: nil)
134
- wrap_impl(@impl.head(unwrap_impl(url), failOnStatusCode: unwrap_impl(failOnStatusCode), headers: unwrap_impl(headers), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), maxRedirects: unwrap_impl(maxRedirects), params: unwrap_impl(params), timeout: unwrap_impl(timeout)))
176
+ wrap_impl(@impl.head(unwrap_impl(url), data: unwrap_impl(data), failOnStatusCode: unwrap_impl(failOnStatusCode), form: unwrap_impl(form), headers: unwrap_impl(headers), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), maxRedirects: unwrap_impl(maxRedirects), multipart: unwrap_impl(multipart), params: unwrap_impl(params), timeout: unwrap_impl(timeout)))
135
177
  end
136
178
 
137
179
  # Sends HTTP(S) [PATCH](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) request and returns its response.
@@ -154,6 +196,42 @@ module Playwright
154
196
  # Sends HTTP(S) [POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) request and returns its response.
155
197
  # The method will populate request cookies from the context and update context cookies from the response. The method will
156
198
  # automatically follow redirects.
199
+ #
200
+ # JSON objects can be passed directly to the request:
201
+ #
202
+ # ```python
203
+ # data = {
204
+ # "title": "Book Title",
205
+ # "body": "John Doe",
206
+ # }
207
+ # api_request_context.post("https://example.com/api/createBook", data=data)
208
+ # ```
209
+ #
210
+ # To send form data to the server use `form` option. Its value will be encoded into the request body with
211
+ # `application/x-www-form-urlencoded` encoding (see below how to use `multipart/form-data` form encoding to send files):
212
+ #
213
+ # ```python
214
+ # formData = {
215
+ # "title": "Book Title",
216
+ # "body": "John Doe",
217
+ # }
218
+ # api_request_context.post("https://example.com/api/findBook", form=formData)
219
+ # ```
220
+ #
221
+ # The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data`
222
+ # encoding. You can achieve that with Playwright API like this:
223
+ #
224
+ # ```python
225
+ # api_request_context.post(
226
+ # "https://example.com/api/uploadScrip'",
227
+ # multipart={
228
+ # "fileField": {
229
+ # "name": "f.js",
230
+ # "mimeType": "text/javascript",
231
+ # "buffer": b"console.log(2022);",
232
+ # },
233
+ # })
234
+ # ```
157
235
  def post(
158
236
  url,
159
237
  data: nil,
@@ -191,12 +269,6 @@ module Playwright
191
269
  raise NotImplementedError.new('storage_state is not implemented yet.')
192
270
  end
193
271
 
194
- # -- inherited from EventEmitter --
195
- # @nodoc
196
- def off(event, callback)
197
- event_emitter_proxy.off(event, callback)
198
- end
199
-
200
272
  # -- inherited from EventEmitter --
201
273
  # @nodoc
202
274
  def once(event, callback)
@@ -209,6 +281,12 @@ module Playwright
209
281
  event_emitter_proxy.on(event, callback)
210
282
  end
211
283
 
284
+ # -- inherited from EventEmitter --
285
+ # @nodoc
286
+ def off(event, callback)
287
+ event_emitter_proxy.off(event, callback)
288
+ end
289
+
212
290
  private def event_emitter_proxy
213
291
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
214
292
  end
@@ -192,12 +192,6 @@ module Playwright
192
192
  wrap_impl(@impl.version)
193
193
  end
194
194
 
195
- # -- inherited from EventEmitter --
196
- # @nodoc
197
- def off(event, callback)
198
- event_emitter_proxy.off(event, callback)
199
- end
200
-
201
195
  # -- inherited from EventEmitter --
202
196
  # @nodoc
203
197
  def once(event, callback)
@@ -210,6 +204,12 @@ module Playwright
210
204
  event_emitter_proxy.on(event, callback)
211
205
  end
212
206
 
207
+ # -- inherited from EventEmitter --
208
+ # @nodoc
209
+ def off(event, callback)
210
+ event_emitter_proxy.off(event, callback)
211
+ end
212
+
213
213
  private def event_emitter_proxy
214
214
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
215
215
  end
@@ -131,7 +131,7 @@ module Playwright
131
131
  # <button onclick="onClick()">Click me</button>
132
132
  # <div></div>
133
133
  # """)
134
- # page.locator("button").click()
134
+ # page.get_by_role("button").click()
135
135
  #
136
136
  # with sync_playwright() as playwright:
137
137
  # run(playwright)
@@ -190,7 +190,7 @@ module Playwright
190
190
  # <button onclick="onClick()">Click me</button>
191
191
  # <div></div>
192
192
  # """)
193
- # page.locator("button").click()
193
+ # page.get_by_role("button").click()
194
194
  #
195
195
  # with sync_playwright() as playwright:
196
196
  # run(playwright)
@@ -358,7 +358,7 @@ module Playwright
358
358
  #
359
359
  # ```python sync
360
360
  # with context.expect_event("page") as event_info:
361
- # page.locator("button").click()
361
+ # page.get_by_role("button").click()
362
362
  # page = event_info.value
363
363
  # ```
364
364
  def expect_event(event, predicate: nil, timeout: nil, &block)
@@ -406,12 +406,6 @@ module Playwright
406
406
  wrap_impl(@impl.owner_page=(unwrap_impl(req)))
407
407
  end
408
408
 
409
- # -- inherited from EventEmitter --
410
- # @nodoc
411
- def off(event, callback)
412
- event_emitter_proxy.off(event, callback)
413
- end
414
-
415
409
  # -- inherited from EventEmitter --
416
410
  # @nodoc
417
411
  def once(event, callback)
@@ -424,6 +418,12 @@ module Playwright
424
418
  event_emitter_proxy.on(event, callback)
425
419
  end
426
420
 
421
+ # -- inherited from EventEmitter --
422
+ # @nodoc
423
+ def off(event, callback)
424
+ event_emitter_proxy.off(event, callback)
425
+ end
426
+
427
427
  private def event_emitter_proxy
428
428
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
429
429
  end
@@ -158,12 +158,6 @@ module Playwright
158
158
  wrap_impl(@impl.name)
159
159
  end
160
160
 
161
- # -- inherited from EventEmitter --
162
- # @nodoc
163
- def off(event, callback)
164
- event_emitter_proxy.off(event, callback)
165
- end
166
-
167
161
  # -- inherited from EventEmitter --
168
162
  # @nodoc
169
163
  def once(event, callback)
@@ -176,6 +170,12 @@ module Playwright
176
170
  event_emitter_proxy.on(event, callback)
177
171
  end
178
172
 
173
+ # -- inherited from EventEmitter --
174
+ # @nodoc
175
+ def off(event, callback)
176
+ event_emitter_proxy.off(event, callback)
177
+ end
178
+
179
179
  private def event_emitter_proxy
180
180
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
181
181
  end
@@ -33,12 +33,6 @@ module Playwright
33
33
  wrap_impl(@impl.send_message(unwrap_impl(method), params: unwrap_impl(params)))
34
34
  end
35
35
 
36
- # -- inherited from EventEmitter --
37
- # @nodoc
38
- def off(event, callback)
39
- event_emitter_proxy.off(event, callback)
40
- end
41
-
42
36
  # -- inherited from EventEmitter --
43
37
  # @nodoc
44
38
  def once(event, callback)
@@ -51,6 +45,12 @@ module Playwright
51
45
  event_emitter_proxy.on(event, callback)
52
46
  end
53
47
 
48
+ # -- inherited from EventEmitter --
49
+ # @nodoc
50
+ def off(event, callback)
51
+ event_emitter_proxy.off(event, callback)
52
+ end
53
+
54
54
  private def event_emitter_proxy
55
55
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
56
56
  end
@@ -42,12 +42,6 @@ module Playwright
42
42
  wrap_impl(@impl.type)
43
43
  end
44
44
 
45
- # -- inherited from EventEmitter --
46
- # @nodoc
47
- def off(event, callback)
48
- event_emitter_proxy.off(event, callback)
49
- end
50
-
51
45
  # -- inherited from EventEmitter --
52
46
  # @nodoc
53
47
  def once(event, callback)
@@ -60,6 +54,12 @@ module Playwright
60
54
  event_emitter_proxy.on(event, callback)
61
55
  end
62
56
 
57
+ # -- inherited from EventEmitter --
58
+ # @nodoc
59
+ def off(event, callback)
60
+ event_emitter_proxy.off(event, callback)
61
+ end
62
+
63
63
  private def event_emitter_proxy
64
64
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
65
65
  end
@@ -58,12 +58,6 @@ module Playwright
58
58
  wrap_impl(@impl.accept_async(promptText: unwrap_impl(promptText)))
59
59
  end
60
60
 
61
- # -- inherited from EventEmitter --
62
- # @nodoc
63
- def off(event, callback)
64
- event_emitter_proxy.off(event, callback)
65
- end
66
-
67
61
  # -- inherited from EventEmitter --
68
62
  # @nodoc
69
63
  def once(event, callback)
@@ -76,6 +70,12 @@ module Playwright
76
70
  event_emitter_proxy.on(event, callback)
77
71
  end
78
72
 
73
+ # -- inherited from EventEmitter --
74
+ # @nodoc
75
+ def off(event, callback)
76
+ event_emitter_proxy.off(event, callback)
77
+ end
78
+
79
79
  private def event_emitter_proxy
80
80
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
81
81
  end
@@ -7,7 +7,7 @@ module Playwright
7
7
  #
8
8
  # ```python sync
9
9
  # with page.expect_download() as download_info:
10
- # page.locator("a").click()
10
+ # page.get_by_text("Download file").click()
11
11
  # download = download_info.value
12
12
  # # wait for download to complete
13
13
  # path = download.path()
@@ -36,7 +36,7 @@ module Playwright
36
36
  # in the snippet below, underlying DOM element is going to be located twice.
37
37
  #
38
38
  # ```python sync
39
- # locator = page.locator("text=Submit")
39
+ # locator = page.get_by_text("Submit")
40
40
  # locator.hover()
41
41
  # locator.click()
42
42
  # ```
@@ -251,10 +251,11 @@ module Playwright
251
251
  def hover(
252
252
  force: nil,
253
253
  modifiers: nil,
254
+ noWaitAfter: nil,
254
255
  position: nil,
255
256
  timeout: nil,
256
257
  trial: nil)
257
- wrap_impl(@impl.hover(force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), position: unwrap_impl(position), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
258
+ 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)))
258
259
  end
259
260
 
260
261
  # Returns the `element.innerHTML`.
@@ -557,12 +558,6 @@ module Playwright
557
558
  wrap_impl(@impl.wait_for_selector(unwrap_impl(selector), state: unwrap_impl(state), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
558
559
  end
559
560
 
560
- # -- inherited from EventEmitter --
561
- # @nodoc
562
- def off(event, callback)
563
- event_emitter_proxy.off(event, callback)
564
- end
565
-
566
561
  # -- inherited from EventEmitter --
567
562
  # @nodoc
568
563
  def once(event, callback)
@@ -575,6 +570,12 @@ module Playwright
575
570
  event_emitter_proxy.on(event, callback)
576
571
  end
577
572
 
573
+ # -- inherited from EventEmitter --
574
+ # @nodoc
575
+ def off(event, callback)
576
+ event_emitter_proxy.off(event, callback)
577
+ end
578
+
578
579
  private def event_emitter_proxy
579
580
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
580
581
  end
@@ -3,7 +3,7 @@ module Playwright
3
3
  #
4
4
  # ```python sync
5
5
  # with page.expect_file_chooser() as fc_info:
6
- # page.locator("upload").click()
6
+ # page.get_by_text("Upload").click()
7
7
  # file_chooser = fc_info.value
8
8
  # file_chooser.set_files("myfile.pdf")
9
9
  # ```
@@ -335,7 +335,7 @@ module Playwright
335
335
  # id="my-frame">`:
336
336
  #
337
337
  # ```python sync
338
- # locator = frame.frame_locator("#my-iframe").locator("text=Submit")
338
+ # locator = frame.frame_locator("#my-iframe").get_by_text("Submit")
339
339
  # locator.click()
340
340
  # ```
341
341
  def frame_locator(selector)
@@ -347,6 +347,111 @@ module Playwright
347
347
  wrap_impl(@impl.get_attribute(unwrap_impl(selector), unwrap_impl(name), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
348
348
  end
349
349
 
350
+ # Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
351
+ #
352
+ # ```html
353
+ # <img alt='Castle'>
354
+ # ```
355
+ def get_by_alt_text(text, exact: nil)
356
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
357
+ end
358
+
359
+ # Allows locating input elements by the text of the associated label. For example, this method will find the input by
360
+ # label text "Password" in the following DOM:
361
+ #
362
+ # ```html
363
+ # <label for="password-input">Password:</label>
364
+ # <input id="password-input">
365
+ # ```
366
+ def get_by_label(text, exact: nil)
367
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
368
+ end
369
+
370
+ # Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
371
+ # "Country":
372
+ #
373
+ # ```html
374
+ # <input placeholder="Country">
375
+ # ```
376
+ def get_by_placeholder(text, exact: nil)
377
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
378
+ end
379
+
380
+ # Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles),
381
+ # [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and
382
+ # [accessible name](https://w3c.github.io/accname/#dfn-accessible-name). Note that role selector **does not replace**
383
+ # accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
384
+ #
385
+ # Note that many html elements have an implicitly
386
+ # [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings) that is recognized by the role selector. You
387
+ # can find all the [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not
388
+ # recommend** duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
389
+ def get_by_role(
390
+ role,
391
+ checked: nil,
392
+ disabled: nil,
393
+ exact: nil,
394
+ expanded: nil,
395
+ includeHidden: nil,
396
+ level: nil,
397
+ name: nil,
398
+ pressed: nil,
399
+ selected: nil)
400
+ 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)))
401
+ end
402
+
403
+ # Locate element by the test id. By default, the `data-testid` attribute is used as a test id. Use
404
+ # [`method: Selectors.setTestIdAttribute`] to configure a different test id attribute if necessary.
405
+ def get_by_test_id(testId)
406
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
407
+ end
408
+
409
+ # Allows locating elements that contain given text. Consider the following DOM structure:
410
+ #
411
+ # ```html
412
+ # <div>Hello <span>world</span></div>
413
+ # <div>Hello</div>
414
+ # ```
415
+ #
416
+ # You can locate by text substring, exact string, or a regular expression:
417
+ #
418
+ # ```python sync
419
+ # # Matches <span>
420
+ # page.get_by_text("world")
421
+ #
422
+ # # Matches first <div>
423
+ # page.get_by_text("Hello world")
424
+ #
425
+ # # Matches second <div>
426
+ # page.get_by_text("Hello", exact=True)
427
+ #
428
+ # # Matches both <div>s
429
+ # page.get_by_text(re.compile("Hello"))
430
+ #
431
+ # # Matches second <div>
432
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
433
+ # ```
434
+ #
435
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter
436
+ # by the text content.
437
+ #
438
+ # > NOTE: Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
439
+ # one, turns line breaks into spaces and ignores leading and trailing whitespace.
440
+ # > NOTE: Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
441
+ # example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
442
+ def get_by_text(text, exact: nil)
443
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
444
+ end
445
+
446
+ # Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
447
+ #
448
+ # ```html
449
+ # <button title='Place the order'>Order Now</button>
450
+ # ```
451
+ def get_by_title(text, exact: nil)
452
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
453
+ end
454
+
350
455
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
351
456
  # last redirect.
352
457
  #
@@ -383,11 +488,12 @@ module Playwright
383
488
  selector,
384
489
  force: nil,
385
490
  modifiers: nil,
491
+ noWaitAfter: nil,
386
492
  position: nil,
387
493
  strict: nil,
388
494
  timeout: nil,
389
495
  trial: nil)
390
- 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)))
496
+ 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)))
391
497
  end
392
498
 
393
499
  # Returns `element.innerHTML`.
@@ -445,9 +551,11 @@ module Playwright
445
551
  wrap_impl(@impl.visible?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
446
552
  end
447
553
 
448
- # The method returns an element locator that can be used to perform actions in the frame. Locator is resolved to the
449
- # element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
450
- # different DOM elements. That would happen if the DOM structure between those actions has changed.
554
+ # The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved to
555
+ # the element immediately before performing an action, so a series of actions on the same locator can in fact be performed
556
+ # on different DOM elements. That would happen if the DOM structure between those actions has changed.
557
+ #
558
+ # [Learn more about locators](../locators.md).
451
559
  #
452
560
  # [Learn more about locators](../locators.md).
453
561
  def locator(selector, has: nil, hasText: nil)
@@ -800,12 +908,6 @@ module Playwright
800
908
  wrap_impl(@impl.highlight(unwrap_impl(selector)))
801
909
  end
802
910
 
803
- # -- inherited from EventEmitter --
804
- # @nodoc
805
- def off(event, callback)
806
- event_emitter_proxy.off(event, callback)
807
- end
808
-
809
911
  # -- inherited from EventEmitter --
810
912
  # @nodoc
811
913
  def once(event, callback)
@@ -818,6 +920,12 @@ module Playwright
818
920
  event_emitter_proxy.on(event, callback)
819
921
  end
820
922
 
923
+ # -- inherited from EventEmitter --
924
+ # @nodoc
925
+ def off(event, callback)
926
+ event_emitter_proxy.off(event, callback)
927
+ end
928
+
821
929
  private def event_emitter_proxy
822
930
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
823
931
  end