playwright-ruby-client 1.57.0 → 1.59.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.
- checksums.yaml +4 -4
- data/README.md +7 -7
- data/documentation/docs/api/browser_context.md +26 -0
- data/documentation/docs/api/browser_type.md +3 -2
- data/documentation/docs/api/console_message.md +9 -0
- data/documentation/docs/api/frame.md +2 -2
- data/documentation/docs/api/frame_locator.md +2 -2
- data/documentation/docs/api/locator.md +17 -4
- data/documentation/docs/api/locator_assertions.md +1 -1
- data/documentation/docs/api/page.md +68 -5
- data/documentation/docs/api/request.md +13 -0
- data/documentation/docs/api/response.md +9 -0
- data/documentation/docs/api/route.md +4 -1
- data/documentation/docs/api/tracing.md +1 -0
- data/documentation/docs/article/getting_started.md +1 -1
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/launch_browser.md +5 -5
- data/documentation/docs/article/guides/rails_integration.md +3 -3
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +46 -0
- data/documentation/docs/article/guides/recording_video.md +2 -2
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/include/api_coverage.md +16 -0
- data/lib/playwright/channel_owners/api_request_context.rb +24 -2
- data/lib/playwright/channel_owners/binding_call.rb +37 -3
- data/lib/playwright/channel_owners/browser_context.rb +24 -4
- data/lib/playwright/channel_owners/browser_type.rb +2 -1
- data/lib/playwright/channel_owners/debugger.rb +4 -0
- data/lib/playwright/channel_owners/dialog.rb +3 -1
- data/lib/playwright/channel_owners/disposable.rb +9 -0
- data/lib/playwright/channel_owners/overlay.rb +4 -0
- data/lib/playwright/channel_owners/page.rb +58 -32
- data/lib/playwright/channel_owners/request.rb +8 -0
- data/lib/playwright/channel_owners/response.rb +5 -0
- data/lib/playwright/channel_owners/stream.rb +4 -0
- data/lib/playwright/channel_owners/tracing.rb +17 -7
- data/lib/playwright/channel_owners/web_socket.rb +14 -0
- data/lib/playwright/connection.rb +25 -20
- data/lib/playwright/console_message_impl.rb +4 -0
- data/lib/playwright/disposable.rb +11 -0
- data/lib/playwright/har_router.rb +16 -1
- data/lib/playwright/javascript/value_serializer.rb +2 -1
- data/lib/playwright/locator_assertions_impl.rb +1 -1
- data/lib/playwright/locator_impl.rb +19 -3
- data/lib/playwright/page_assertions_impl.rb +1 -1
- data/lib/playwright/screencast.rb +91 -0
- data/lib/playwright/utils.rb +19 -0
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/video.rb +6 -4
- data/lib/playwright/waiter.rb +24 -6
- data/lib/playwright.rb +2 -0
- data/lib/playwright_api/android.rb +7 -7
- data/lib/playwright_api/android_device.rb +8 -8
- data/lib/playwright_api/api_request_context.rb +6 -6
- data/lib/playwright_api/browser.rb +18 -6
- data/lib/playwright_api/browser_context.rb +32 -6
- data/lib/playwright_api/browser_type.rb +13 -12
- data/lib/playwright_api/cdp_session.rb +6 -6
- data/lib/playwright_api/console_message.rb +6 -0
- data/lib/playwright_api/dialog.rb +6 -6
- data/lib/playwright_api/element_handle.rb +6 -6
- data/lib/playwright_api/frame.rb +8 -8
- data/lib/playwright_api/frame_locator.rb +2 -2
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/locator.rb +19 -9
- data/lib/playwright_api/locator_assertions.rb +1 -1
- data/lib/playwright_api/page.rb +72 -23
- data/lib/playwright_api/playwright.rb +6 -6
- data/lib/playwright_api/request.rb +28 -6
- data/lib/playwright_api/response.rb +12 -6
- data/lib/playwright_api/route.rb +10 -7
- data/lib/playwright_api/tracing.rb +8 -7
- data/lib/playwright_api/web_socket.rb +6 -6
- data/lib/playwright_api/worker.rb +6 -6
- data/playwright.gemspec +9 -1
- data/sig/playwright.rbs +30 -17
- metadata +35 -2
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* redirected_to
|
|
18
18
|
* resource_type
|
|
19
19
|
* response
|
|
20
|
+
* existing_response
|
|
21
|
+
* ~~service_worker~~
|
|
20
22
|
* sizes
|
|
21
23
|
* timing
|
|
22
24
|
* url
|
|
@@ -32,6 +34,7 @@
|
|
|
32
34
|
* headers_array
|
|
33
35
|
* header_value
|
|
34
36
|
* header_values
|
|
37
|
+
* http_version
|
|
35
38
|
* json
|
|
36
39
|
* ok
|
|
37
40
|
* request
|
|
@@ -227,6 +230,7 @@
|
|
|
227
230
|
* location
|
|
228
231
|
* page
|
|
229
232
|
* text
|
|
233
|
+
* timestamp
|
|
230
234
|
* type
|
|
231
235
|
* worker
|
|
232
236
|
|
|
@@ -256,6 +260,7 @@
|
|
|
256
260
|
* add_script_tag
|
|
257
261
|
* add_style_tag
|
|
258
262
|
* bring_to_front
|
|
263
|
+
* cancel_pick_locator
|
|
259
264
|
* check
|
|
260
265
|
* click
|
|
261
266
|
* close
|
|
@@ -299,6 +304,8 @@
|
|
|
299
304
|
* enabled?
|
|
300
305
|
* hidden?
|
|
301
306
|
* visible?
|
|
307
|
+
* clear_console_messages
|
|
308
|
+
* clear_page_errors
|
|
302
309
|
* console_messages
|
|
303
310
|
* page_errors
|
|
304
311
|
* locator
|
|
@@ -306,6 +313,7 @@
|
|
|
306
313
|
* opener
|
|
307
314
|
* pause
|
|
308
315
|
* pdf
|
|
316
|
+
* pick_locator
|
|
309
317
|
* press
|
|
310
318
|
* query_selector
|
|
311
319
|
* query_selector_all
|
|
@@ -325,6 +333,7 @@
|
|
|
325
333
|
* set_extra_http_headers
|
|
326
334
|
* set_input_files
|
|
327
335
|
* set_viewport_size
|
|
336
|
+
* aria_snapshot
|
|
328
337
|
* tap_point
|
|
329
338
|
* text_content
|
|
330
339
|
* title
|
|
@@ -357,6 +366,7 @@
|
|
|
357
366
|
* keyboard
|
|
358
367
|
* mouse
|
|
359
368
|
* request
|
|
369
|
+
* screencast
|
|
360
370
|
* touchscreen
|
|
361
371
|
|
|
362
372
|
## BrowserContext
|
|
@@ -372,6 +382,7 @@
|
|
|
372
382
|
* expose_binding
|
|
373
383
|
* expose_function
|
|
374
384
|
* grant_permissions
|
|
385
|
+
* closed?
|
|
375
386
|
* new_cdp_session
|
|
376
387
|
* new_page
|
|
377
388
|
* pages
|
|
@@ -385,6 +396,7 @@
|
|
|
385
396
|
* set_geolocation
|
|
386
397
|
* set_offline
|
|
387
398
|
* storage_state
|
|
399
|
+
* set_storage_state
|
|
388
400
|
* unroute_all
|
|
389
401
|
* unroute
|
|
390
402
|
* expect_console_message
|
|
@@ -392,6 +404,7 @@
|
|
|
392
404
|
* expect_page
|
|
393
405
|
* ~~wait_for_event~~
|
|
394
406
|
* clock
|
|
407
|
+
* ~~debugger~~
|
|
395
408
|
* request
|
|
396
409
|
* tracing
|
|
397
410
|
|
|
@@ -409,8 +422,10 @@
|
|
|
409
422
|
* new_browser_cdp_session
|
|
410
423
|
* new_context
|
|
411
424
|
* new_page
|
|
425
|
+
* ~~bind~~
|
|
412
426
|
* start_tracing
|
|
413
427
|
* stop_tracing
|
|
428
|
+
* ~~unbind~~
|
|
414
429
|
* version
|
|
415
430
|
|
|
416
431
|
## BrowserType
|
|
@@ -491,6 +506,7 @@
|
|
|
491
506
|
* visible?
|
|
492
507
|
* last
|
|
493
508
|
* locator
|
|
509
|
+
* normalize
|
|
494
510
|
* nth
|
|
495
511
|
* or
|
|
496
512
|
* page
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'base64'
|
|
2
|
-
require 'cgi'
|
|
2
|
+
require 'cgi/escape'
|
|
3
3
|
|
|
4
4
|
module Playwright
|
|
5
5
|
define_channel_owner :APIRequestContext do
|
|
@@ -197,7 +197,7 @@ module Playwright
|
|
|
197
197
|
end
|
|
198
198
|
|
|
199
199
|
private def query_string_to_array(query_string)
|
|
200
|
-
params =
|
|
200
|
+
params = cgi_parse(query_string)
|
|
201
201
|
|
|
202
202
|
params.map do |key, values|
|
|
203
203
|
values.map do |value|
|
|
@@ -206,6 +206,28 @@ module Playwright
|
|
|
206
206
|
end.flatten
|
|
207
207
|
end
|
|
208
208
|
|
|
209
|
+
# https://bugs.ruby-lang.org/issues/21258
|
|
210
|
+
# CGI.parse is defined in 'cgi' library.
|
|
211
|
+
# But it produces an error in Ruby 2.4 environment: undefined method `delete_prefix' for "CONTENT_LENGTH":String
|
|
212
|
+
# So we implement our own version of CGI.parse here.
|
|
213
|
+
private def cgi_parse(query)
|
|
214
|
+
# https://github.com/ruby/cgi/blob/master/lib/cgi/core.rb#L396
|
|
215
|
+
params = {}
|
|
216
|
+
|
|
217
|
+
query.split(/[&;]/).each do |pairs|
|
|
218
|
+
key, value = pairs.split('=',2).map do |v|
|
|
219
|
+
CGI.unescape(v)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
next unless key
|
|
223
|
+
params[key] ||= []
|
|
224
|
+
next unless value
|
|
225
|
+
params[key] << value
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
params
|
|
229
|
+
end
|
|
230
|
+
|
|
209
231
|
private def object_to_array(hash)
|
|
210
232
|
hash&.map do |key, value|
|
|
211
233
|
{ name: key, value: value.to_s }
|
|
@@ -1,11 +1,45 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
define_channel_owner :BindingCall do
|
|
3
|
+
class << self
|
|
4
|
+
def call_queue
|
|
5
|
+
@call_queue ||= Queue.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def worker_mutex
|
|
9
|
+
@worker_mutex ||= Mutex.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def ensure_worker
|
|
13
|
+
worker_mutex.synchronize do
|
|
14
|
+
return if @worker&.alive?
|
|
15
|
+
|
|
16
|
+
@worker = Thread.new do
|
|
17
|
+
loop do
|
|
18
|
+
job = call_queue.pop
|
|
19
|
+
begin
|
|
20
|
+
job.call
|
|
21
|
+
rescue => err
|
|
22
|
+
$stderr.write("BindingCall worker error: #{err.class}: #{err.message}\n")
|
|
23
|
+
err.backtrace&.each { |line| $stderr.write("#{line}\n") }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
3
31
|
def name
|
|
4
32
|
@initializer['name']
|
|
5
33
|
end
|
|
6
34
|
|
|
7
35
|
def call_async(callback)
|
|
8
|
-
|
|
36
|
+
# Binding callbacks can be fired concurrently from multiple threads.
|
|
37
|
+
# Enqueue and execute them on a single worker thread so we:
|
|
38
|
+
# - preserve the delivery order of binding calls
|
|
39
|
+
# - avoid spawning a thread per call (bursty timers create many callbacks)
|
|
40
|
+
# - keep the protocol dispatch thread unblocked
|
|
41
|
+
self.class.ensure_worker
|
|
42
|
+
self.class.call_queue << -> { call(callback) }
|
|
9
43
|
end
|
|
10
44
|
|
|
11
45
|
# @param callback [Proc]
|
|
@@ -31,9 +65,9 @@ module Playwright
|
|
|
31
65
|
|
|
32
66
|
begin
|
|
33
67
|
result = PlaywrightApi.unwrap(callback.call(source, *args))
|
|
34
|
-
@channel.
|
|
68
|
+
@channel.async_send_message_to_server('resolve', result: JavaScript::ValueSerializer.new(result).serialize)
|
|
35
69
|
rescue => err
|
|
36
|
-
@channel.
|
|
70
|
+
@channel.async_send_message_to_server('reject', error: { error: { message: err.message, name: 'Error' }})
|
|
37
71
|
end
|
|
38
72
|
end
|
|
39
73
|
end
|
|
@@ -333,8 +333,8 @@ module Playwright
|
|
|
333
333
|
raise ArgumentError.new('Either path or script parameter must be specified')
|
|
334
334
|
end
|
|
335
335
|
|
|
336
|
-
@channel.
|
|
337
|
-
|
|
336
|
+
result = @channel.send_message_to_server_result('addInitScript', source: source)
|
|
337
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
338
338
|
end
|
|
339
339
|
|
|
340
340
|
def expose_binding(name, callback, handle: nil)
|
|
@@ -349,17 +349,19 @@ module Playwright
|
|
|
349
349
|
needsHandle: handle,
|
|
350
350
|
}.compact
|
|
351
351
|
@bindings[name] = callback
|
|
352
|
-
@channel.
|
|
352
|
+
result = @channel.send_message_to_server_result('exposeBinding', params)
|
|
353
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
353
354
|
end
|
|
354
355
|
|
|
355
356
|
def expose_function(name, callback)
|
|
356
|
-
expose_binding(name, ->(_source, *args) { callback.call(*args) }
|
|
357
|
+
expose_binding(name, ->(_source, *args) { callback.call(*args) })
|
|
357
358
|
end
|
|
358
359
|
|
|
359
360
|
def route(url, handler, times: nil)
|
|
360
361
|
entry = RouteHandler.new(url, base_url, handler, times)
|
|
361
362
|
@routes.unshift(entry)
|
|
362
363
|
update_interception_patterns
|
|
364
|
+
DisposableStub.new { unroute(url, handler: handler) }
|
|
363
365
|
end
|
|
364
366
|
|
|
365
367
|
def unroute_all(behavior: nil)
|
|
@@ -547,6 +549,24 @@ module Playwright
|
|
|
547
549
|
@timeout_settings
|
|
548
550
|
end
|
|
549
551
|
|
|
552
|
+
def set_storage_state(storageState)
|
|
553
|
+
payload = case storageState
|
|
554
|
+
when String
|
|
555
|
+
begin
|
|
556
|
+
JSON.parse(File.read(storageState))
|
|
557
|
+
rescue => e
|
|
558
|
+
raise ::Playwright::Error.new(message: "Failed to read storage state from '#{storageState}': #{e.message}")
|
|
559
|
+
end
|
|
560
|
+
else
|
|
561
|
+
storageState
|
|
562
|
+
end
|
|
563
|
+
@channel.send_message_to_server('setStorageState', storageState: payload)
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def closed?
|
|
567
|
+
@close_was_called
|
|
568
|
+
end
|
|
569
|
+
|
|
550
570
|
private def has_record_video_option?
|
|
551
571
|
@options.key?(:recordVideo)
|
|
552
572
|
end
|
|
@@ -60,12 +60,13 @@ module Playwright
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def connect_over_cdp(endpointURL, headers: nil, slowMo: nil, timeout: nil, &block)
|
|
63
|
+
def connect_over_cdp(endpointURL, headers: nil, isLocal: nil, slowMo: nil, timeout: nil, &block)
|
|
64
64
|
raise 'Connecting over CDP is only supported in Chromium.' unless name == 'chromium'
|
|
65
65
|
|
|
66
66
|
params = {
|
|
67
67
|
endpointURL: endpointURL,
|
|
68
68
|
headers: headers,
|
|
69
|
+
isLocal: isLocal,
|
|
69
70
|
slowMo: slowMo,
|
|
70
71
|
timeout: @timeout_settings.timeout(timeout),
|
|
71
72
|
}.compact
|
|
@@ -56,7 +56,9 @@ module Playwright
|
|
|
56
56
|
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
|
57
57
|
})
|
|
58
58
|
@channel.on('route', ->(params) { on_route(ChannelOwners::Route.from(params['route'])) })
|
|
59
|
-
@
|
|
59
|
+
if @initializer['video']
|
|
60
|
+
@video_artifact = ChannelOwners::Artifact.from(@initializer['video'])
|
|
61
|
+
end
|
|
60
62
|
@channel.on('viewportSizeChanged', method(:on_viewport_size_changed))
|
|
61
63
|
@channel.on('webSocket', ->(params) {
|
|
62
64
|
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
|
@@ -98,7 +100,7 @@ module Playwright
|
|
|
98
100
|
|
|
99
101
|
private def on_route(route)
|
|
100
102
|
route.send(:update_context, self)
|
|
101
|
-
|
|
103
|
+
return if @close_was_called
|
|
102
104
|
# It is not desired to use PlaywrightApi.wrap directly.
|
|
103
105
|
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
|
104
106
|
# Just a workaround...
|
|
@@ -171,11 +173,6 @@ module Playwright
|
|
|
171
173
|
emit(Events::Page::Download, download)
|
|
172
174
|
end
|
|
173
175
|
|
|
174
|
-
private def on_video(params)
|
|
175
|
-
artifact = ChannelOwners::Artifact.from(params['artifact'])
|
|
176
|
-
video.send(:set_artifact, artifact)
|
|
177
|
-
end
|
|
178
|
-
|
|
179
176
|
private def on_viewport_size_changed(params)
|
|
180
177
|
@viewport_size = {
|
|
181
178
|
width: params['viewportSize']['width'],
|
|
@@ -307,8 +304,9 @@ module Playwright
|
|
|
307
304
|
end
|
|
308
305
|
|
|
309
306
|
def expose_function(name, callback)
|
|
310
|
-
@channel.
|
|
307
|
+
result = @channel.send_message_to_server_result('exposeBinding', name: name)
|
|
311
308
|
@bindings[name] = ->(_source, *args) { callback.call(*args) }
|
|
309
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
312
310
|
end
|
|
313
311
|
|
|
314
312
|
def expose_binding(name, callback, handle: nil)
|
|
@@ -316,8 +314,9 @@ module Playwright
|
|
|
316
314
|
name: name,
|
|
317
315
|
needsHandle: handle,
|
|
318
316
|
}.compact
|
|
319
|
-
@channel.
|
|
317
|
+
result = @channel.send_message_to_server_result('exposeBinding', params)
|
|
320
318
|
@bindings[name] = callback
|
|
319
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
321
320
|
end
|
|
322
321
|
|
|
323
322
|
def set_extra_http_headers(headers)
|
|
@@ -412,14 +411,15 @@ module Playwright
|
|
|
412
411
|
raise ArgumentError.new('Either path or script parameter must be specified')
|
|
413
412
|
end
|
|
414
413
|
|
|
415
|
-
@channel.
|
|
416
|
-
|
|
414
|
+
result = @channel.send_message_to_server_result('addInitScript', source: source)
|
|
415
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
417
416
|
end
|
|
418
417
|
|
|
419
418
|
def route(url, handler, times: nil)
|
|
420
419
|
entry = RouteHandler.new(url, @browser_context.send(:base_url), handler, times)
|
|
421
420
|
@routes.unshift(entry)
|
|
422
421
|
update_interception_patterns
|
|
422
|
+
DisposableStub.new { unroute(url, handler: handler) }
|
|
423
423
|
end
|
|
424
424
|
|
|
425
425
|
def unroute_all(behavior: nil)
|
|
@@ -508,6 +508,9 @@ module Playwright
|
|
|
508
508
|
|
|
509
509
|
def close(runBeforeUnload: nil, reason: nil)
|
|
510
510
|
@close_reason = reason
|
|
511
|
+
unless runBeforeUnload
|
|
512
|
+
@close_was_called = true
|
|
513
|
+
end
|
|
511
514
|
if @owned_context
|
|
512
515
|
@owned_context.close
|
|
513
516
|
else
|
|
@@ -643,20 +646,49 @@ module Playwright
|
|
|
643
646
|
timeout: timeout)
|
|
644
647
|
end
|
|
645
648
|
|
|
646
|
-
def console_messages
|
|
647
|
-
|
|
649
|
+
def console_messages(filter: nil)
|
|
650
|
+
params = {}
|
|
651
|
+
params[:filter] = filter if filter
|
|
652
|
+
messages = @channel.send_message_to_server('consoleMessages', params)
|
|
648
653
|
messages.map do |message|
|
|
649
654
|
ConsoleMessageImpl.new(message, self, nil)
|
|
650
655
|
end
|
|
651
656
|
end
|
|
652
657
|
|
|
653
|
-
def page_errors
|
|
654
|
-
|
|
658
|
+
def page_errors(filter: nil)
|
|
659
|
+
params = {}
|
|
660
|
+
params[:filter] = filter if filter
|
|
661
|
+
errors = @channel.send_message_to_server('pageErrors', params)
|
|
655
662
|
errors.map do |error|
|
|
656
663
|
Error.parse(error['error'])
|
|
657
664
|
end
|
|
658
665
|
end
|
|
659
666
|
|
|
667
|
+
def clear_console_messages
|
|
668
|
+
@channel.send_message_to_server('clearConsoleMessages')
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
def clear_page_errors
|
|
672
|
+
@channel.send_message_to_server('clearPageErrors')
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
def cancel_pick_locator
|
|
676
|
+
@channel.send_message_to_server('cancelPickLocator')
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
def aria_snapshot(depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
680
|
+
params = { selector: 'body' }
|
|
681
|
+
params[:timeout] = @timeout_settings.timeout(timeout)
|
|
682
|
+
params[:depth] = depth if depth
|
|
683
|
+
params[:mode] = mode if mode
|
|
684
|
+
if _track
|
|
685
|
+
params.delete(:selector)
|
|
686
|
+
params[:track] = _track
|
|
687
|
+
end
|
|
688
|
+
result = @main_frame.channel.send_message_to_server_result('ariaSnapshot', params)
|
|
689
|
+
result['snapshot']
|
|
690
|
+
end
|
|
691
|
+
|
|
660
692
|
def locator(
|
|
661
693
|
selector,
|
|
662
694
|
has: nil,
|
|
@@ -901,28 +933,22 @@ module Playwright
|
|
|
901
933
|
decoded_binary
|
|
902
934
|
end
|
|
903
935
|
|
|
936
|
+
def screencast
|
|
937
|
+
@screencast ||= Screencast.new(self)
|
|
938
|
+
end
|
|
939
|
+
|
|
904
940
|
def video
|
|
905
941
|
return nil unless @browser_context.send(:has_record_video_option?)
|
|
906
|
-
@video ||= Video.new(self)
|
|
942
|
+
@video ||= Video.new(self, artifact: @video_artifact)
|
|
907
943
|
end
|
|
908
944
|
|
|
909
|
-
def
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
end
|
|
945
|
+
def pick_locator
|
|
946
|
+
result = @channel.send_message_to_server_result('pickLocator', {})
|
|
947
|
+
@main_frame.locator(result['selector'])
|
|
948
|
+
end
|
|
914
949
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
mode: option_mode,
|
|
918
|
-
}
|
|
919
|
-
options[:track] = track if track
|
|
920
|
-
result = @channel.send_message_to_server_result('snapshotForAI', options)
|
|
921
|
-
if option_mode == 'full'
|
|
922
|
-
result['full']
|
|
923
|
-
elsif option_mode == 'incremental'
|
|
924
|
-
result['incremental']
|
|
925
|
-
end
|
|
950
|
+
def snapshot_for_ai(timeout: nil, depth: nil, _track: nil)
|
|
951
|
+
aria_snapshot(mode: 'ai', timeout: timeout, depth: depth, _track: _track)
|
|
926
952
|
end
|
|
927
953
|
|
|
928
954
|
def start_js_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
|
|
@@ -81,6 +81,10 @@ module Playwright
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
def existing_response
|
|
85
|
+
@response
|
|
86
|
+
end
|
|
87
|
+
|
|
84
88
|
def response
|
|
85
89
|
resp = @channel.send_message_to_server('response')
|
|
86
90
|
ChannelOwners::Response.from_nullable(resp)
|
|
@@ -162,6 +166,10 @@ module Playwright
|
|
|
162
166
|
res.send(:sizes)
|
|
163
167
|
end
|
|
164
168
|
|
|
169
|
+
private def update_response(response)
|
|
170
|
+
@response = response
|
|
171
|
+
end
|
|
172
|
+
|
|
165
173
|
private def update_redirected_to(request)
|
|
166
174
|
@redirected_to = request
|
|
167
175
|
end
|
|
@@ -7,6 +7,7 @@ module Playwright
|
|
|
7
7
|
private def after_initialize
|
|
8
8
|
@provisional_headers = RawHeaders.new(@initializer['headers'])
|
|
9
9
|
@request = ChannelOwners::Request.from(@initializer['request'])
|
|
10
|
+
@request.send(:update_response, self)
|
|
10
11
|
timing = @initializer['timing']
|
|
11
12
|
@request.send(:update_timings,
|
|
12
13
|
start_time: timing["startTime"],
|
|
@@ -74,6 +75,10 @@ module Playwright
|
|
|
74
75
|
actual_headers.get_all(name)
|
|
75
76
|
end
|
|
76
77
|
|
|
78
|
+
def http_version
|
|
79
|
+
@channel.send_message_to_server('httpVersion')
|
|
80
|
+
end
|
|
81
|
+
|
|
77
82
|
def server_addr
|
|
78
83
|
@channel.send_message_to_server('serverAddr')
|
|
79
84
|
end
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
require 'base64'
|
|
2
|
+
require 'fileutils'
|
|
2
3
|
|
|
3
4
|
module Playwright
|
|
4
5
|
define_channel_owner :Stream do
|
|
5
6
|
def save_as(path)
|
|
7
|
+
parent_dir = File.dirname(path)
|
|
8
|
+
FileUtils.mkdir_p(parent_dir) unless parent_dir == '.'
|
|
9
|
+
|
|
6
10
|
File.open(path, 'wb') do |f|
|
|
7
11
|
read_with_block do |chunk|
|
|
8
12
|
f.write(chunk)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
define_channel_owner :Tracing do
|
|
3
|
-
def start(name: nil, title: nil, screenshots: nil, snapshots: nil, sources: nil)
|
|
3
|
+
def start(name: nil, title: nil, screenshots: nil, snapshots: nil, sources: nil, live: nil)
|
|
4
4
|
params = {
|
|
5
5
|
name: name,
|
|
6
6
|
screenshots: screenshots,
|
|
7
7
|
snapshots: snapshots,
|
|
8
8
|
sources: sources,
|
|
9
|
+
live: live,
|
|
9
10
|
}.compact
|
|
10
11
|
@include_sources = params[:sources] || false
|
|
11
12
|
@channel.send_message_to_server('tracingStart', params)
|
|
@@ -23,7 +24,8 @@ module Playwright
|
|
|
23
24
|
@is_tracing = true
|
|
24
25
|
@connection.set_in_tracing(true)
|
|
25
26
|
end
|
|
26
|
-
|
|
27
|
+
local_utils = @connection.local_utils
|
|
28
|
+
@stacks_id = local_utils&.tracing_started(@traces_dir, trace_name)
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def stop_chunk(path: nil)
|
|
@@ -40,20 +42,26 @@ module Playwright
|
|
|
40
42
|
@is_tracing = false
|
|
41
43
|
@connection.set_in_tracing(false)
|
|
42
44
|
end
|
|
45
|
+
local_utils = @connection.local_utils
|
|
43
46
|
|
|
44
47
|
unless file_path
|
|
45
48
|
# Not interested in any artifacts
|
|
46
49
|
@channel.send_message_to_server('tracingStopChunk', mode: 'discard')
|
|
47
50
|
if @stacks_id
|
|
48
|
-
|
|
51
|
+
local_utils.trace_discarded(@stacks_id) if local_utils
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
return
|
|
52
55
|
end
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
is_local = !@connection.remote?
|
|
58
|
+
if is_local
|
|
59
|
+
unless local_utils
|
|
60
|
+
raise 'Cannot save trace because localUtils is unavailable.'
|
|
61
|
+
end
|
|
62
|
+
|
|
55
63
|
result = @channel.send_message_to_server_result('tracingStopChunk', mode: 'entries')
|
|
56
|
-
|
|
64
|
+
local_utils.zip(
|
|
57
65
|
zipFile: file_path,
|
|
58
66
|
entries: result['entries'],
|
|
59
67
|
stacksId: @stacks_id,
|
|
@@ -69,7 +77,7 @@ module Playwright
|
|
|
69
77
|
# The artifact may be missing if the browser closed while stopping tracing.
|
|
70
78
|
unless result['artifact']
|
|
71
79
|
if @stacks_id
|
|
72
|
-
|
|
80
|
+
local_utils.trace_discarded(@stacks_id) if local_utils
|
|
73
81
|
end
|
|
74
82
|
|
|
75
83
|
return
|
|
@@ -80,7 +88,9 @@ module Playwright
|
|
|
80
88
|
artifact.save_as(file_path)
|
|
81
89
|
artifact.delete
|
|
82
90
|
|
|
83
|
-
|
|
91
|
+
return unless local_utils
|
|
92
|
+
|
|
93
|
+
local_utils.zip(
|
|
84
94
|
zipFile: file_path,
|
|
85
95
|
entries: [],
|
|
86
96
|
stacksId: @stacks_id,
|
|
@@ -48,7 +48,21 @@ module Playwright
|
|
|
48
48
|
|
|
49
49
|
waiter.reject_on_event(@parent, 'close', -> { @parent.send(:close_error_with_reason) })
|
|
50
50
|
waiter.wait_for_event(self, event, predicate: predicate)
|
|
51
|
+
if @closed
|
|
52
|
+
if event == Events::WebSocket::Close
|
|
53
|
+
waiter.force_fulfill(nil)
|
|
54
|
+
else
|
|
55
|
+
waiter.force_reject(SocketClosedError.new)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
51
58
|
block&.call
|
|
59
|
+
if @closed
|
|
60
|
+
if event == Events::WebSocket::Close
|
|
61
|
+
waiter.force_fulfill(nil)
|
|
62
|
+
else
|
|
63
|
+
waiter.force_reject(SocketClosedError.new)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
52
66
|
|
|
53
67
|
waiter.result.value!
|
|
54
68
|
end
|