playwright-ruby-client 1.60.0 → 1.62.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -17
  3. data/documentation/docs/api/api_response.md +30 -0
  4. data/documentation/docs/api/browser_context.md +11 -3
  5. data/documentation/docs/api/browser_type.md +3 -0
  6. data/documentation/docs/api/credentials.md +136 -0
  7. data/documentation/docs/api/element_handle.md +7 -0
  8. data/documentation/docs/api/frame.md +12 -4
  9. data/documentation/docs/api/locator.md +29 -0
  10. data/documentation/docs/api/locator_assertions.md +4 -2
  11. data/documentation/docs/api/page.md +26 -2
  12. data/documentation/docs/api/playwright.md +2 -2
  13. data/documentation/docs/api/touchscreen.md +1 -1
  14. data/documentation/docs/api/web_storage.md +65 -0
  15. data/documentation/docs/article/getting_started.md +12 -11
  16. data/documentation/docs/article/guides/download_playwright_driver.md +11 -32
  17. data/documentation/docs/article/guides/launch_browser.md +5 -4
  18. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +6 -5
  19. data/documentation/docs/article/guides/rails_integration.md +72 -4
  20. data/documentation/docs/article/guides/rails_integration_with_null_driver.md +4 -3
  21. data/documentation/docs/article/guides/semi_automation.md +1 -1
  22. data/documentation/docs/article/guides/use_storage_state.md +1 -1
  23. data/documentation/docs/include/api_coverage.md +22 -0
  24. data/documentation/docusaurus.config.js +31 -0
  25. data/documentation/package.json +3 -0
  26. data/documentation/yarn.lock +159 -174
  27. data/lib/playwright/api_response_impl.rb +24 -0
  28. data/lib/playwright/channel_owners/browser_context.rb +8 -3
  29. data/lib/playwright/channel_owners/browser_type.rb +2 -1
  30. data/lib/playwright/channel_owners/element_handle.rb +14 -4
  31. data/lib/playwright/channel_owners/frame.rb +50 -17
  32. data/lib/playwright/channel_owners/page.rb +31 -10
  33. data/lib/playwright/connection.rb +16 -2
  34. data/lib/playwright/credentials_impl.rb +35 -0
  35. data/lib/playwright/errors.rb +4 -1
  36. data/lib/playwright/locator_assertions_impl.rb +14 -1
  37. data/lib/playwright/locator_impl.rb +28 -5
  38. data/lib/playwright/locator_utils.rb +9 -1
  39. data/lib/playwright/screencast.rb +22 -6
  40. data/lib/playwright/screenshot_utils.rb +24 -0
  41. data/lib/playwright/test.rb +12 -2
  42. data/lib/playwright/url_matcher.rb +120 -4
  43. data/lib/playwright/version.rb +2 -2
  44. data/lib/playwright/waiter.rb +9 -41
  45. data/lib/playwright/web_storage_impl.rb +34 -0
  46. data/lib/playwright.rb +2 -2
  47. data/lib/playwright_api/api_request_context.rb +6 -6
  48. data/lib/playwright_api/api_response.rb +21 -0
  49. data/lib/playwright_api/browser.rb +6 -6
  50. data/lib/playwright_api/browser_context.rb +27 -18
  51. data/lib/playwright_api/browser_type.rb +10 -7
  52. data/lib/playwright_api/cdp_session.rb +6 -6
  53. data/lib/playwright_api/credentials.rb +124 -0
  54. data/lib/playwright_api/dialog.rb +6 -6
  55. data/lib/playwright_api/element_handle.rb +20 -13
  56. data/lib/playwright_api/frame.rb +36 -28
  57. data/lib/playwright_api/js_handle.rb +6 -6
  58. data/lib/playwright_api/locator.rb +37 -11
  59. data/lib/playwright_api/locator_assertions.rb +6 -4
  60. data/lib/playwright_api/page.rb +55 -29
  61. data/lib/playwright_api/playwright.rb +6 -6
  62. data/lib/playwright_api/request.rb +6 -6
  63. data/lib/playwright_api/response.rb +6 -6
  64. data/lib/playwright_api/route.rb +6 -6
  65. data/lib/playwright_api/touchscreen.rb +1 -1
  66. data/lib/playwright_api/tracing.rb +6 -6
  67. data/lib/playwright_api/web_socket.rb +6 -6
  68. data/lib/playwright_api/web_storage.rb +48 -0
  69. data/lib/playwright_api/worker.rb +6 -6
  70. data/playwright.gemspec +5 -0
  71. data/sig/playwright.rbs +62 -40
  72. metadata +13 -3
@@ -39,6 +39,30 @@ module Playwright
39
39
  @headers.headers_array
40
40
  end
41
41
 
42
+ def security_details
43
+ @initializer['securityDetails']
44
+ end
45
+
46
+ def server_addr
47
+ @initializer['serverAddr']
48
+ end
49
+
50
+ def timing
51
+ response_end = @initializer['responseEndTiming']
52
+ {
53
+ 'startTime' => -1,
54
+ 'domainLookupStart' => -1,
55
+ 'domainLookupEnd' => -1,
56
+ 'connectStart' => -1,
57
+ 'secureConnectionStart' => -1,
58
+ 'connectEnd' => -1,
59
+ 'requestStart' => -1,
60
+ 'responseStart' => -1,
61
+ }.merge(@initializer['timing'] || {}).merge(
62
+ 'responseEnd' => response_end.nil? ? -1 : response_end,
63
+ )
64
+ end
65
+
42
66
  class AlreadyDisposedError < StandardError
43
67
  def initialize
44
68
  super('Response has been disposed')
@@ -5,7 +5,7 @@ module Playwright
5
5
 
6
6
  attr_accessor :browser
7
7
  attr_writer :owner_page, :options
8
- attr_reader :clock, :tracing, :request
8
+ attr_reader :clock, :tracing, :request, :credentials
9
9
 
10
10
  private def after_initialize
11
11
  @options = @initializer['options']
@@ -20,6 +20,7 @@ module Playwright
20
20
  @request = ChannelOwners::APIRequestContext.from(@initializer['requestContext'])
21
21
  @request.send(:_update_timeout_settings, @timeout_settings)
22
22
  @clock = ClockImpl.new(self)
23
+ @credentials = CredentialsImpl.new(self)
23
24
 
24
25
  @channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
25
26
  @channel.once('close', ->(_) { on_close })
@@ -461,8 +462,12 @@ module Playwright
461
462
  @channel.send_message_to_server('pause')
462
463
  end
463
464
 
464
- def storage_state(path: nil, indexedDB: nil)
465
- @channel.send_message_to_server_result('storageState', { indexedDB: indexedDB }.compact).tap do |result|
465
+ def storage_state(path: nil, indexedDB: nil, credentials: nil)
466
+ params = {
467
+ indexedDB: indexedDB,
468
+ credentials: credentials,
469
+ }.compact
470
+ @channel.send_message_to_server_result('storageState', params).tap do |result|
466
471
  if path
467
472
  File.open(path, 'w') do |f|
468
473
  f.write(JSON.dump(result))
@@ -92,11 +92,12 @@ module Playwright
92
92
  raise
93
93
  end
94
94
 
95
- def connect_over_cdp(endpointURL, headers: nil, isLocal: nil, noDefaults: nil, slowMo: nil, timeout: nil, &block)
95
+ def connect_over_cdp(endpointURL, artifactsDir: nil, headers: nil, isLocal: nil, noDefaults: nil, slowMo: nil, timeout: nil, &block)
96
96
  raise 'Connecting over CDP is only supported in Chromium.' unless name == 'chromium'
97
97
 
98
98
  params = {
99
99
  endpointURL: endpointURL,
100
+ artifactsDir: artifactsDir,
100
101
  headers: headers,
101
102
  isLocal: isLocal,
102
103
  noDefaults: noDefaults,
@@ -1,4 +1,5 @@
1
1
  require_relative './js_handle'
2
+ require_relative '../screenshot_utils'
2
3
 
3
4
  module Playwright
4
5
  module ChannelOwners
@@ -86,6 +87,7 @@ module Playwright
86
87
  modifiers: nil,
87
88
  noWaitAfter: nil,
88
89
  position: nil,
90
+ scroll: nil,
89
91
  timeout: nil,
90
92
  trial: nil)
91
93
  params = {
@@ -93,6 +95,7 @@ module Playwright
93
95
  modifiers: modifiers,
94
96
  noWaitAfter: noWaitAfter,
95
97
  position: position,
98
+ scroll: scroll,
96
99
  timeout: _timeout(timeout),
97
100
  trial: trial,
98
101
  }.compact
@@ -109,6 +112,7 @@ module Playwright
109
112
  modifiers: nil,
110
113
  noWaitAfter: nil,
111
114
  position: nil,
115
+ scroll: nil,
112
116
  timeout: nil,
113
117
  trial: nil,
114
118
  steps: nil)
@@ -121,6 +125,7 @@ module Playwright
121
125
  modifiers: modifiers,
122
126
  noWaitAfter: noWaitAfter,
123
127
  position: position,
128
+ scroll: scroll,
124
129
  timeout: _timeout(timeout),
125
130
  trial: trial,
126
131
  steps: steps,
@@ -137,6 +142,7 @@ module Playwright
137
142
  modifiers: nil,
138
143
  noWaitAfter: nil,
139
144
  position: nil,
145
+ scroll: nil,
140
146
  timeout: nil,
141
147
  trial: nil,
142
148
  steps: nil)
@@ -148,6 +154,7 @@ module Playwright
148
154
  modifiers: modifiers,
149
155
  noWaitAfter: noWaitAfter,
150
156
  position: position,
157
+ scroll: scroll,
151
158
  timeout: _timeout(timeout),
152
159
  trial: trial,
153
160
  steps: steps,
@@ -180,6 +187,7 @@ module Playwright
180
187
  modifiers: nil,
181
188
  noWaitAfter: nil,
182
189
  position: nil,
190
+ scroll: nil,
183
191
  timeout: nil,
184
192
  trial: nil)
185
193
 
@@ -188,6 +196,7 @@ module Playwright
188
196
  modifiers: modifiers,
189
197
  noWaitAfter: noWaitAfter,
190
198
  position: position,
199
+ scroll: scroll,
191
200
  timeout: _timeout(timeout),
192
201
  trial: trial,
193
202
  }.compact
@@ -263,11 +272,12 @@ module Playwright
263
272
  nil
264
273
  end
265
274
 
266
- def check(force: nil, noWaitAfter: nil, position: nil, timeout: nil, trial: nil)
275
+ def check(force: nil, noWaitAfter: nil, position: nil, scroll: nil, timeout: nil, trial: nil)
267
276
  params = {
268
277
  force: force,
269
278
  noWaitAfter: noWaitAfter,
270
279
  position: position,
280
+ scroll: scroll,
271
281
  timeout: _timeout(timeout),
272
282
  trial: trial,
273
283
  }.compact
@@ -276,11 +286,12 @@ module Playwright
276
286
  nil
277
287
  end
278
288
 
279
- def uncheck(force: nil, noWaitAfter: nil, position: nil, timeout: nil, trial: nil)
289
+ def uncheck(force: nil, noWaitAfter: nil, position: nil, scroll: nil, timeout: nil, trial: nil)
280
290
  params = {
281
291
  force: force,
282
292
  noWaitAfter: noWaitAfter,
283
293
  position: position,
294
+ scroll: scroll,
284
295
  timeout: _timeout(timeout),
285
296
  trial: trial,
286
297
  }.compact
@@ -319,12 +330,11 @@ module Playwright
319
330
  caret: caret,
320
331
  maskColor: maskColor,
321
332
  omitBackground: omitBackground,
322
- path: path,
323
333
  quality: quality,
324
334
  scale: scale,
325
335
  style: style,
326
336
  timeout: _timeout(timeout),
327
- type: type,
337
+ type: ScreenshotUtils.determine_type(path: path, type: type),
328
338
  }.compact
329
339
  if mask.is_a?(Enumerable)
330
340
  params[:mask] = mask.map do |locator|
@@ -338,6 +338,7 @@ module Playwright
338
338
  modifiers: nil,
339
339
  noWaitAfter: nil,
340
340
  position: nil,
341
+ scroll: nil,
341
342
  strict: nil,
342
343
  timeout: nil,
343
344
  trial: nil,
@@ -352,6 +353,7 @@ module Playwright
352
353
  modifiers: modifiers,
353
354
  noWaitAfter: noWaitAfter,
354
355
  position: position,
356
+ scroll: scroll,
355
357
  strict: strict,
356
358
  timeout: _timeout(timeout),
357
359
  trial: trial,
@@ -367,6 +369,7 @@ module Playwright
367
369
  target,
368
370
  force: nil,
369
371
  noWaitAfter: nil,
372
+ scroll: nil,
370
373
  sourcePosition: nil,
371
374
  strict: nil,
372
375
  targetPosition: nil,
@@ -379,6 +382,7 @@ module Playwright
379
382
  target: target,
380
383
  force: force,
381
384
  noWaitAfter: noWaitAfter,
385
+ scroll: scroll,
382
386
  sourcePosition: sourcePosition,
383
387
  strict: strict,
384
388
  targetPosition: targetPosition,
@@ -416,6 +420,7 @@ module Playwright
416
420
  modifiers: nil,
417
421
  noWaitAfter: nil,
418
422
  position: nil,
423
+ scroll: nil,
419
424
  strict: nil,
420
425
  timeout: nil,
421
426
  trial: nil,
@@ -429,6 +434,7 @@ module Playwright
429
434
  modifiers: modifiers,
430
435
  noWaitAfter: noWaitAfter,
431
436
  position: position,
437
+ scroll: scroll,
432
438
  strict: strict,
433
439
  timeout: _timeout(timeout),
434
440
  trial: trial,
@@ -445,6 +451,7 @@ module Playwright
445
451
  modifiers: nil,
446
452
  noWaitAfter: nil,
447
453
  position: nil,
454
+ scroll: nil,
448
455
  strict: nil,
449
456
  timeout: nil,
450
457
  trial: nil)
@@ -454,6 +461,7 @@ module Playwright
454
461
  modifiers: modifiers,
455
462
  noWaitAfter: noWaitAfter,
456
463
  position: position,
464
+ scroll: scroll,
457
465
  strict: strict,
458
466
  timeout: _timeout(timeout),
459
467
  trial: trial,
@@ -539,6 +547,7 @@ module Playwright
539
547
  modifiers: nil,
540
548
  noWaitAfter: nil,
541
549
  position: nil,
550
+ scroll: nil,
542
551
  strict: nil,
543
552
  timeout: nil,
544
553
  trial: nil)
@@ -548,6 +557,7 @@ module Playwright
548
557
  modifiers: modifiers,
549
558
  noWaitAfter: noWaitAfter,
550
559
  position: position,
560
+ scroll: scroll,
551
561
  strict: strict,
552
562
  timeout: _timeout(timeout),
553
563
  trial: trial,
@@ -642,6 +652,7 @@ module Playwright
642
652
  force: nil,
643
653
  noWaitAfter: nil,
644
654
  position: nil,
655
+ scroll: nil,
645
656
  strict: nil,
646
657
  timeout: nil,
647
658
  trial: nil)
@@ -651,6 +662,7 @@ module Playwright
651
662
  force: force,
652
663
  noWaitAfter: noWaitAfter,
653
664
  position: position,
665
+ scroll: scroll,
654
666
  strict: strict,
655
667
  timeout: _timeout(timeout),
656
668
  trial: trial,
@@ -665,6 +677,7 @@ module Playwright
665
677
  force: nil,
666
678
  noWaitAfter: nil,
667
679
  position: nil,
680
+ scroll: nil,
668
681
  strict: nil,
669
682
  timeout: nil,
670
683
  trial: nil)
@@ -674,6 +687,7 @@ module Playwright
674
687
  force: force,
675
688
  noWaitAfter: noWaitAfter,
676
689
  position: position,
690
+ scroll: scroll,
677
691
  strict: strict,
678
692
  timeout: _timeout(timeout),
679
693
  trial: trial,
@@ -725,25 +739,44 @@ module Playwright
725
739
  .serialize
726
740
  end
727
741
 
728
- result = @channel.send_message_to_server_result(
729
- title, # title
730
- "expect", # method
731
- { # params
732
- selector: selector,
733
- expression: expression,
734
- **options,
735
- }.compact
736
- )
737
-
738
- if result.key?('received')
739
- if result['received'].is_a?(Hash) && result['received'].key?('value')
740
- result['received']['value'] = JavaScript::ValueParser.new(result['received']['value']).parse
741
- elsif !result['received'].is_a?(Hash)
742
- result['received'] = JavaScript::ValueParser.new(result['received']).parse
742
+ is_not = options[:isNot] || false
743
+
744
+ # Since Playwright 1.61, the `expect` command resolves on a successful
745
+ # match and rejects with FrameExpectErrorDetails on a mismatch/timeout.
746
+ begin
747
+ @channel.send_message_to_server_result(
748
+ title, # title
749
+ "expect", # method
750
+ { # params
751
+ selector: selector,
752
+ expression: expression,
753
+ **options,
754
+ }.compact
755
+ )
756
+ { 'matches' => !is_not }
757
+ rescue ::Playwright::Error => err
758
+ details = err.details || {}
759
+ received = details['received']
760
+ if received.is_a?(Hash)
761
+ received = received.dup
762
+ if received.key?('value')
763
+ received['value'] = JavaScript::ValueParser.new(received['value']).parse
764
+ end
743
765
  end
744
- end
745
766
 
746
- result
767
+ error_message =
768
+ if details['customErrorMessage']
769
+ "Error: #{details['customErrorMessage']}"
770
+ end
771
+
772
+ {
773
+ 'matches' => is_not,
774
+ 'received' => received,
775
+ 'log' => err.raw_log,
776
+ 'timedOut' => details['timedOut'],
777
+ 'errorMessage' => error_message,
778
+ }.compact
779
+ end
747
780
  end
748
781
 
749
782
  private def drop_payload_params(payload)
@@ -1,5 +1,6 @@
1
1
  require 'base64'
2
2
  require_relative '../locator_utils'
3
+ require_relative '../screenshot_utils'
3
4
 
4
5
  module Playwright
5
6
  # @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_page.py
@@ -86,6 +87,14 @@ module Playwright
86
87
  :viewport_size,
87
88
  :main_frame
88
89
 
90
+ def local_storage
91
+ @local_storage ||= WebStorageImpl.new(self, 'local')
92
+ end
93
+
94
+ def session_storage
95
+ @session_storage ||= WebStorageImpl.new(self, 'session')
96
+ end
97
+
89
98
  private def on_frame_attached(frame)
90
99
  frame.send(:update_page_from_page, self)
91
100
  @frames << frame
@@ -475,7 +484,7 @@ module Playwright
475
484
  type: nil)
476
485
 
477
486
  params = {
478
- type: type,
487
+ type: ScreenshotUtils.determine_type(path: path, type: type),
479
488
  quality: quality,
480
489
  fullPage: fullPage,
481
490
  clip: clip,
@@ -513,13 +522,15 @@ module Playwright
513
522
  end
514
523
  if @owned_context
515
524
  @owned_context.close
525
+ elsif runBeforeUnload
526
+ @channel.send_message_to_server('runBeforeUnload')
516
527
  else
517
- options = { runBeforeUnload: runBeforeUnload }.compact
528
+ options = { reason: reason }.compact
518
529
  @channel.send_message_to_server('close', options)
519
530
  end
520
531
  nil
521
532
  rescue => err
522
- raise if !target_closed_error?(err) || !runBeforeUnload
533
+ raise if !target_closed_error?(err) || runBeforeUnload
523
534
  end
524
535
 
525
536
  def closed?
@@ -535,6 +546,7 @@ module Playwright
535
546
  modifiers: nil,
536
547
  noWaitAfter: nil,
537
548
  position: nil,
549
+ scroll: nil,
538
550
  strict: nil,
539
551
  timeout: nil,
540
552
  trial: nil,
@@ -549,6 +561,7 @@ module Playwright
549
561
  modifiers: modifiers,
550
562
  noWaitAfter: noWaitAfter,
551
563
  position: position,
564
+ scroll: scroll,
552
565
  strict: strict,
553
566
  timeout: timeout,
554
567
  trial: trial,
@@ -561,6 +574,7 @@ module Playwright
561
574
  target,
562
575
  force: nil,
563
576
  noWaitAfter: nil,
577
+ scroll: nil,
564
578
  sourcePosition: nil,
565
579
  strict: nil,
566
580
  targetPosition: nil,
@@ -573,6 +587,7 @@ module Playwright
573
587
  target,
574
588
  force: force,
575
589
  noWaitAfter: noWaitAfter,
590
+ scroll: scroll,
576
591
  sourcePosition: sourcePosition,
577
592
  strict: strict,
578
593
  targetPosition: targetPosition,
@@ -590,6 +605,7 @@ module Playwright
590
605
  modifiers: nil,
591
606
  noWaitAfter: nil,
592
607
  position: nil,
608
+ scroll: nil,
593
609
  strict: nil,
594
610
  timeout: nil,
595
611
  trial: nil,
@@ -602,6 +618,7 @@ module Playwright
602
618
  modifiers: modifiers,
603
619
  noWaitAfter: noWaitAfter,
604
620
  position: position,
621
+ scroll: scroll,
605
622
  strict: strict,
606
623
  timeout: timeout,
607
624
  trial: trial,
@@ -615,6 +632,7 @@ module Playwright
615
632
  modifiers: nil,
616
633
  noWaitAfter: nil,
617
634
  position: nil,
635
+ scroll: nil,
618
636
  strict: nil,
619
637
  timeout: nil,
620
638
  trial: nil)
@@ -624,6 +642,7 @@ module Playwright
624
642
  modifiers: modifiers,
625
643
  noWaitAfter: noWaitAfter,
626
644
  position: position,
645
+ scroll: scroll,
627
646
  strict: strict,
628
647
  timeout: timeout,
629
648
  trial: trial,
@@ -680,16 +699,12 @@ module Playwright
680
699
  @channel.send_message_to_server('hideHighlight')
681
700
  end
682
701
 
683
- def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil, _track: nil)
702
+ def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil)
684
703
  params = { selector: 'body' }
685
704
  params[:timeout] = @timeout_settings.timeout(timeout)
686
705
  params[:boxes] = boxes unless boxes.nil?
687
706
  params[:depth] = depth if depth
688
707
  params[:mode] = mode if mode
689
- if _track
690
- params.delete(:selector)
691
- params[:track] = _track
692
- end
693
708
  result = @main_frame.channel.send_message_to_server_result('ariaSnapshot', params)
694
709
  result['snapshot']
695
710
  end
@@ -738,6 +753,7 @@ module Playwright
738
753
  modifiers: nil,
739
754
  noWaitAfter: nil,
740
755
  position: nil,
756
+ scroll: nil,
741
757
  strict: nil,
742
758
  timeout: nil,
743
759
  trial: nil)
@@ -747,6 +763,7 @@ module Playwright
747
763
  modifiers: modifiers,
748
764
  noWaitAfter: noWaitAfter,
749
765
  position: position,
766
+ scroll: scroll,
750
767
  strict: strict,
751
768
  timeout: timeout,
752
769
  trial: trial,
@@ -828,6 +845,7 @@ module Playwright
828
845
  force: nil,
829
846
  noWaitAfter: nil,
830
847
  position: nil,
848
+ scroll: nil,
831
849
  strict: nil,
832
850
  timeout: nil,
833
851
  trial: nil)
@@ -837,6 +855,7 @@ module Playwright
837
855
  force: force,
838
856
  noWaitAfter: noWaitAfter,
839
857
  position: position,
858
+ scroll: scroll,
840
859
  strict: strict,
841
860
  timeout: timeout,
842
861
  trial: trial)
@@ -847,6 +866,7 @@ module Playwright
847
866
  force: nil,
848
867
  noWaitAfter: nil,
849
868
  position: nil,
869
+ scroll: nil,
850
870
  strict: nil,
851
871
  timeout: nil,
852
872
  trial: nil)
@@ -856,6 +876,7 @@ module Playwright
856
876
  force: force,
857
877
  noWaitAfter: noWaitAfter,
858
878
  position: position,
879
+ scroll: scroll,
859
880
  strict: strict,
860
881
  timeout: timeout,
861
882
  trial: trial)
@@ -952,8 +973,8 @@ module Playwright
952
973
  @main_frame.locator(result['selector'])
953
974
  end
954
975
 
955
- def snapshot_for_ai(timeout: nil, depth: nil, boxes: nil, _track: nil)
956
- aria_snapshot(mode: 'ai', timeout: timeout, depth: depth, boxes: boxes, _track: _track)
976
+ def snapshot_for_ai(timeout: nil, depth: nil, boxes: nil)
977
+ aria_snapshot(mode: 'ai', timeout: timeout, depth: depth, boxes: boxes)
957
978
  end
958
979
 
959
980
  def _assertions(timeout, is_not, message)
@@ -74,14 +74,25 @@ module Playwright
74
74
  end
75
75
 
76
76
  def async_send_message_to_server(guid, method, params, metadata: nil)
77
+ if method == '__waitInfo__' && @closed_error
78
+ return Concurrent::Promises.fulfilled_future(nil)
79
+ end
77
80
  return if @closed_error
78
81
 
79
82
  callback = Concurrent::Promises.resolvable_future
83
+ fire_and_forget = method == '__waitInfo__'
80
84
 
81
85
  with_generated_id do |id|
82
86
  # register callback promise object first.
83
87
  # @see https://github.com/YusukeIwaki/puppeteer-ruby/pull/34
84
- @callbacks_mutex.synchronize { @callbacks[id] = callback }
88
+ @callbacks_mutex.synchronize { @callbacks[id] = callback } unless fire_and_forget
89
+
90
+ wire_params = params.dup
91
+ timeout = if wire_params.key?(:timeout)
92
+ wire_params.delete(:timeout)
93
+ elsif wire_params.key?('timeout')
94
+ wire_params.delete('timeout')
95
+ end
85
96
 
86
97
  _metadata = {}
87
98
  frames = []
@@ -95,13 +106,14 @@ module Playwright
95
106
  _metadata[:title] = metadata[:title]
96
107
  end
97
108
  end
109
+ _metadata[:timeout] = timeout unless timeout.nil?
98
110
  _metadata.compact!
99
111
 
100
112
  message = {
101
113
  id: id,
102
114
  guid: guid,
103
115
  method: method,
104
- params: replace_channels_with_guids(params),
116
+ params: replace_channels_with_guids(wire_params),
105
117
  metadata: _metadata,
106
118
  }
107
119
 
@@ -112,6 +124,7 @@ module Playwright
112
124
  callback.reject(err)
113
125
  raise unless err.is_a?(Transport::AlreadyDisconnectedError)
114
126
  end
127
+ callback.fulfill(nil) if fire_and_forget
115
128
 
116
129
  if @tracing_count > 0 && !frames.empty? && guid != 'localUtils' && !remote?
117
130
  @local_utils.add_stack_to_tracing_no_reply(id, frames)
@@ -168,6 +181,7 @@ module Playwright
168
181
  if error && !msg['result']
169
182
  parsed_error = ::Playwright::Error.parse(error['error'])
170
183
  parsed_error.log = msg['log']
184
+ parsed_error.details = msg['errorDetails']
171
185
  callback.reject(parsed_error)
172
186
  else
173
187
  result = replace_guids_with_channels(msg['result'])
@@ -0,0 +1,35 @@
1
+ module Playwright
2
+ # ref: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/credentials.ts
3
+ define_api_implementation :CredentialsImpl do
4
+ # @param browser_context [ChannelOwners::BrowserContext]
5
+ def initialize(browser_context)
6
+ @browser_context = browser_context
7
+ end
8
+
9
+ def install
10
+ @browser_context.channel.send_message_to_server('credentialsInstall')
11
+ nil
12
+ end
13
+
14
+ def create(rpId, id: nil, userHandle: nil, privateKey: nil, publicKey: nil)
15
+ params = {
16
+ rpId: rpId,
17
+ id: id,
18
+ userHandle: userHandle,
19
+ privateKey: privateKey,
20
+ publicKey: publicKey,
21
+ }.compact
22
+ @browser_context.channel.send_message_to_server('credentialsCreate', params)
23
+ end
24
+
25
+ def get(id: nil, rpId: nil)
26
+ params = { id: id, rpId: rpId }.compact
27
+ @browser_context.channel.send_message_to_server('credentialsGet', params)
28
+ end
29
+
30
+ def delete(id)
31
+ @browser_context.channel.send_message_to_server('credentialsDelete', id: id)
32
+ nil
33
+ end
34
+ end
35
+ end
@@ -31,10 +31,13 @@ module Playwright
31
31
  @stack = stack
32
32
  end
33
33
 
34
- attr_reader :name, :message, :stack
34
+ attr_reader :name, :message, :stack, :raw_log
35
+ # Error details for `expect` failures (received value, timedOut, customErrorMessage).
36
+ attr_accessor :details
35
37
 
36
38
  def log=(log)
37
39
  return unless log
40
+ @raw_log = log
38
41
  format_call_log = log.join("\n - ")
39
42
  @message = "#{@message}\nCall log:\n#{format_call_log}\n"
40
43
  end
@@ -214,7 +214,20 @@ module Playwright
214
214
  end
215
215
  _define_negation :to_have_accessible_error_message
216
216
 
217
- def to_have_attribute(name, value, ignoreCase: nil, timeout: nil)
217
+ def to_have_attribute(name, value: nil, ignoreCase: nil, timeout: nil)
218
+ if value.nil?
219
+ return expect_impl(
220
+ 'to.have.attribute',
221
+ {
222
+ expressionArg: name,
223
+ timeout: timeout,
224
+ },
225
+ nil,
226
+ 'Locator expected to have attribute',
227
+ 'Expect "to_have_attribute"',
228
+ )
229
+ end
230
+
218
231
  expected_text = to_expected_text_values([value], ignore_case: ignoreCase)
219
232
  expect_impl(
220
233
  "to.have.attribute.value",