playwright-ruby-client 1.32.0 → 1.34.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/browser_context.md +12 -1
  3. data/documentation/docs/api/console_message.md +9 -0
  4. data/documentation/docs/api/dialog.md +9 -0
  5. data/documentation/docs/api/frame.md +6 -1
  6. data/documentation/docs/api/frame_locator.md +6 -1
  7. data/documentation/docs/api/locator.md +52 -3
  8. data/documentation/docs/api/page.md +6 -1
  9. data/documentation/docs/api/route.md +2 -1
  10. data/documentation/docs/include/api_coverage.md +5 -0
  11. data/lib/playwright/channel_owners/browser_context.rb +40 -2
  12. data/lib/playwright/channel_owners/console_message.rb +4 -0
  13. data/lib/playwright/channel_owners/dialog.rb +4 -0
  14. data/lib/playwright/channel_owners/frame.rb +14 -2
  15. data/lib/playwright/channel_owners/page.rb +14 -14
  16. data/lib/playwright/channel_owners/request.rb +6 -1
  17. data/lib/playwright/channel_owners/route.rb +5 -2
  18. data/lib/playwright/events.rb +2 -0
  19. data/lib/playwright/frame_locator_impl.rb +9 -3
  20. data/lib/playwright/locator_impl.rb +50 -10
  21. data/lib/playwright/locator_utils.rb +1 -1
  22. data/lib/playwright/version.rb +2 -2
  23. data/lib/playwright.rb +1 -1
  24. data/lib/playwright_api/browser_context.rb +10 -2
  25. data/lib/playwright_api/console_message.rb +6 -0
  26. data/lib/playwright_api/dialog.rb +6 -0
  27. data/lib/playwright_api/frame.rb +7 -2
  28. data/lib/playwright_api/frame_locator.rb +7 -2
  29. data/lib/playwright_api/locator.rb +47 -5
  30. data/lib/playwright_api/page.rb +7 -2
  31. data/lib/playwright_api/route.rb +3 -2
  32. data/lib/playwright_api/worker.rb +4 -4
  33. data/sig/playwright.rbs +12 -7
  34. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 495cb2986f254eece67f5db9b5f7f528e6ee4ce450d8cb9f33710fffd33f6f36
4
- data.tar.gz: a77adbc84c2b816988262c71a44772d314c9a6fef5420d8122b71ee698c1bd43
3
+ metadata.gz: 64c373804c3cc418f35774036436563714c4e7a42ce87d9ce242d961814c28f9
4
+ data.tar.gz: 3dccf880e4d4911279bbac84575f03872284c379fdcac468fa4e16940b51c352
5
5
  SHA512:
6
- metadata.gz: 6b4a172fe40f17bd6b6177b623eeb8397d2e696e65c1a84a318dfcd6df6cd134460e1924b30ebf030402d8ba0c20823d178d9a9eef822e66ea39801cf63fa2a7
7
- data.tar.gz: 5682df9be25bd8ff3a97f9b85d925c4ca410c12570f18f238dee17188a3520357b32ad5265f49bcfab371bfb83ae12723c8a039c56608c79832661f7c65c9221
6
+ metadata.gz: e911b7eac54e773e83c18efcc13562500e736b75fc259da2f63abed7bc31b716d86b568215c410245fd613a379a3c0fdb63a3a9d942b33042eaf14019829474b
7
+ data.tar.gz: 47ce8a3dd0a37c79c4786f3d1b34ce99009ee3a572b1d88345d3ae6da767c81cc4f6f0bb9e14c93292dfe4e007f229dd37861a1e358544f787f1aa463792b1f0
@@ -451,6 +451,17 @@ def unroute(url, handler: nil)
451
451
  Removes a route created with [BrowserContext#route](./browser_context#route). When `handler` is not specified, removes all
452
452
  routes for the `url`.
453
453
 
454
+ ## expect_console_message
455
+
456
+ ```
457
+ def expect_console_message(predicate: nil, timeout: nil, &block)
458
+ ```
459
+
460
+
461
+ Performs action and waits for a [ConsoleMessage](./console_message) to be logged by in the pages in the context. If predicate is provided, it passes
462
+ [ConsoleMessage](./console_message) value into the `predicate` function and waits for `predicate(message)` to return a truthy value.
463
+ Will throw an error if the page is closed before the [`event: BrowserContext.console`] event is fired.
464
+
454
465
  ## expect_event
455
466
 
456
467
  ```
@@ -472,7 +483,7 @@ end
472
483
  ## expect_page
473
484
 
474
485
  ```
475
- def expect_page(predicate: nil, timeout: nil)
486
+ def expect_page(predicate: nil, timeout: nil, &block)
476
487
  ```
477
488
 
478
489
 
@@ -49,6 +49,15 @@ def location
49
49
 
50
50
 
51
51
 
52
+ ## page
53
+
54
+ ```
55
+ def page
56
+ ```
57
+
58
+
59
+ The page that produced this console message, if any.
60
+
52
61
  ## text
53
62
 
54
63
  ```
@@ -65,6 +65,15 @@ def message
65
65
 
66
66
  A message displayed in the dialog.
67
67
 
68
+ ## page
69
+
70
+ ```
71
+ def page
72
+ ```
73
+
74
+
75
+ The page that initiated this dialog, if available.
76
+
68
77
  ## type
69
78
 
70
79
  ```
@@ -779,7 +779,12 @@ Returns whether the element is [visible](https://playwright.dev/python/docs/acti
779
779
  ## locator
780
780
 
781
781
  ```
782
- def locator(selector, has: nil, hasText: nil)
782
+ def locator(
783
+ selector,
784
+ has: nil,
785
+ hasNot: nil,
786
+ hasNotText: nil,
787
+ hasText: nil)
783
788
  ```
784
789
 
785
790
 
@@ -284,7 +284,12 @@ Returns locator to the last matching frame.
284
284
  ## locator
285
285
 
286
286
  ```
287
- def locator(selectorOrLocator, has: nil, hasText: nil)
287
+ def locator(
288
+ selectorOrLocator,
289
+ has: nil,
290
+ hasNot: nil,
291
+ hasNotText: nil,
292
+ hasText: nil)
288
293
  ```
289
294
 
290
295
 
@@ -20,7 +20,11 @@ def all
20
20
  When locator points to a list of elements, returns array of locators, pointing
21
21
  to respective elements.
22
22
 
23
- Note that [Locator#all](./locator#all) does not wait for elements to match the locator, and instead immediately returns whatever is present in the page. To avoid flakiness when elements are loaded dynamically, wait for the loading to finish before calling [Locator#all](./locator#all).
23
+ **NOTE**: [Locator#all](./locator#all) does not wait for elements to match the locator, and instead immediately returns whatever is present in the page.
24
+
25
+ When the list of elements changes dynamically, [Locator#all](./locator#all) will produce unpredictable and flaky results.
26
+
27
+ When the list of elements is stable, but loaded dynamically, wait for the full list to finish loading before calling [Locator#all](./locator#all).
24
28
 
25
29
  **Usage**
26
30
 
@@ -60,6 +64,23 @@ Returns an array of `node.textContent` values for all matching nodes.
60
64
  texts = page.get_by_role("link").all_text_contents
61
65
  ```
62
66
 
67
+ ## and
68
+
69
+ ```
70
+ def and(locator)
71
+ ```
72
+
73
+
74
+ Creates a locator that matches both this locator and the argument locator.
75
+
76
+ **Usage**
77
+
78
+ The following example finds a button with a specific title.
79
+
80
+ ```ruby
81
+ button = page.get_by_role("button").and(page.get_by_title("Subscribe"))
82
+ ```
83
+
63
84
  ## blur
64
85
 
65
86
  ```
@@ -443,7 +464,7 @@ To send fine-grained keyboard events, use [Locator#type](./locator#type).
443
464
  ## filter
444
465
 
445
466
  ```
446
- def filter(has: nil, hasText: nil)
467
+ def filter(has: nil, hasNot: nil, hasNotText: nil, hasText: nil)
447
468
  ```
448
469
 
449
470
 
@@ -915,7 +936,12 @@ banana = page.get_by_role("listitem").last
915
936
  ## locator
916
937
 
917
938
  ```
918
- def locator(selectorOrLocator, has: nil, hasText: nil)
939
+ def locator(
940
+ selectorOrLocator,
941
+ has: nil,
942
+ hasNot: nil,
943
+ hasNotText: nil,
944
+ hasText: nil)
919
945
  ```
920
946
 
921
947
 
@@ -938,6 +964,29 @@ Returns locator to the n-th matching element. It's zero based, `nth(0)` selects
938
964
  banana = page.get_by_role("listitem").nth(2)
939
965
  ```
940
966
 
967
+ ## or
968
+
969
+ ```
970
+ def or(locator)
971
+ ```
972
+
973
+
974
+ Creates a locator that matches either of the two locators.
975
+
976
+ **Usage**
977
+
978
+ Consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly.
979
+
980
+ ```ruby
981
+ new_email = page.get_by_role("button", name: "New")
982
+ dialog = page.get_by_text("Confirm security settings")
983
+ new_email.or(dialog).wait_for(state: 'visible')
984
+ if dialog.visible?
985
+ page.get_by_role("button", name: "Dismiss").click
986
+ end
987
+ new_email.click
988
+ ```
989
+
941
990
  ## page
942
991
 
943
992
  ```
@@ -1015,7 +1015,12 @@ Returns whether the element is [visible](https://playwright.dev/python/docs/acti
1015
1015
  ## locator
1016
1016
 
1017
1017
  ```
1018
- def locator(selector, has: nil, hasText: nil)
1018
+ def locator(
1019
+ selector,
1020
+ has: nil,
1021
+ hasNot: nil,
1022
+ hasNotText: nil,
1023
+ hasText: nil)
1019
1024
  ```
1020
1025
 
1021
1026
 
@@ -84,7 +84,7 @@ def handle_post(route, request)
84
84
  end
85
85
 
86
86
  # Handle POST requests.
87
- def handle_post(route)
87
+ def handle_post(route, request)
88
88
  if request.method != "POST"
89
89
  route.fallback
90
90
  return
@@ -122,6 +122,7 @@ def fetch(
122
122
  maxRedirects: nil,
123
123
  method: nil,
124
124
  postData: nil,
125
+ timeout: nil,
125
126
  url: nil)
126
127
  ```
127
128
 
@@ -218,6 +218,7 @@
218
218
 
219
219
  * args
220
220
  * location
221
+ * page
221
222
  * text
222
223
  * type
223
224
 
@@ -227,6 +228,7 @@
227
228
  * default_value
228
229
  * dismiss
229
230
  * message
231
+ * page
230
232
  * type
231
233
 
232
234
  ## Download
@@ -367,6 +369,7 @@
367
369
  * set_offline
368
370
  * storage_state
369
371
  * unroute
372
+ * expect_console_message
370
373
  * expect_event
371
374
  * expect_page
372
375
  * ~~wait_for_event~~
@@ -422,6 +425,7 @@
422
425
  * all
423
426
  * all_inner_texts
424
427
  * all_text_contents
428
+ * and
425
429
  * blur
426
430
  * bounding_box
427
431
  * check
@@ -463,6 +467,7 @@
463
467
  * last
464
468
  * locator
465
469
  * nth
470
+ * or
466
471
  * page
467
472
  * press
468
473
  * screenshot
@@ -35,6 +35,12 @@ module Playwright
35
35
  @channel.on('serviceWorker', ->(params) {
36
36
  on_service_worker(ChannelOwners::Worker.from(params['worker']))
37
37
  })
38
+ @channel.on('console', ->(params) {
39
+ on_console_message(ChannelOwners::ConsoleMessage.from(params['message']))
40
+ })
41
+ @channel.on('dialog', ->(params) {
42
+ on_dialog(ChannelOwners::Dialog.from(params['dialog']))
43
+ })
38
44
  @channel.on('request', ->(params) {
39
45
  on_request(
40
46
  ChannelOwners::Request.from(params['request']),
@@ -57,6 +63,8 @@ module Playwright
57
63
  )
58
64
  })
59
65
  set_event_to_subscription_mapping({
66
+ Events::BrowserContext::Console => 'console',
67
+ Events::BrowserContext::Dialog => 'dialog',
60
68
  Events::BrowserContext::Request => "request",
61
69
  Events::BrowserContext::Response => "response",
62
70
  Events::BrowserContext::RequestFinished => "requestFinished",
@@ -147,6 +155,28 @@ module Playwright
147
155
  response&.send(:mark_as_finished)
148
156
  end
149
157
 
158
+ private def on_console_message(message)
159
+ emit(Events::BrowserContext::Console, message)
160
+ if (page = message.page)
161
+ page.emit(Events::Page::Console, message)
162
+ end
163
+ end
164
+
165
+ private def on_dialog(dialog)
166
+ consumed_by_context = emit(Events::BrowserContext::Dialog, dialog)
167
+ if (page = dialog.page)
168
+ consumed_by_page = page.emit(Events::Page::Dialog, dialog)
169
+ end
170
+
171
+ if !consumed_by_context && !consumed_by_page
172
+ if dialog.type == 'beforeunload'
173
+ dialog.accept_async
174
+ else
175
+ dialog.dismiss
176
+ end
177
+ end
178
+ end
179
+
150
180
  private def on_request(request, page)
151
181
  emit(Events::BrowserContext::Request, request)
152
182
  page&.emit(Events::Page::Request, request)
@@ -414,12 +444,20 @@ module Playwright
414
444
  end
415
445
  end
416
446
 
417
- def expect_page(predicate: nil, timeout: nil)
447
+ def expect_console_message(predicate: nil, timeout: nil, &block)
448
+ params = {
449
+ predicate: predicate,
450
+ timeout: timeout,
451
+ }.compact
452
+ expect_event(Events::BrowserContext::Console, params, &block)
453
+ end
454
+
455
+ def expect_page(predicate: nil, timeout: nil, &block)
418
456
  params = {
419
457
  predicate: predicate,
420
458
  timeout: timeout,
421
459
  }.compact
422
- expect_event(Events::BrowserContext::Page, params)
460
+ expect_event(Events::BrowserContext::Page, params, &block)
423
461
  end
424
462
 
425
463
  # called from Page#on_close with send(:remove_page, page), so keep private
@@ -1,5 +1,9 @@
1
1
  module Playwright
2
2
  define_channel_owner :ConsoleMessage do
3
+ def page
4
+ @page ||= ChannelOwners::Page.from_nullable(@initializer['page'])
5
+ end
6
+
3
7
  def type
4
8
  @initializer['type']
5
9
  end
@@ -1,5 +1,9 @@
1
1
  module Playwright
2
2
  define_channel_owner :Dialog do
3
+ def page
4
+ @page ||= ChannelOwners::Page.from_nullable(@initializer['page'])
5
+ end
6
+
3
7
  def type
4
8
  @initializer['type']
5
9
  end
@@ -418,8 +418,20 @@ module Playwright
418
418
  nil
419
419
  end
420
420
 
421
- def locator(selector, hasText: nil, has: nil)
422
- LocatorImpl.new(frame: self, timeout_settings: @page.send(:timeout_settings), selector: selector, hasText: hasText, has: has)
421
+ def locator(
422
+ selector,
423
+ has: nil,
424
+ hasNot: nil,
425
+ hasNotText: nil,
426
+ hasText: nil)
427
+ LocatorImpl.new(
428
+ frame: self,
429
+ timeout_settings: @page.send(:timeout_settings),
430
+ selector: selector,
431
+ has: has,
432
+ hasNot: hasNot,
433
+ hasNotText: hasNotText,
434
+ hasText: hasText)
423
435
  end
424
436
 
425
437
  def frame_locator(selector)
@@ -36,12 +36,7 @@ module Playwright
36
36
 
37
37
  @channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
38
38
  @channel.once('close', ->(_) { on_close })
39
- @channel.on('console', ->(params) {
40
- console_message = ChannelOwners::ConsoleMessage.from(params['message'])
41
- emit(Events::Page::Console, console_message)
42
- })
43
39
  @channel.on('crash', ->(_) { emit(Events::Page::Crash) })
44
- @channel.on('dialog', method(:on_dialog))
45
40
  @channel.on('download', method(:on_download))
46
41
  @channel.on('fileChooser', ->(params) {
47
42
  chooser = FileChooserImpl.new(
@@ -70,6 +65,8 @@ module Playwright
70
65
  })
71
66
 
72
67
  set_event_to_subscription_mapping({
68
+ Events::Page::Console => "console",
69
+ Events::Page::Dialog => "dialog",
73
70
  Events::Page::Request => "request",
74
71
  Events::Page::Response => "response",
75
72
  Events::Page::RequestFinished => "requestFinished",
@@ -151,13 +148,6 @@ module Playwright
151
148
  emit(Events::Page::Close)
152
149
  end
153
150
 
154
- private def on_dialog(params)
155
- dialog = ChannelOwners::Dialog.from(params['dialog'])
156
- unless emit(Events::Page::Dialog, dialog)
157
- dialog.dismiss
158
- end
159
- end
160
-
161
151
  private def on_download(params)
162
152
  artifact = ChannelOwners::Artifact.from(params['artifact'])
163
153
  download = DownloadImpl.new(
@@ -614,8 +604,18 @@ module Playwright
614
604
  timeout: timeout)
615
605
  end
616
606
 
617
- def locator(selector, hasText: nil, has: nil)
618
- @main_frame.locator(selector, hasText: hasText, has: has)
607
+ def locator(
608
+ selector,
609
+ has: nil,
610
+ hasNot: nil,
611
+ hasNotText: nil,
612
+ hasText: nil)
613
+ @main_frame.locator(
614
+ selector,
615
+ has: has,
616
+ hasNot: hasNot,
617
+ hasNotText: hasNotText,
618
+ hasText: hasText)
619
619
  end
620
620
 
621
621
  def frame_locator(selector)
@@ -19,6 +19,7 @@ module Playwright
19
19
  responseEnd: -1,
20
20
  }
21
21
  @fallback_overrides = {}
22
+ @url = @initializer['url']
22
23
  end
23
24
 
24
25
  private def fallback_overrides
@@ -35,7 +36,11 @@ module Playwright
35
36
  end
36
37
 
37
38
  def url
38
- @fallback_overrides[:url] || @initializer['url']
39
+ @fallback_overrides[:url] || @url
40
+ end
41
+
42
+ private def internal_url
43
+ @url
39
44
  end
40
45
 
41
46
  def resource_type
@@ -21,7 +21,7 @@ module Playwright
21
21
 
22
22
  def abort(errorCode: nil)
23
23
  handling_with_result(true) do
24
- params = { errorCode: errorCode }.compact
24
+ params = { requestUrl: request.send(:internal_url), errorCode: errorCode }.compact
25
25
  # TODO _race_with_page_close
26
26
  @channel.async_send_message_to_server('abort', params)
27
27
  end
@@ -91,6 +91,7 @@ module Playwright
91
91
 
92
92
  params[:status] = option_status || 200
93
93
  params[:headers] = HttpHeaders.new(param_headers).as_serialized
94
+ params[:requestUrl] = request.send(:internal_url)
94
95
 
95
96
  @channel.async_send_message_to_server('fulfill', params)
96
97
  end
@@ -109,7 +110,7 @@ module Playwright
109
110
  end
110
111
  end
111
112
 
112
- def fetch(headers: nil, method: nil, postData: nil, url: nil, maxRedirects: nil)
113
+ def fetch(headers: nil, method: nil, postData: nil, url: nil, maxRedirects: nil, timeout: nil)
113
114
  api_request_context = request.frame.page.context.request
114
115
  api_request_context.send(:_inner_fetch,
115
116
  request,
@@ -118,6 +119,7 @@ module Playwright
118
119
  method: method,
119
120
  data: postData,
120
121
  maxRedirects: maxRedirects,
122
+ timeout: timeout,
121
123
  )
122
124
  end
123
125
 
@@ -152,6 +154,7 @@ module Playwright
152
154
  if post_data_for_wire
153
155
  params[:postData] = post_data_for_wire
154
156
  end
157
+ params[:requestUrl] = request.send(:internal_url)
155
158
 
156
159
  # TODO _race_with_page_close
157
160
  @channel.async_send_message_to_server('continue', params)
@@ -26,6 +26,8 @@ end
26
26
  BrowserContext: {
27
27
  BackgroundPage: 'backgroundpage',
28
28
  Close: 'close',
29
+ Console: 'console',
30
+ Dialog: 'dialog',
29
31
  Page: 'page',
30
32
  ServiceWorker: 'serviceworker',
31
33
  Request: 'request',
@@ -10,14 +10,20 @@ module Playwright
10
10
  @frame_selector = frame_selector
11
11
  end
12
12
 
13
- def locator(selector, hasText: nil, has: nil)
13
+ def locator(
14
+ selector,
15
+ has: nil,
16
+ hasNot: nil,
17
+ hasNotText: nil,
18
+ hasText: nil)
14
19
  LocatorImpl.new(
15
20
  frame: @frame,
16
21
  timeout_settings: @timeout_settings,
17
22
  selector: "#{@frame_selector} >> internal:control=enter-frame >> #{selector}",
18
- hasText: hasText,
19
23
  has: has,
20
- )
24
+ hasNot: hasNot,
25
+ hasNotText: hasNotText,
26
+ hasText: hasText)
21
27
  end
22
28
 
23
29
  def frame_locator(selector)
@@ -5,7 +5,7 @@ module Playwright
5
5
  define_api_implementation :LocatorImpl do
6
6
  include LocatorUtils
7
7
 
8
- def initialize(frame:, timeout_settings:, selector:, hasText: nil, has: nil)
8
+ def initialize(frame:, timeout_settings:, selector:, has: nil, hasNot: nil, hasNotText: nil, hasText: nil)
9
9
  @frame = frame
10
10
  @timeout_settings = timeout_settings
11
11
  selector_scopes = [selector]
@@ -16,11 +16,22 @@ module Playwright
16
16
 
17
17
  if has
18
18
  unless same_frame?(has)
19
- raise DifferentFrameError.new
19
+ raise DifferentFrameError.new('has')
20
20
  end
21
21
  selector_scopes << "internal:has=#{has.send(:selector_json)}"
22
22
  end
23
23
 
24
+ if hasNotText
25
+ selector_scopes << "internal:has-not-text=#{escape_for_text_selector(hasNotText, false)}"
26
+ end
27
+
28
+ if hasNot
29
+ unless same_frame?(hasNot)
30
+ raise DifferentFrameError.new('hasNot')
31
+ end
32
+ selector_scopes << "internal:has-not=#{hasNot.send(:selector_json)}"
33
+ end
34
+
24
35
  @selector = selector_scopes.join(' >> ')
25
36
  end
26
37
 
@@ -36,8 +47,8 @@ module Playwright
36
47
  end
37
48
 
38
49
  class DifferentFrameError < StandardError
39
- def initialize
40
- super('Inner "has" locator must belong to the same frame.')
50
+ def initialize(method_name)
51
+ super("Inner \"#{method_name}\" locator must belong to the same frame.")
41
52
  end
42
53
  end
43
54
 
@@ -190,14 +201,20 @@ module Playwright
190
201
  @frame.fill(@selector, '', strict: true, force: force, noWaitAfter: noWaitAfter, timeout: timeout)
191
202
  end
192
203
 
193
- def locator(selector, hasText: nil, has: nil)
204
+ def locator(
205
+ selector,
206
+ has: nil,
207
+ hasNot: nil,
208
+ hasNotText: nil,
209
+ hasText: nil)
194
210
  LocatorImpl.new(
195
211
  frame: @frame,
196
212
  timeout_settings: @timeout_settings,
197
213
  selector: "#{@selector} >> #{selector}",
198
- hasText: hasText,
199
214
  has: has,
200
- )
215
+ hasNot: hasNot,
216
+ hasNotText: hasNotText,
217
+ hasText: hasText)
201
218
  end
202
219
 
203
220
  def frame_locator(selector)
@@ -216,14 +233,15 @@ module Playwright
216
233
  @frame.query_selector_all(@selector)
217
234
  end
218
235
 
219
- def filter(has: nil, hasText: nil)
236
+ def filter(has: nil, hasNot: nil, hasNotText: nil, hasText: nil)
220
237
  LocatorImpl.new(
221
238
  frame: @frame,
222
239
  timeout_settings: @timeout_settings,
223
240
  selector: @selector,
224
- hasText: hasText,
225
241
  has: has,
226
- )
242
+ hasNot: hasNot,
243
+ hasNotText: hasNotText,
244
+ hasText: hasText)
227
245
  end
228
246
 
229
247
  def first
@@ -250,6 +268,28 @@ module Playwright
250
268
  )
251
269
  end
252
270
 
271
+ def and(locator)
272
+ unless same_frame?(locator)
273
+ raise DifferentFrameError.new('and')
274
+ end
275
+ LocatorImpl.new(
276
+ frame: @frame,
277
+ timeout_settings: @timeout_settings,
278
+ selector: "#{@selector} >> internal:and=#{locator.send(:selector_json)}",
279
+ )
280
+ end
281
+
282
+ def or(locator)
283
+ unless same_frame?(locator)
284
+ raise DifferentFrameError.new('or')
285
+ end
286
+ LocatorImpl.new(
287
+ frame: @frame,
288
+ timeout_settings: @timeout_settings,
289
+ selector: "#{@selector} >> internal:or=#{locator.send(:selector_json)}",
290
+ )
291
+ end
292
+
253
293
  def focus(timeout: nil)
254
294
  @frame.focus(@selector, strict: true, timeout: timeout)
255
295
  end
@@ -39,7 +39,7 @@ module Playwright
39
39
  end
40
40
 
41
41
  private def get_by_test_id_selector(test_id_attribute_name, test_id)
42
- "internal:testid=[#{test_id_attribute_name}=#{escape_for_attribute_selector(test_id, true)}]"
42
+ "internal:testid=[#{test_id_attribute_name}=#{escape_for_attribute_selector_or_regex(test_id, true)}]"
43
43
  end
44
44
 
45
45
  private def get_by_label_selector(text, exact:)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '1.32.0'
5
- COMPATIBLE_PLAYWRIGHT_VERSION = '1.32.2'
4
+ VERSION = '1.34.0'
5
+ COMPATIBLE_PLAYWRIGHT_VERSION = '1.34.3'
6
6
  end
data/lib/playwright.rb CHANGED
@@ -74,7 +74,7 @@ module Playwright
74
74
  # ...
75
75
  # end
76
76
  #
77
- # When we use this method without block, an instance of Puppeteer::Execution is returned
77
+ # When we use this method without block, an instance of Playwright::Execution is returned
78
78
  # and we *must* call execution.stop on the end.
79
79
  # The instance of playwright is available by calling execution.playwright
80
80
  module_function def create(playwright_cli_executable_path:, &block)
@@ -391,6 +391,14 @@ module Playwright
391
391
  wrap_impl(@impl.unroute(unwrap_impl(url), handler: unwrap_impl(handler)))
392
392
  end
393
393
 
394
+ #
395
+ # Performs action and waits for a `ConsoleMessage` to be logged by in the pages in the context. If predicate is provided, it passes
396
+ # `ConsoleMessage` value into the `predicate` function and waits for `predicate(message)` to return a truthy value.
397
+ # Will throw an error if the page is closed before the [`event: BrowserContext.console`] event is fired.
398
+ def expect_console_message(predicate: nil, timeout: nil, &block)
399
+ wrap_impl(@impl.expect_console_message(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
400
+ end
401
+
394
402
  #
395
403
  # Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
396
404
  # value. Will throw an error if the context closes before the event is fired. Returns the event data value.
@@ -410,8 +418,8 @@ module Playwright
410
418
  # Performs action and waits for a new `Page` to be created in the context. If predicate is provided, it passes
411
419
  # `Page` value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
412
420
  # Will throw an error if the context closes before new `Page` is created.
413
- def expect_page(predicate: nil, timeout: nil)
414
- wrap_impl(@impl.expect_page(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout)))
421
+ def expect_page(predicate: nil, timeout: nil, &block)
422
+ wrap_impl(@impl.expect_page(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
415
423
  end
416
424
 
417
425
  #
@@ -33,6 +33,12 @@ module Playwright
33
33
  wrap_impl(@impl.location)
34
34
  end
35
35
 
36
+ #
37
+ # The page that produced this console message, if any.
38
+ def page
39
+ wrap_impl(@impl.page)
40
+ end
41
+
36
42
  #
37
43
  # The text of the console message.
38
44
  def text
@@ -51,6 +51,12 @@ module Playwright
51
51
  wrap_impl(@impl.message)
52
52
  end
53
53
 
54
+ #
55
+ # The page that initiated this dialog, if available.
56
+ def page
57
+ wrap_impl(@impl.page)
58
+ end
59
+
54
60
  #
55
61
  # Returns dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
56
62
  def type
@@ -664,8 +664,13 @@ module Playwright
664
664
  # [Learn more about locators](../locators.md).
665
665
  #
666
666
  # [Learn more about locators](../locators.md).
667
- def locator(selector, has: nil, hasText: nil)
668
- wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
667
+ def locator(
668
+ selector,
669
+ has: nil,
670
+ hasNot: nil,
671
+ hasNotText: nil,
672
+ hasText: nil)
673
+ wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
669
674
  end
670
675
 
671
676
  #
@@ -241,8 +241,13 @@ module Playwright
241
241
  # The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, similar to [`method: Locator.filter`] method.
242
242
  #
243
243
  # [Learn more about locators](../locators.md).
244
- def locator(selectorOrLocator, has: nil, hasText: nil)
245
- wrap_impl(@impl.locator(unwrap_impl(selectorOrLocator), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
244
+ def locator(
245
+ selectorOrLocator,
246
+ has: nil,
247
+ hasNot: nil,
248
+ hasNotText: nil,
249
+ hasText: nil)
250
+ wrap_impl(@impl.locator(unwrap_impl(selectorOrLocator), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
246
251
  end
247
252
 
248
253
  #
@@ -10,7 +10,11 @@ module Playwright
10
10
  # When locator points to a list of elements, returns array of locators, pointing
11
11
  # to respective elements.
12
12
  #
13
- # Note that [`method: Locator.all`] does not wait for elements to match the locator, and instead immediately returns whatever is present in the page. To avoid flakiness when elements are loaded dynamically, wait for the loading to finish before calling [`method: Locator.all`].
13
+ # **NOTE**: [`method: Locator.all`] does not wait for elements to match the locator, and instead immediately returns whatever is present in the page.
14
+ #
15
+ # When the list of elements changes dynamically, [`method: Locator.all`] will produce unpredictable and flaky results.
16
+ #
17
+ # When the list of elements is stable, but loaded dynamically, wait for the full list to finish loading before calling [`method: Locator.all`].
14
18
  #
15
19
  # **Usage**
16
20
  #
@@ -46,6 +50,20 @@ module Playwright
46
50
  wrap_impl(@impl.all_text_contents)
47
51
  end
48
52
 
53
+ #
54
+ # Creates a locator that matches both this locator and the argument locator.
55
+ #
56
+ # **Usage**
57
+ #
58
+ # The following example finds a button with a specific title.
59
+ #
60
+ # ```python sync
61
+ # button = page.get_by_role("button").and_(page.getByTitle("Subscribe"))
62
+ # ```
63
+ def and(locator)
64
+ wrap_impl(@impl.and(unwrap_impl(locator)))
65
+ end
66
+
49
67
  #
50
68
  # Calls [blur](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur) on the element.
51
69
  def blur(timeout: nil)
@@ -393,8 +411,8 @@ module Playwright
393
411
  # .filter(has=page.get_by_role("button", name="column 2 button"))
394
412
  # .screenshot()
395
413
  # ```
396
- def filter(has: nil, hasText: nil)
397
- wrap_impl(@impl.filter(has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
414
+ def filter(has: nil, hasNot: nil, hasNotText: nil, hasText: nil)
415
+ wrap_impl(@impl.filter(has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
398
416
  end
399
417
 
400
418
  #
@@ -773,8 +791,13 @@ module Playwright
773
791
  # The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, similar to [`method: Locator.filter`] method.
774
792
  #
775
793
  # [Learn more about locators](../locators.md).
776
- def locator(selectorOrLocator, has: nil, hasText: nil)
777
- wrap_impl(@impl.locator(unwrap_impl(selectorOrLocator), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
794
+ def locator(
795
+ selectorOrLocator,
796
+ has: nil,
797
+ hasNot: nil,
798
+ hasNotText: nil,
799
+ hasText: nil)
800
+ wrap_impl(@impl.locator(unwrap_impl(selectorOrLocator), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
778
801
  end
779
802
 
780
803
  #
@@ -789,6 +812,25 @@ module Playwright
789
812
  wrap_impl(@impl.nth(unwrap_impl(index)))
790
813
  end
791
814
 
815
+ #
816
+ # Creates a locator that matches either of the two locators.
817
+ #
818
+ # **Usage**
819
+ #
820
+ # Consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly.
821
+ #
822
+ # ```python sync
823
+ # new_email = page.get_by_role("button", name="New")
824
+ # dialog = page.get_by_text("Confirm security settings")
825
+ # expect(new_email.or_(dialog)).to_be_visible()
826
+ # if (dialog.is_visible())
827
+ # page.get_by_role("button", name="Dismiss").click()
828
+ # new_email.click()
829
+ # ```
830
+ def or(locator)
831
+ wrap_impl(@impl.or(unwrap_impl(locator)))
832
+ end
833
+
792
834
  #
793
835
  # A page this locator belongs to.
794
836
  def page
@@ -916,8 +916,13 @@ module Playwright
916
916
  # Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
917
917
  #
918
918
  # [Learn more about locators](../locators.md).
919
- def locator(selector, has: nil, hasText: nil)
920
- wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasText: unwrap_impl(hasText)))
919
+ def locator(
920
+ selector,
921
+ has: nil,
922
+ hasNot: nil,
923
+ hasNotText: nil,
924
+ hasText: nil)
925
+ wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
921
926
  end
922
927
 
923
928
  #
@@ -57,7 +57,7 @@ module Playwright
57
57
  #
58
58
  # ```python sync
59
59
  # # Handle GET requests.
60
- # def handle_post(route):
60
+ # def handle_get(route):
61
61
  # if route.request.method != "GET":
62
62
  # route.fallback()
63
63
  # return
@@ -119,8 +119,9 @@ module Playwright
119
119
  maxRedirects: nil,
120
120
  method: nil,
121
121
  postData: nil,
122
+ timeout: nil,
122
123
  url: nil)
123
- wrap_impl(@impl.fetch(headers: unwrap_impl(headers), maxRedirects: unwrap_impl(maxRedirects), method: unwrap_impl(method), postData: unwrap_impl(postData), url: unwrap_impl(url)))
124
+ wrap_impl(@impl.fetch(headers: unwrap_impl(headers), maxRedirects: unwrap_impl(maxRedirects), method: unwrap_impl(method), postData: unwrap_impl(postData), timeout: unwrap_impl(timeout), url: unwrap_impl(url)))
124
125
  end
125
126
 
126
127
  #
@@ -47,13 +47,13 @@ module Playwright
47
47
  end
48
48
 
49
49
  # @nodoc
50
- def page=(req)
51
- wrap_impl(@impl.page=(unwrap_impl(req)))
50
+ def context=(req)
51
+ wrap_impl(@impl.context=(unwrap_impl(req)))
52
52
  end
53
53
 
54
54
  # @nodoc
55
- def context=(req)
56
- wrap_impl(@impl.context=(unwrap_impl(req)))
55
+ def page=(req)
56
+ wrap_impl(@impl.page=(unwrap_impl(req)))
57
57
  end
58
58
 
59
59
  # -- inherited from EventEmitter --
data/sig/playwright.rbs CHANGED
@@ -47,7 +47,7 @@ module Playwright
47
47
  def abort: (?errorCode: String) -> void
48
48
  def continue: (?headers: Hash[untyped, untyped], ?method: String, ?postData: (String | String | untyped), ?url: String) -> void
49
49
  def fallback: (?headers: Hash[untyped, untyped], ?method: String, ?postData: (String | String | untyped), ?url: String) -> void
50
- def fetch: (?headers: Hash[untyped, untyped], ?maxRedirects: Integer, ?method: String, ?postData: (String | String | untyped), ?url: String) -> APIResponse
50
+ def fetch: (?headers: Hash[untyped, untyped], ?maxRedirects: Integer, ?method: String, ?postData: (String | String | untyped), ?timeout: Float, ?url: String) -> APIResponse
51
51
  def fulfill: (?body: (String | String), ?contentType: String, ?headers: Hash[untyped, untyped], ?json: untyped, ?path: (String | File), ?response: APIResponse, ?status: Integer) -> void
52
52
  def request: -> Request
53
53
  end
@@ -184,7 +184,7 @@ module Playwright
184
184
  def enabled?: (String selector, ?strict: bool, ?timeout: Float) -> bool
185
185
  def hidden?: (String selector, ?strict: bool, ?timeout: Float) -> bool
186
186
  def visible?: (String selector, ?strict: bool, ?timeout: Float) -> bool
187
- def locator: (String selector, ?has: Locator, ?hasText: (String | Regexp)) -> Locator
187
+ def locator: (String selector, ?has: Locator, ?hasNot: Locator, ?hasNotText: (String | Regexp), ?hasText: (String | Regexp)) -> Locator
188
188
  def name: -> String
189
189
  def page: -> Page
190
190
  def parent_frame: -> (nil | Frame)
@@ -223,6 +223,7 @@ module Playwright
223
223
  class ConsoleMessage
224
224
  def args: -> Array[untyped]
225
225
  def location: -> Hash[untyped, untyped]
226
+ def page: -> (nil | Page)
226
227
  def text: -> String
227
228
  def type: -> String
228
229
  end
@@ -232,6 +233,7 @@ module Playwright
232
233
  def default_value: -> String
233
234
  def dismiss: -> void
234
235
  def message: -> String
236
+ def page: -> (nil | Page)
235
237
  def type: -> String
236
238
  end
237
239
 
@@ -293,7 +295,7 @@ module Playwright
293
295
  def enabled?: (String selector, ?strict: bool, ?timeout: Float) -> bool
294
296
  def hidden?: (String selector, ?strict: bool, ?timeout: Float) -> bool
295
297
  def visible?: (String selector, ?strict: bool, ?timeout: Float) -> bool
296
- def locator: (String selector, ?has: Locator, ?hasText: (String | Regexp)) -> Locator
298
+ def locator: (String selector, ?has: Locator, ?hasNot: Locator, ?hasNotText: (String | Regexp), ?hasText: (String | Regexp)) -> Locator
297
299
  def main_frame: -> Frame
298
300
  def opener: -> (nil | Page)
299
301
  def pause: -> void
@@ -382,8 +384,9 @@ module Playwright
382
384
  def offline=: (bool offline) -> void
383
385
  def storage_state: (?path: (String | File)) -> Hash[untyped, untyped]
384
386
  def unroute: ((String | Regexp | function) url, ?handler: function) -> void
387
+ def expect_console_message: (?predicate: function, ?timeout: Float) { () -> void } -> ConsoleMessage
385
388
  def expect_event: (String event, ?predicate: function, ?timeout: Float) { () -> void } -> untyped
386
- def expect_page: (?predicate: function, ?timeout: Float) -> Page
389
+ def expect_page: (?predicate: function, ?timeout: Float) { () -> void } -> Page
387
390
 
388
391
  attr_reader request: APIRequestContext
389
392
  attr_reader tracing: Tracing
@@ -434,6 +437,7 @@ module Playwright
434
437
  def all: -> Array[untyped]
435
438
  def all_inner_texts: -> Array[untyped]
436
439
  def all_text_contents: -> Array[untyped]
440
+ def and: (Locator locator) -> Locator
437
441
  def blur: (?timeout: Float) -> void
438
442
  def bounding_box: (?timeout: Float) -> (nil | Hash[untyped, untyped])
439
443
  def check: (?force: bool, ?noWaitAfter: bool, ?position: Hash[untyped, untyped], ?timeout: Float, ?trial: bool) -> void
@@ -449,7 +453,7 @@ module Playwright
449
453
  def evaluate_all: (String expression, ?arg: untyped) -> untyped
450
454
  def evaluate_handle: (String expression, ?arg: untyped, ?timeout: Float) -> JSHandle
451
455
  def fill: (String value, ?force: bool, ?noWaitAfter: bool, ?timeout: Float) -> void
452
- def filter: (?has: Locator, ?hasText: (String | Regexp)) -> Locator
456
+ def filter: (?has: Locator, ?hasNot: Locator, ?hasNotText: (String | Regexp), ?hasText: (String | Regexp)) -> Locator
453
457
  def first: -> Locator
454
458
  def focus: (?timeout: Float) -> void
455
459
  def frame_locator: (String selector) -> FrameLocator
@@ -474,8 +478,9 @@ module Playwright
474
478
  def hidden?: (?timeout: Float) -> bool
475
479
  def visible?: (?timeout: Float) -> bool
476
480
  def last: -> Locator
477
- def locator: ((String | Locator) selectorOrLocator, ?has: Locator, ?hasText: (String | Regexp)) -> Locator
481
+ def locator: ((String | Locator) selectorOrLocator, ?has: Locator, ?hasNot: Locator, ?hasNotText: (String | Regexp), ?hasText: (String | Regexp)) -> Locator
478
482
  def nth: (Integer index) -> Locator
483
+ def or: (Locator locator) -> Locator
479
484
  def page: -> Page
480
485
  def press: (String key, ?delay: Float, ?noWaitAfter: bool, ?timeout: Float) -> void
481
486
  def screenshot: (?animations: ("disabled" | "allow"), ?caret: ("hide" | "initial"), ?mask: Array[untyped], ?omitBackground: bool, ?path: (String | File), ?quality: Integer, ?scale: ("css" | "device"), ?timeout: Float, ?type: ("png" | "jpeg")) -> String
@@ -504,7 +509,7 @@ module Playwright
504
509
  def get_by_text: ((String | Regexp) text, ?exact: bool) -> Locator
505
510
  def get_by_title: ((String | Regexp) text, ?exact: bool) -> Locator
506
511
  def last: -> FrameLocator
507
- def locator: ((String | Locator) selectorOrLocator, ?has: Locator, ?hasText: (String | Regexp)) -> Locator
512
+ def locator: ((String | Locator) selectorOrLocator, ?has: Locator, ?hasNot: Locator, ?hasNotText: (String | Regexp), ?hasText: (String | Regexp)) -> Locator
508
513
  def nth: (Integer index) -> FrameLocator
509
514
  end
510
515
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playwright-ruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.32.0
4
+ version: 1.34.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-11 00:00:00.000000000 Z
11
+ date: 2023-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -401,5 +401,5 @@ requirements: []
401
401
  rubygems_version: 3.3.26
402
402
  signing_key:
403
403
  specification_version: 4
404
- summary: The Ruby binding of playwright driver 1.32.2
404
+ summary: The Ruby binding of playwright driver 1.34.3
405
405
  test_files: []