playwright-ruby-client 1.16.0 → 1.17.1

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/api_request.md +7 -0
  3. data/documentation/docs/api/api_request_context.md +137 -0
  4. data/documentation/docs/api/api_response.md +90 -0
  5. data/documentation/docs/api/browser_context.md +4 -0
  6. data/documentation/docs/api/element_handle.md +2 -3
  7. data/documentation/docs/api/frame.md +30 -0
  8. data/documentation/docs/api/frame_locator.md +70 -0
  9. data/documentation/docs/api/locator.md +17 -2
  10. data/documentation/docs/api/page.md +33 -3
  11. data/documentation/docs/api/request.md +3 -3
  12. data/documentation/docs/api/selectors.md +1 -1
  13. data/documentation/docs/api/tracing.md +2 -2
  14. data/documentation/docs/include/api_coverage.md +42 -12
  15. data/lib/playwright/api_response_impl.rb +73 -0
  16. data/lib/playwright/channel.rb +1 -1
  17. data/lib/playwright/channel_owners/api_request_context.rb +232 -0
  18. data/lib/playwright/channel_owners/artifact.rb +1 -6
  19. data/lib/playwright/channel_owners/browser.rb +6 -8
  20. data/lib/playwright/channel_owners/browser_context.rb +3 -4
  21. data/lib/playwright/channel_owners/browser_type.rb +0 -1
  22. data/lib/playwright/channel_owners/fetch_request.rb +2 -0
  23. data/lib/playwright/channel_owners/frame.rb +10 -6
  24. data/lib/playwright/channel_owners/page.rb +17 -10
  25. data/lib/playwright/connection.rb +9 -0
  26. data/lib/playwright/frame_locator_impl.rb +49 -0
  27. data/lib/playwright/locator_impl.rb +13 -5
  28. data/lib/playwright/tracing_impl.rb +6 -9
  29. data/lib/playwright/version.rb +2 -2
  30. data/lib/playwright/video.rb +3 -0
  31. data/lib/playwright.rb +2 -1
  32. data/lib/playwright_api/android_device.rb +4 -4
  33. data/lib/playwright_api/api_request.rb +18 -0
  34. data/lib/playwright_api/api_request_context.rb +11 -8
  35. data/lib/playwright_api/api_response.rb +68 -0
  36. data/lib/playwright_api/browser_context.rb +10 -5
  37. data/lib/playwright_api/element_handle.rb +2 -3
  38. data/lib/playwright_api/frame.rb +26 -1
  39. data/lib/playwright_api/frame_locator.rb +51 -0
  40. data/lib/playwright_api/locator.rb +12 -2
  41. data/lib/playwright_api/page.rb +34 -4
  42. data/lib/playwright_api/playwright.rb +9 -4
  43. data/lib/playwright_api/selectors.rb +2 -2
  44. data/lib/playwright_api/tracing.rb +4 -4
  45. data/playwright.gemspec +1 -1
  46. metadata +14 -6
@@ -0,0 +1,73 @@
1
+ module Playwright
2
+ define_api_implementation :APIResponseImpl do
3
+ include Utils::Errors::SafeCloseError
4
+
5
+ # @params context [APIRequestContext]
6
+ # @params initializer [Hash]
7
+ def initialize(context, initializer)
8
+ @request = context
9
+ @initializer = initializer
10
+ @headers = RawHeaders.new(initializer['headers'])
11
+ end
12
+
13
+ def to_s
14
+ "#<APIResponse url=#{url} status=#{status} status_text=#{status_text}>"
15
+ end
16
+
17
+ def url
18
+ @initializer['url']
19
+ end
20
+
21
+ def ok
22
+ (200...300).include?(status)
23
+ end
24
+ alias_method :ok?, :ok
25
+
26
+ def status
27
+ @initializer['status']
28
+ end
29
+
30
+ def status_text
31
+ @initializer['statusText']
32
+ end
33
+
34
+ def headers
35
+ @headers.headers
36
+ end
37
+
38
+ def headers_array
39
+ @headers.headers_array
40
+ end
41
+
42
+ class AlreadyDisposedError < StandardError
43
+ def initialize
44
+ super('Response has been disposed')
45
+ end
46
+ end
47
+
48
+ def body
49
+ binary = @request.channel.send_message_to_server("fetchResponseBody", fetchUid: fetch_uid)
50
+ raise AlreadyDisposedError.new unless binary
51
+ Base64.strict_decode64(binary)
52
+ rescue => err
53
+ if safe_close_error?(err)
54
+ raise AlreadyDisposedError.new
55
+ else
56
+ raise
57
+ end
58
+ end
59
+ alias_method :text, :body
60
+
61
+ def json
62
+ JSON.parse(text)
63
+ end
64
+
65
+ def dispose
66
+ @request.channel.send_message_to_server("disposeAPIResponse", fetchUid: fetch_uid)
67
+ end
68
+
69
+ private def fetch_uid
70
+ @initializer['fetchUid']
71
+ end
72
+ end
73
+ end
@@ -71,7 +71,7 @@ module Playwright
71
71
  {
72
72
  apiName: api_name,
73
73
  stack: stacks.map do |loc|
74
- { file: loc.absolute_path, line: loc.lineno, function: loc.label }
74
+ { file: loc.absolute_path || '', line: loc.lineno, function: loc.label }
75
75
  end,
76
76
  }
77
77
  end
@@ -1,4 +1,236 @@
1
+ require 'base64'
2
+
1
3
  module Playwright
2
4
  define_channel_owner :APIRequestContext do
5
+ def dispose
6
+ @channel.send_message_to_server('dispose')
7
+ end
8
+
9
+ def delete(
10
+ url,
11
+ data: nil,
12
+ failOnStatusCode: nil,
13
+ form: nil,
14
+ headers: nil,
15
+ ignoreHTTPSErrors: nil,
16
+ multipart: nil,
17
+ params: nil,
18
+ timeout: nil)
19
+ fetch(
20
+ url,
21
+ method: 'DELETE',
22
+ data: data,
23
+ failOnStatusCode: failOnStatusCode,
24
+ form: form,
25
+ headers: headers,
26
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
27
+ multipart: multipart,
28
+ params: params,
29
+ timeout: timeout,
30
+ )
31
+ end
32
+
33
+ def head(
34
+ url,
35
+ failOnStatusCode: nil,
36
+ headers: nil,
37
+ ignoreHTTPSErrors: nil,
38
+ params: nil,
39
+ timeout: nil)
40
+ fetch(
41
+ url,
42
+ method: 'HEAD',
43
+ failOnStatusCode: failOnStatusCode,
44
+ headers: headers,
45
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
46
+ params: params,
47
+ timeout: timeout,
48
+ )
49
+ end
50
+
51
+ def get(
52
+ url,
53
+ failOnStatusCode: nil,
54
+ headers: nil,
55
+ ignoreHTTPSErrors: nil,
56
+ params: nil,
57
+ timeout: nil)
58
+ fetch(
59
+ url,
60
+ method: 'GET',
61
+ failOnStatusCode: failOnStatusCode,
62
+ headers: headers,
63
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
64
+ params: params,
65
+ timeout: timeout,
66
+ )
67
+ end
68
+
69
+ def patch(
70
+ url,
71
+ data: nil,
72
+ failOnStatusCode: nil,
73
+ form: nil,
74
+ headers: nil,
75
+ ignoreHTTPSErrors: nil,
76
+ multipart: nil,
77
+ params: nil,
78
+ timeout: nil)
79
+ fetch(
80
+ url,
81
+ method: 'PATCH',
82
+ data: data,
83
+ failOnStatusCode: failOnStatusCode,
84
+ form: form,
85
+ headers: headers,
86
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
87
+ multipart: multipart,
88
+ params: params,
89
+ timeout: timeout,
90
+ )
91
+ end
92
+
93
+ def put(
94
+ url,
95
+ data: nil,
96
+ failOnStatusCode: nil,
97
+ form: nil,
98
+ headers: nil,
99
+ ignoreHTTPSErrors: nil,
100
+ multipart: nil,
101
+ params: nil,
102
+ timeout: nil)
103
+ fetch(
104
+ url,
105
+ method: 'PUT',
106
+ data: data,
107
+ failOnStatusCode: failOnStatusCode,
108
+ form: form,
109
+ headers: headers,
110
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
111
+ multipart: multipart,
112
+ params: params,
113
+ timeout: timeout,
114
+ )
115
+ end
116
+
117
+ def post(
118
+ url,
119
+ data: nil,
120
+ failOnStatusCode: nil,
121
+ form: nil,
122
+ headers: nil,
123
+ ignoreHTTPSErrors: nil,
124
+ multipart: nil,
125
+ params: nil,
126
+ timeout: nil)
127
+ fetch(
128
+ url,
129
+ method: 'POST',
130
+ data: data,
131
+ failOnStatusCode: failOnStatusCode,
132
+ form: form,
133
+ headers: headers,
134
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
135
+ multipart: multipart,
136
+ params: params,
137
+ timeout: timeout,
138
+ )
139
+ end
140
+
141
+ def fetch(
142
+ urlOrRequest,
143
+ data: nil,
144
+ failOnStatusCode: nil,
145
+ form: nil,
146
+ headers: nil,
147
+ ignoreHTTPSErrors: nil,
148
+ method: nil,
149
+ multipart: nil,
150
+ params: nil,
151
+ timeout: nil)
152
+
153
+ if [ChannelOwners::Request, String].none? { |type| urlOrRequest.is_a?(type) }
154
+ raise ArgumentError.new("First argument must be either URL string or Request")
155
+ end
156
+ if [data, form, multipart].compact.count > 1
157
+ raise ArgumentError.new("Only one of 'data', 'form' or 'multipart' can be specified")
158
+ end
159
+
160
+ request = urlOrRequest.is_a?(ChannelOwners::Request) ? urlOrRequest : nil
161
+ headers_obj = headers || request&.headers
162
+ fetch_params = {
163
+ url: request&.url || urlOrRequest,
164
+ params: object_to_array(params),
165
+ method: method || request&.method || 'GET',
166
+ headers: headers_obj ? HttpHeaders.new(headers_obj).as_serialized : nil,
167
+ }
168
+
169
+ json_data = nil
170
+ form_data = nil
171
+ multipart_data = nil
172
+ post_data_buffer = nil
173
+ if data
174
+ case data
175
+ when String
176
+ if headers_obj&.any? { |key, value| key.downcase == 'content-type' && value == 'application/json' }
177
+ json_data = data
178
+ else
179
+ post_data_buffer = data
180
+ end
181
+ when Hash, Array, Numeric, true, false
182
+ json_data = data
183
+ else
184
+ raise ArgumentError.new("Unsupported 'data' type: #{data.class}")
185
+ end
186
+ elsif form
187
+ form_data = object_to_array(form)
188
+ elsif multipart
189
+ multipart_data = multipart.map do |name, value|
190
+ if file_payload?(value)
191
+ { name: name, file: file_payload_to_json(value) }
192
+ else
193
+ { name: name, value: value.to_s }
194
+ end
195
+ end
196
+ end
197
+
198
+ if !json_data && !form_data && !multipart_data
199
+ post_data_buffer ||= request&.post_data_buffer
200
+ end
201
+ if post_data_buffer
202
+ fetch_params[:postData] = Base64.strict_encode64(post_data_buffer)
203
+ end
204
+
205
+ fetch_params[:jsonData] = json_data
206
+ fetch_params[:formData] = form_data
207
+ fetch_params[:multipartData] = multipart_data
208
+ fetch_params[:timeout] = timeout
209
+ fetch_params[:failOnStatusCode] = failOnStatusCode
210
+ fetch_params[:ignoreHTTPSErrors] = ignoreHTTPSErrors
211
+ fetch_params.compact!
212
+ response = @channel.send_message_to_server('fetch', fetch_params)
213
+
214
+ APIResponseImpl.new(self, response)
215
+ end
216
+
217
+ private def file_payload?(value)
218
+ value.is_a?(Hash) &&
219
+ %w(name mimeType buffer).all? { |key| value.has_key?(key) || value.has_key?(key.to_sym) }
220
+ end
221
+
222
+ private def file_payload_to_json(payload)
223
+ {
224
+ name: payload[:name] || payload['name'],
225
+ mimeType: payload[:mimeType] || payload['mimeType'],
226
+ buffer: Base64.strict_encode64(payload[:buffer] || payload['buffer'])
227
+ }
228
+ end
229
+
230
+ private def object_to_array(hash)
231
+ hash&.map do |key, value|
232
+ { name: key, value: value.to_s }
233
+ end
234
+ end
3
235
  end
4
236
  end
@@ -1,14 +1,13 @@
1
1
  module Playwright
2
2
  define_channel_owner :Artifact do
3
3
  private def after_initialize
4
- @remote = false
5
4
  @absolute_path = @initializer['absolutePath']
6
5
  end
7
6
 
8
7
  attr_reader :absolute_path
9
8
 
10
9
  def path_after_finished
11
- if @remote
10
+ if @connection.remote?
12
11
  raise "Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
13
12
  end
14
13
  @channel.send_message_to_server('pathAfterFinished')
@@ -30,9 +29,5 @@ module Playwright
30
29
  def cancel
31
30
  @channel.send_message_to_server('cancel')
32
31
  end
33
-
34
- private def update_as_remote
35
- @remote = true
36
- end
37
32
  end
38
33
  end
@@ -7,7 +7,7 @@ module Playwright
7
7
  private def after_initialize
8
8
  @connected = true
9
9
  @closed_or_closing = false
10
- @remote = false
10
+ @should_close_connection_on_close = false
11
11
 
12
12
  @contexts = Set.new
13
13
  @channel.on('close', method(:on_close))
@@ -58,6 +58,9 @@ module Playwright
58
58
  return if @closed_or_closing
59
59
  @closed_or_closing = true
60
60
  @channel.send_message_to_server('close')
61
+ if @should_close_connection_on_close
62
+ @connection.stop
63
+ end
61
64
  nil
62
65
  rescue => err
63
66
  raise unless safe_close_error?(err)
@@ -99,13 +102,8 @@ module Playwright
99
102
  @contexts << context
100
103
  end
101
104
 
102
- # called from BrowserType#connectOverCDP
103
- private def update_as_remote
104
- @remote = true
105
- end
106
-
107
- private def remote?
108
- @remote
105
+ private def should_close_connection_on_close!
106
+ @should_close_connection_on_close = true
109
107
  end
110
108
 
111
109
  # called from BrowserContext#on_close with send(:remove_context), so keep private.
@@ -4,7 +4,7 @@ module Playwright
4
4
  include Utils::Errors::SafeCloseError
5
5
  attr_accessor :browser
6
6
  attr_writer :owner_page, :options
7
- attr_reader :tracing
7
+ attr_reader :tracing, :request
8
8
 
9
9
  private def after_initialize
10
10
  @pages = Set.new
@@ -15,6 +15,8 @@ module Playwright
15
15
  @background_pages = Set.new
16
16
 
17
17
  @tracing = TracingImpl.new(@channel, self)
18
+ @request = ChannelOwners::APIRequestContext.from(@initializer['APIRequestContext'])
19
+
18
20
  @channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
19
21
  @channel.once('close', ->(_) { on_close })
20
22
  @channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
@@ -276,9 +278,6 @@ module Playwright
276
278
  def close
277
279
  if @options && @options.key?(:recordHar)
278
280
  har = ChannelOwners::Artifact.from(@channel.send_message_to_server('harExport'))
279
- if @browser.send(:remote?)
280
- har.update_as_remote
281
- end
282
281
  har.save_as(@options[:recordHar][:path])
283
282
  har.delete
284
283
  end
@@ -54,7 +54,6 @@ module Playwright
54
54
 
55
55
  result = @channel.send_message_to_server_result('connectOverCDP', params)
56
56
  browser = ChannelOwners::Browser.from(result['browser'])
57
- browser.send(:update_as_remote)
58
57
 
59
58
  if result['defaultContext']
60
59
  context = ChannelOwners::BrowserContext.from(result['defaultContext'])
@@ -1,3 +1,5 @@
1
+ require_relative './api_request_context'
2
+
1
3
  module Playwright
2
4
  module ChannelOwners
3
5
  class FetchRequest < APIRequestContext
@@ -110,8 +110,8 @@ module Playwright
110
110
  def wait_for_load_state(state: nil, timeout: nil)
111
111
  option_state = state || 'load'
112
112
  option_timeout = timeout || @page.send(:timeout_settings).navigation_timeout
113
- unless %w(load domcontentloaded networkidle).include?(option_state)
114
- raise ArgumentError.new('state: expected one of (load|domcontentloaded|networkidle)')
113
+ unless %w(load domcontentloaded networkidle commit).include?(option_state)
114
+ raise ArgumentError.new('state: expected one of (load|domcontentloaded|networkidle|commit)')
115
115
  end
116
116
  if @load_states.include?(option_state)
117
117
  return
@@ -191,10 +191,6 @@ module Playwright
191
191
  @channel.send_message_to_server('isVisible', params)
192
192
  end
193
193
 
194
- def locator(selector)
195
- LocatorImpl.new(frame: self, timeout_settings: @page.send(:timeout_settings), selector: selector)
196
- end
197
-
198
194
  def dispatch_event(selector, type, eventInit: nil, strict: nil, timeout: nil)
199
195
  params = {
200
196
  selector: selector,
@@ -404,6 +400,14 @@ module Playwright
404
400
  nil
405
401
  end
406
402
 
403
+ def locator(selector)
404
+ LocatorImpl.new(frame: self, timeout_settings: @page.send(:timeout_settings), selector: selector)
405
+ end
406
+
407
+ def frame_locator(selector)
408
+ FrameLocatorImpl.new(frame: self, timeout_settings: @page.send(:timeout_settings), frame_selector: selector)
409
+ end
410
+
407
411
  def focus(selector, strict: nil, timeout: nil)
408
412
  params = { selector: selector, strict: strict, timeout: timeout }.compact
409
413
  @channel.send_message_to_server('focus', params)
@@ -138,9 +138,6 @@ module Playwright
138
138
 
139
139
  private def on_download(params)
140
140
  artifact = ChannelOwners::Artifact.from(params['artifact'])
141
- if @browser_context.browser.send(:remote?)
142
- artifact.update_as_remote
143
- end
144
141
  download = DownloadImpl.new(
145
142
  page: self,
146
143
  url: params['url'],
@@ -152,9 +149,6 @@ module Playwright
152
149
 
153
150
  private def on_video(params)
154
151
  artifact = ChannelOwners::Artifact.from(params['artifact'])
155
- if @browser_context.browser.send(:remote?)
156
- artifact.update_as_remote
157
- end
158
152
  video.send(:set_artifact, artifact)
159
153
  end
160
154
 
@@ -261,10 +255,6 @@ module Playwright
261
255
  @main_frame.visible?(selector, strict: strict, timeout: timeout)
262
256
  end
263
257
 
264
- def locator(selector)
265
- @main_frame.locator(selector)
266
- end
267
-
268
258
  def dispatch_event(selector, type, eventInit: nil, strict: nil, timeout: nil)
269
259
  @main_frame.dispatch_event(selector, type, eventInit: eventInit, strict: strict, timeout: timeout)
270
260
  end
@@ -568,6 +558,14 @@ module Playwright
568
558
  timeout: timeout)
569
559
  end
570
560
 
561
+ def locator(selector)
562
+ @main_frame.locator(selector)
563
+ end
564
+
565
+ def frame_locator(selector)
566
+ @main_frame.frame_locator(selector)
567
+ end
568
+
571
569
  def focus(selector, strict: nil, timeout: nil)
572
570
  @main_frame.focus(selector, strict: strict, timeout: timeout)
573
571
  end
@@ -735,6 +733,10 @@ module Playwright
735
733
  @workers.to_a
736
734
  end
737
735
 
736
+ def request
737
+ @browser_context.request
738
+ end
739
+
738
740
  def pause
739
741
  @browser_context.send(:pause)
740
742
  end
@@ -925,6 +927,11 @@ module Playwright
925
927
  @workers.delete(worker)
926
928
  end
927
929
 
930
+ # called from Video
931
+ private def remote_connection?
932
+ @connection.remote?
933
+ end
934
+
928
935
  # Expose guid for library developers.
929
936
  # Not intended to be used by users.
930
937
  def guid
@@ -21,6 +21,15 @@ module Playwright
21
21
  @waiting_for_object = {} # Hash[ guid => Promise<ChannelOwner> ]
22
22
  @callbacks = {} # Hash [ guid => Promise<ChannelOwner> ]
23
23
  @root_object = RootChannelOwner.new(self)
24
+ @remote = false
25
+ end
26
+
27
+ def mark_as_remote
28
+ @remote = true
29
+ end
30
+
31
+ def remote?
32
+ @remote
24
33
  end
25
34
 
26
35
  def async_run
@@ -0,0 +1,49 @@
1
+ module Playwright
2
+ define_api_implementation :FrameLocatorImpl do
3
+ def initialize(frame:, timeout_settings:, frame_selector:)
4
+ @frame = frame
5
+ @timeout_settings = timeout_settings
6
+ @frame_selector = frame_selector
7
+ end
8
+
9
+ def locator(selector)
10
+ LocatorImpl.new(
11
+ frame: @frame,
12
+ timeout_settings: @timeout_settings,
13
+ selector: "#{@frame_selector} >> control=enter-frame >> #{selector}",
14
+ )
15
+ end
16
+
17
+ def frame_locator(selector)
18
+ FrameLocatorImpl.new(
19
+ frame: @frame,
20
+ timeout_settings: @timeout_settings,
21
+ frame_selector: "#{@frame_selector} >> control=enter-frame >> #{selector}",
22
+ )
23
+ end
24
+
25
+ def first
26
+ FrameLocatorImpl.new(
27
+ frame: @frame,
28
+ timeout_settings: @timeout_settings,
29
+ frame_selector: "#{@frame_selector} >> nth=0",
30
+ )
31
+ end
32
+
33
+ def last
34
+ FrameLocatorImpl.new(
35
+ frame: @frame,
36
+ timeout_settings: @timeout_settings,
37
+ frame_selector: "#{@frame_selector} >> nth=-1",
38
+ )
39
+ end
40
+
41
+ def nth(index)
42
+ FrameLocatorImpl.new(
43
+ frame: @frame,
44
+ timeout_settings: @timeout_settings,
45
+ frame_selector: "#{@frame_selector} >> nth=#{index}",
46
+ )
47
+ end
48
+ end
49
+ end
@@ -11,17 +11,17 @@ module Playwright
11
11
  end
12
12
 
13
13
  private def with_element(timeout: nil, &block)
14
+ timeout_or_default = @timeout_settings.timeout(timeout)
14
15
  start_time = Time.now
15
16
 
16
- handle = @frame.wait_for_selector(@selector, strict: true, state: 'attached', timeout: timeout)
17
+ handle = @frame.wait_for_selector(@selector, strict: true, state: 'attached', timeout: timeout_or_default)
17
18
  unless handle
18
19
  raise "Could not resolve #{@selector} to DOM Element"
19
20
  end
20
21
 
21
- call_options = {}
22
- if timeout
23
- call_options[:timeout] = (timeout - (Time.now - start_time) * 1000).to_i
24
- end
22
+ call_options = {
23
+ timeout: (timeout_or_default - (Time.now - start_time) * 1000).to_i,
24
+ }
25
25
 
26
26
  begin
27
27
  block.call(handle, call_options)
@@ -130,6 +130,14 @@ module Playwright
130
130
  )
131
131
  end
132
132
 
133
+ def frame_locator(selector)
134
+ FrameLocatorImpl.new(
135
+ frame: @frame,
136
+ timeout_settings: @timeout_settings,
137
+ frame_selector: "#{@selector} >> #{selector}",
138
+ )
139
+ end
140
+
133
141
  def element_handle(timeout: nil)
134
142
  @frame.wait_for_selector(@selector, strict: true, state: 'attached', timeout: timeout)
135
143
  end
@@ -5,18 +5,18 @@ module Playwright
5
5
  @context = context
6
6
  end
7
7
 
8
- def start(name: nil, screenshots: nil, snapshots: nil)
8
+ def start(name: nil, title: nil, screenshots: nil, snapshots: nil)
9
9
  params = {
10
10
  name: name,
11
11
  screenshots: screenshots,
12
12
  snapshots: snapshots,
13
13
  }.compact
14
14
  @channel.send_message_to_server('tracingStart', params)
15
- @channel.send_message_to_server('tracingStartChunk')
15
+ @channel.send_message_to_server('tracingStartChunk', { title: title }.compact)
16
16
  end
17
17
 
18
- def start_chunk
19
- @channel.send_message_to_server('tracingStartChunk')
18
+ def start_chunk(title: nil)
19
+ @channel.send_message_to_server('tracingStartChunk', { title: title }.compact)
20
20
  end
21
21
 
22
22
  def stop_chunk(path: nil)
@@ -29,13 +29,10 @@ module Playwright
29
29
  end
30
30
 
31
31
  private def do_stop_chunk(path:)
32
- resp = @channel.send_message_to_server('tracingStopChunk', save: !path.nil?)
33
- artifact = ChannelOwners::Artifact.from_nullable(resp)
32
+ result = @channel.send_message_to_server_result('tracingStopChunk', save: !path.nil?, skipCompress: false)
33
+ artifact = ChannelOwners::Artifact.from_nullable(result['artifact'])
34
34
  return unless artifact
35
35
 
36
- if @context.browser.send(:remote?)
37
- artifact.update_as_remote
38
- end
39
36
  artifact.save_as(path)
40
37
  artifact.delete
41
38
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '1.16.0'
5
- COMPATIBLE_PLAYWRIGHT_VERSION = '1.16.0'
4
+ VERSION = '1.17.1'
5
+ COMPATIBLE_PLAYWRIGHT_VERSION = '1.17.2'
6
6
  end
@@ -22,6 +22,9 @@ module Playwright
22
22
  end
23
23
 
24
24
  def path
25
+ if @page.send(:remote_connection?)
26
+ raise 'Path is not available when using browserType.connect(). Use save_as() to save a local copy.'
27
+ end
25
28
  wait_for_artifact_and do |artifact|
26
29
  artifact.absolute_path
27
30
  end