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
@@ -105,6 +105,7 @@ module Playwright
105
105
  force: nil,
106
106
  noWaitAfter: nil,
107
107
  position: nil,
108
+ scroll: nil,
108
109
  timeout: nil,
109
110
  trial: nil)
110
111
 
@@ -113,6 +114,7 @@ module Playwright
113
114
  force: force,
114
115
  noWaitAfter: noWaitAfter,
115
116
  position: position,
117
+ scroll: scroll,
116
118
  timeout: timeout,
117
119
  trial: trial)
118
120
  end
@@ -125,6 +127,7 @@ module Playwright
125
127
  modifiers: nil,
126
128
  noWaitAfter: nil,
127
129
  position: nil,
130
+ scroll: nil,
128
131
  timeout: nil,
129
132
  trial: nil,
130
133
  steps: nil)
@@ -138,6 +141,7 @@ module Playwright
138
141
  modifiers: modifiers,
139
142
  noWaitAfter: noWaitAfter,
140
143
  position: position,
144
+ scroll: scroll,
141
145
  timeout: timeout,
142
146
  trial: trial,
143
147
  steps: steps)
@@ -150,6 +154,7 @@ module Playwright
150
154
  modifiers: nil,
151
155
  noWaitAfter: nil,
152
156
  position: nil,
157
+ scroll: nil,
153
158
  timeout: nil,
154
159
  trial: nil,
155
160
  steps: nil)
@@ -162,6 +167,7 @@ module Playwright
162
167
  modifiers: modifiers,
163
168
  noWaitAfter: noWaitAfter,
164
169
  position: position,
170
+ scroll: scroll,
165
171
  timeout: timeout,
166
172
  trial: trial,
167
173
  steps: steps)
@@ -174,6 +180,7 @@ module Playwright
174
180
  def drag_to(target,
175
181
  force: nil,
176
182
  noWaitAfter: nil,
183
+ scroll: nil,
177
184
  sourcePosition: nil,
178
185
  targetPosition: nil,
179
186
  timeout: nil,
@@ -185,6 +192,7 @@ module Playwright
185
192
  target.instance_variable_get(:@selector),
186
193
  force: force,
187
194
  noWaitAfter: noWaitAfter,
195
+ scroll: scroll,
188
196
  sourcePosition: sourcePosition,
189
197
  targetPosition: targetPosition,
190
198
  timeout: timeout,
@@ -363,6 +371,7 @@ module Playwright
363
371
  modifiers: nil,
364
372
  noWaitAfter: nil,
365
373
  position: nil,
374
+ scroll: nil,
366
375
  timeout: nil,
367
376
  trial: nil)
368
377
  @frame.hover(@selector,
@@ -371,6 +380,7 @@ module Playwright
371
380
  modifiers: modifiers,
372
381
  noWaitAfter: noWaitAfter,
373
382
  position: position,
383
+ scroll: scroll,
374
384
  timeout: timeout,
375
385
  trial: trial)
376
386
  end
@@ -426,7 +436,7 @@ module Playwright
426
436
  end
427
437
  end
428
438
 
429
- def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil, _track: nil)
439
+ def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil)
430
440
  params = {
431
441
  selector: @selector,
432
442
  timeout: _timeout(timeout),
@@ -434,10 +444,6 @@ module Playwright
434
444
  params[:boxes] = boxes unless boxes.nil?
435
445
  params[:depth] = depth if depth
436
446
  params[:mode] = mode if mode
437
- if _track
438
- params.delete(:selector)
439
- params[:track] = _track
440
- end
441
447
  result = @frame.channel.send_message_to_server_result('ariaSnapshot', params.compact)
442
448
  result['snapshot']
443
449
  end
@@ -499,6 +505,7 @@ module Playwright
499
505
  modifiers: nil,
500
506
  noWaitAfter: nil,
501
507
  position: nil,
508
+ scroll: nil,
502
509
  timeout: nil,
503
510
  trial: nil)
504
511
  @frame.tap_point(@selector,
@@ -507,6 +514,7 @@ module Playwright
507
514
  modifiers: modifiers,
508
515
  noWaitAfter: noWaitAfter,
509
516
  position: position,
517
+ scroll: scroll,
510
518
  timeout: timeout,
511
519
  trial: trial)
512
520
  end
@@ -527,6 +535,7 @@ module Playwright
527
535
  force: nil,
528
536
  noWaitAfter: nil,
529
537
  position: nil,
538
+ scroll: nil,
530
539
  timeout: nil,
531
540
  trial: nil)
532
541
  @frame.uncheck(@selector,
@@ -534,10 +543,24 @@ module Playwright
534
543
  force: force,
535
544
  noWaitAfter: noWaitAfter,
536
545
  position: position,
546
+ scroll: scroll,
537
547
  timeout: timeout,
538
548
  trial: trial)
539
549
  end
540
550
 
551
+ def wait_for_function(expression, arg: nil, timeout: nil)
552
+ @frame.channel.send_message_to_server(
553
+ 'waitForFunction',
554
+ selector: @selector,
555
+ strict: true,
556
+ expression: expression,
557
+ isFunction: true,
558
+ arg: JavaScript::ValueSerializer.new(arg).serialize,
559
+ timeout: _timeout(timeout),
560
+ )
561
+ nil
562
+ end
563
+
541
564
  def wait_for(state: nil, timeout: nil)
542
565
  @frame.wait_for_selector(@selector, strict: true, state: state, timeout: timeout)
543
566
  end
@@ -39,7 +39,15 @@ 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_or_regex(test_id, true)}]"
42
+ "internal:testid=[#{encode_test_id_attribute_name(test_id_attribute_name)}=#{escape_for_attribute_selector_or_regex(test_id, true)}]"
43
+ end
44
+
45
+ private def encode_test_id_attribute_name(test_id_attribute_name)
46
+ if test_id_attribute_name.include?(',')
47
+ JSON.generate(test_id_attribute_name)
48
+ else
49
+ test_id_attribute_name
50
+ end
43
51
  end
44
52
 
45
53
  private def get_by_label_selector(text, exact:)
@@ -63,11 +63,12 @@ module Playwright
63
63
  @page.send(:channel).send_message_to_server('screencastChapter', params)
64
64
  end
65
65
 
66
- def show_actions(duration: nil, fontSize: nil, position: nil)
66
+ def show_actions(duration: nil, fontSize: nil, position: nil, cursor: nil)
67
67
  params = {}
68
68
  params[:duration] = duration if duration
69
69
  params[:fontSize] = fontSize if fontSize
70
70
  params[:position] = position if position
71
+ params[:cursor] = cursor if cursor
71
72
  @page.send(:channel).send_message_to_server('screencastShowActions', params)
72
73
  DisposableStub.new { hide_actions }
73
74
  end
@@ -85,11 +86,26 @@ module Playwright
85
86
  end
86
87
 
87
88
  private def handle_screencast_frame(event)
88
- @on_frame&.call({
89
- data: Base64.strict_decode64(event['data']),
90
- viewportWidth: event['viewportWidth'],
91
- viewportHeight: event['viewportHeight'],
92
- })
89
+ on_frame = @on_frame
90
+ Thread.new do
91
+ begin
92
+ on_frame&.call({
93
+ data: Base64.strict_decode64(event['data']),
94
+ timestamp: event['timestamp'],
95
+ viewportWidth: event['viewportWidth'],
96
+ viewportHeight: event['viewportHeight'],
97
+ })
98
+ ensure
99
+ begin
100
+ @page.send(:channel).async_send_message_to_server(
101
+ 'screencastFrameAck',
102
+ frameId: event['frameId'],
103
+ )
104
+ rescue Transport::AlreadyDisconnectedError
105
+ # The page or driver may close while a callback is running.
106
+ end
107
+ end
108
+ end
93
109
  end
94
110
  end
95
111
  end
@@ -0,0 +1,24 @@
1
+ require 'mime/types'
2
+
3
+ module Playwright
4
+ module ScreenshotUtils
5
+ module_function
6
+
7
+ def determine_type(path:, type:)
8
+ return type if type
9
+ return nil unless path
10
+
11
+ mime_type = MIME::Types.type_for(path).first
12
+ case mime_type&.content_type
13
+ when 'image/png'
14
+ 'png'
15
+ when 'image/jpeg'
16
+ 'jpeg'
17
+ when 'image/webp'
18
+ 'webp'
19
+ else
20
+ raise ArgumentError.new("path: unsupported mime type \"#{mime_type}\"")
21
+ end
22
+ end
23
+ end
24
+ end
@@ -30,7 +30,7 @@ module Playwright
30
30
  end
31
31
 
32
32
  def matches?(actual)
33
- assertions_for(actual, false).send(@method, *@args, **@kwargs)
33
+ call_assertion(actual, false)
34
34
  true
35
35
  rescue AssertionError => e
36
36
  @failure_message = e.full_message
@@ -38,7 +38,7 @@ module Playwright
38
38
  end
39
39
 
40
40
  def does_not_match?(actual)
41
- assertions_for(actual, true).send(@method, *@args, **@kwargs)
41
+ call_assertion(actual, true)
42
42
  true
43
43
  rescue AssertionError => e
44
44
  @failure_message = e.full_message
@@ -55,6 +55,16 @@ module Playwright
55
55
 
56
56
  private
57
57
 
58
+ def call_assertion(actual, is_not)
59
+ args = @args
60
+ kwargs = @kwargs
61
+ if ['to_have_attribute', 'not_to_have_attribute'].include?(@method) && args.length == 2 && !kwargs.key?(:value)
62
+ args = [args.first]
63
+ kwargs = kwargs.merge(value: @args.last)
64
+ end
65
+ assertions_for(actual, is_not).send(@method, *args, **kwargs)
66
+ end
67
+
58
68
  def assertions_for(actual, is_not)
59
69
  if actual.respond_to?(:_assertions)
60
70
  actual._assertions(::Playwright::Test.expect_timeout, is_not, nil)
@@ -23,7 +23,7 @@ module Playwright
23
23
  def match?(target_url)
24
24
  case @url
25
25
  when String
26
- joined_url == target_url || File.fnmatch?(@url, target_url)
26
+ joined_url == target_url || File.fnmatch?(joined_url, target_url)
27
27
  when Regexp
28
28
  @url.match?(target_url)
29
29
  else
@@ -32,13 +32,129 @@ module Playwright
32
32
  end
33
33
 
34
34
  private def joined_url
35
- if @base_url && !@url.start_with?('*')
36
- URI.join(@base_url, @url).to_s
35
+ normalized_url = normalize_literal_url(@url)
36
+ if @base_url && !normalized_url.start_with?('*')
37
+ normalize_literal_url(URI.join(normalize_literal_url(@base_url), normalized_url).to_s)
37
38
  else
38
- @url
39
+ normalized_url
39
40
  end
40
41
  end
41
42
 
43
+ private def normalize_literal_url(url)
44
+ match = url.match(/\A([a-z][a-z0-9+.-]*):\/\/([^\/?#]*)(.*)\z/i)
45
+ return percent_encode_literal_characters(url) unless match
46
+
47
+ scheme = match[1].downcase
48
+ authority = match[2]
49
+ suffix = percent_encode_literal_characters(match[3])
50
+
51
+ before, separator, after = authority.rpartition('@')
52
+ if separator.empty?
53
+ userinfo = nil
54
+ host_port = authority
55
+ else
56
+ userinfo = before
57
+ host_port = after
58
+ end
59
+
60
+ if host_port.start_with?('[')
61
+ host = host_port
62
+ port = nil
63
+ else
64
+ host, separator, candidate_port = host_port.rpartition(':')
65
+ if separator.empty? || candidate_port !~ /\A\d+\z/
66
+ host = host_port
67
+ port = nil
68
+ else
69
+ port = candidate_port
70
+ end
71
+ host = host.split('.').map { |label| punycode_label(label.downcase) }.join('.')
72
+ end
73
+
74
+ port = nil if (scheme == 'http' && port == '80') || (scheme == 'https' && port == '443')
75
+ normalized_authority = String.new
76
+ normalized_authority << "#{userinfo}@" if userinfo
77
+ normalized_authority << host
78
+ normalized_authority << ":#{port}" if port
79
+ "#{scheme}://#{normalized_authority}#{suffix}"
80
+ end
81
+
82
+ private def percent_encode_literal_characters(value)
83
+ value.each_char.map do |char|
84
+ if char == ' '
85
+ '%20'
86
+ elsif char.ascii_only?
87
+ char
88
+ else
89
+ char.encode(Encoding::UTF_8).bytes.map { |byte| format('%%%02X', byte) }.join
90
+ end
91
+ end.join
92
+ end
93
+
94
+ # RFC 3492 Punycode encoder for the non-ASCII URL host labels normalized by WHATWG URL.
95
+ private def punycode_label(label)
96
+ return label if label.ascii_only?
97
+
98
+ codepoints = label.codepoints
99
+ output = codepoints.select { |codepoint| codepoint < 0x80 }.map(&:chr).join
100
+ basic_length = output.length
101
+ output << '-' if basic_length > 0
102
+
103
+ handled = basic_length
104
+ n = 128
105
+ delta = 0
106
+ bias = 72
107
+ while handled < codepoints.length
108
+ next_codepoint = codepoints.select { |codepoint| codepoint >= n }.min
109
+ delta += (next_codepoint - n) * (handled + 1)
110
+ n = next_codepoint
111
+
112
+ codepoints.each do |codepoint|
113
+ delta += 1 if codepoint < n
114
+ next unless codepoint == n
115
+
116
+ q = delta
117
+ k = 36
118
+ loop do
119
+ threshold = if k <= bias
120
+ 1
121
+ elsif k >= bias + 26
122
+ 26
123
+ else
124
+ k - bias
125
+ end
126
+ break if q < threshold
127
+
128
+ output << punycode_digit(threshold + ((q - threshold) % (36 - threshold)))
129
+ q = (q - threshold) / (36 - threshold)
130
+ k += 36
131
+ end
132
+ output << punycode_digit(q)
133
+ bias = adapt_punycode_bias(delta, handled + 1, handled == basic_length)
134
+ delta = 0
135
+ handled += 1
136
+ end
137
+ delta += 1
138
+ n += 1
139
+ end
140
+ "xn--#{output}"
141
+ end
142
+
143
+ private def punycode_digit(value)
144
+ value < 26 ? (value + 97).chr : (value - 26 + 48).chr
145
+ end
146
+
147
+ private def adapt_punycode_bias(delta, points, first_time)
148
+ delta = first_time ? delta / 700 : delta / 2
149
+ delta += delta / points
150
+ k = 0
151
+ while delta > 455
152
+ delta /= 35
153
+ k += 36
154
+ end
155
+ k + ((36 * delta) / (delta + 38))
156
+ end
157
+
42
158
  private def validate_glob_pattern
43
159
  in_group = false
44
160
  escaped = false
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '1.60.0'
5
- COMPATIBLE_PLAYWRIGHT_VERSION = '1.60.0'
4
+ VERSION = '1.62.0'
5
+ COMPATIBLE_PLAYWRIGHT_VERSION = '1.62.1'
6
6
  end
@@ -12,33 +12,14 @@ module Playwright
12
12
  @registered_listeners = Set.new
13
13
  @listeners_mutex = Mutex.new
14
14
  @logs = []
15
- wait_for_event_info_before
15
+ send_wait_info(waitId: @wait_id, phase: 'before', event: @event)
16
16
  end
17
17
 
18
- private def wait_for_event_info_before
19
- @channel.async_send_message_to_server(
20
- "waitForEventInfo",
21
- {
22
- "info": {
23
- "waitId": @wait_id,
24
- "phase": "before",
25
- "event": @event,
26
- }
27
- },
28
- )
29
- end
30
-
31
- private def wait_for_event_info_after(error: nil)
32
- @channel.async_send_message_to_server(
33
- "waitForEventInfo",
34
- {
35
- "info": {
36
- "waitId": @wait_id,
37
- "phase": "after",
38
- "error": error,
39
- }.compact,
40
- },
41
- )
18
+ private def send_wait_info(params)
19
+ @channel.async_send_message_to_server('__waitInfo__', params.compact)
20
+ rescue
21
+ # Fire-and-forget. The server intentionally does not reply and this must
22
+ # not affect the API call that is being waited for.
42
23
  end
43
24
 
44
25
  def reject_on_event(emitter, event, error_or_proc, predicate: nil)
@@ -89,7 +70,7 @@ module Playwright
89
70
  cleanup
90
71
  return if @result.resolved?
91
72
  @result.fulfill(result)
92
- wait_for_event_info_after
73
+ send_wait_info(waitId: @wait_id, phase: 'after')
93
74
  end
94
75
 
95
76
  private def reject(error)
@@ -98,7 +79,7 @@ module Playwright
98
79
  klass = error.is_a?(TimeoutError) ? TimeoutError : Error
99
80
  ex = klass.new(message: "#{error.message}#{format_log_recording(@logs)}")
100
81
  @result.reject(ex)
101
- wait_for_event_info_after(error: ex)
82
+ send_wait_info(waitId: @wait_id, phase: 'after', error: ex.message)
102
83
  end
103
84
 
104
85
  # @param [Playwright::EventEmitter]
@@ -135,20 +116,7 @@ module Playwright
135
116
 
136
117
  def log(message)
137
118
  @logs << message
138
- begin
139
- @channel.async_send_message_to_server(
140
- "waitForEventInfo",
141
- {
142
- "info": {
143
- "waitId": @wait_id,
144
- "phase": "log",
145
- "message": message,
146
- },
147
- },
148
- )
149
- rescue => err
150
- # ignore
151
- end
119
+ send_wait_info(waitId: @wait_id, phase: 'log', message: message)
152
120
  end
153
121
 
154
122
  # @param logs [Array<String>]
@@ -0,0 +1,34 @@
1
+ module Playwright
2
+ # ref: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/webStorage.ts
3
+ define_api_implementation :WebStorageImpl do
4
+ # @param page [ChannelOwners::Page]
5
+ # @param kind [String] 'local' or 'session'
6
+ def initialize(page, kind)
7
+ @page = page
8
+ @kind = kind
9
+ end
10
+
11
+ def items
12
+ @page.channel.send_message_to_server('webStorageItems', kind: @kind)
13
+ end
14
+
15
+ def get_item(name)
16
+ @page.channel.send_message_to_server('webStorageGetItem', kind: @kind, name: name)
17
+ end
18
+
19
+ def set_item(name, value)
20
+ @page.channel.send_message_to_server('webStorageSetItem', kind: @kind, name: name, value: value)
21
+ nil
22
+ end
23
+
24
+ def remove_item(name)
25
+ @page.channel.send_message_to_server('webStorageRemoveItem', kind: @kind, name: name)
26
+ nil
27
+ end
28
+
29
+ def clear
30
+ @page.channel.send_message_to_server('webStorageClear', kind: @kind)
31
+ nil
32
+ end
33
+ end
34
+ end
data/lib/playwright.rb CHANGED
@@ -138,7 +138,7 @@ module Playwright
138
138
  end
139
139
  end
140
140
 
141
- # Connects to Playwright server, launched by `npx playwright launch-server --browser chromium` or `npx playwright run-server`
141
+ # Connects to Playwright server, launched by `playwright-core launch-server --browser chromium` or `playwright-core run-server`
142
142
  #
143
143
  # Playwright.connect_to_browser_server('ws://....') do |browser|
144
144
  # page = browser.new_page
@@ -186,7 +186,7 @@ module Playwright
186
186
  end
187
187
  end
188
188
 
189
- # Connects to Playwright server, launched by `npx playwright launch-server --browser _android` or `playwright._android.launchServer()`
189
+ # Connects to Playwright server, launched by `playwright-core launch-server --browser _android` or `playwright._android.launchServer()`
190
190
  #
191
191
  # Playwright.connect_to_android_server('ws://....') do |browser|
192
192
  # page = browser.new_page
@@ -292,20 +292,20 @@ module Playwright
292
292
 
293
293
  # -- inherited from EventEmitter --
294
294
  # @nodoc
295
- def on(event, callback)
296
- event_emitter_proxy.on(event, callback)
295
+ def once(event, callback)
296
+ event_emitter_proxy.once(event, callback)
297
297
  end
298
298
 
299
299
  # -- inherited from EventEmitter --
300
300
  # @nodoc
301
- def off(event, callback)
302
- event_emitter_proxy.off(event, callback)
301
+ def on(event, callback)
302
+ event_emitter_proxy.on(event, callback)
303
303
  end
304
304
 
305
305
  # -- inherited from EventEmitter --
306
306
  # @nodoc
307
- def once(event, callback)
308
- event_emitter_proxy.once(event, callback)
307
+ def off(event, callback)
308
+ event_emitter_proxy.off(event, callback)
309
309
  end
310
310
 
311
311
  private def event_emitter_proxy
@@ -55,6 +55,18 @@ module Playwright
55
55
  wrap_impl(@impl.ok)
56
56
  end
57
57
 
58
+ #
59
+ # Returns SSL and other security information. Resolves to `null` for non-HTTPS responses. For redirected requests, returns the information for the last request in the redirect chain.
60
+ def security_details
61
+ wrap_impl(@impl.security_details)
62
+ end
63
+
64
+ #
65
+ # Returns the IP address and port of the server. Resolves to `null` if the server address is not available. For redirected requests, returns the information for the last request in the redirect chain.
66
+ def server_addr
67
+ wrap_impl(@impl.server_addr)
68
+ end
69
+
58
70
  #
59
71
  # Contains the status code of the response (e.g., 200 for a success).
60
72
  def status
@@ -73,6 +85,15 @@ module Playwright
73
85
  wrap_impl(@impl.text)
74
86
  end
75
87
 
88
+ #
89
+ # Returns resource timing information for given response. For redirected requests, returns the information for the last
90
+ # request in the redirect chain. When the response is served [from the HAR file](../mock.md#replaying-from-har), timing
91
+ # information is not available and all the values are -1. Find more information at
92
+ # [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming).
93
+ def timing
94
+ wrap_impl(@impl.timing)
95
+ end
96
+
76
97
  #
77
98
  # Contains the URL of the response.
78
99
  def url
@@ -217,20 +217,20 @@ module Playwright
217
217
 
218
218
  # -- inherited from EventEmitter --
219
219
  # @nodoc
220
- def on(event, callback)
221
- event_emitter_proxy.on(event, callback)
220
+ def once(event, callback)
221
+ event_emitter_proxy.once(event, callback)
222
222
  end
223
223
 
224
224
  # -- inherited from EventEmitter --
225
225
  # @nodoc
226
- def off(event, callback)
227
- event_emitter_proxy.off(event, callback)
226
+ def on(event, callback)
227
+ event_emitter_proxy.on(event, callback)
228
228
  end
229
229
 
230
230
  # -- inherited from EventEmitter --
231
231
  # @nodoc
232
- def once(event, callback)
233
- event_emitter_proxy.once(event, callback)
232
+ def off(event, callback)
233
+ event_emitter_proxy.off(event, callback)
234
234
  end
235
235
 
236
236
  private def event_emitter_proxy