playwright-ruby-client 1.39.1 → 1.41.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/documentation/docs/api/api_request_context.md +1 -2
- data/documentation/docs/api/browser.md +1 -1
- data/documentation/docs/api/browser_context.md +10 -1
- data/documentation/docs/api/browser_type.md +1 -0
- data/documentation/docs/api/download.md +1 -2
- data/documentation/docs/api/element_handle.md +5 -1
- data/documentation/docs/api/frame.md +4 -1
- data/documentation/docs/api/locator.md +5 -1
- data/documentation/docs/api/locator_assertions.md +12 -2
- data/documentation/docs/api/page.md +16 -3
- data/documentation/docs/api/tracing.md +2 -2
- data/documentation/docs/article/guides/rails_integration.md +80 -51
- data/documentation/docs/article/guides/rspec_integration.md +59 -0
- data/documentation/docs/include/api_coverage.md +2 -0
- data/documentation/docusaurus.config.js +1 -1
- data/documentation/package.json +7 -7
- data/documentation/yarn.lock +4641 -5023
- data/lib/playwright/api_response_impl.rb +2 -2
- data/lib/playwright/channel_owners/api_request_context.rb +12 -3
- data/lib/playwright/channel_owners/browser.rb +11 -7
- data/lib/playwright/channel_owners/browser_context.rb +40 -15
- data/lib/playwright/channel_owners/element_handle.rb +2 -0
- data/lib/playwright/channel_owners/frame.rb +38 -14
- data/lib/playwright/channel_owners/page.rb +36 -16
- data/lib/playwright/channel_owners/web_socket.rb +8 -13
- data/lib/playwright/connection.rb +18 -2
- data/lib/playwright/errors.rb +20 -2
- data/lib/playwright/input_files.rb +4 -4
- data/lib/playwright/locator_assertions_impl.rb +15 -15
- data/lib/playwright/locator_impl.rb +2 -0
- data/lib/playwright/test.rb +2 -2
- data/lib/playwright/utils.rb +3 -10
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/waiter.rb +146 -0
- data/lib/playwright.rb +1 -1
- data/lib/playwright_api/api_request_context.rb +1 -2
- data/lib/playwright_api/browser.rb +2 -2
- data/lib/playwright_api/browser_context.rb +9 -3
- data/lib/playwright_api/browser_type.rb +2 -1
- data/lib/playwright_api/download.rb +1 -2
- data/lib/playwright_api/element_handle.rb +6 -2
- data/lib/playwright_api/frame.rb +4 -1
- data/lib/playwright_api/locator.rb +6 -2
- data/lib/playwright_api/locator_assertions.rb +14 -4
- data/lib/playwright_api/page.rb +20 -10
- data/lib/playwright_api/request.rb +4 -4
- data/lib/playwright_api/tracing.rb +2 -2
- data/lib/playwright_api/worker.rb +4 -4
- data/sig/playwright.rbs +12 -10
- metadata +7 -6
- data/lib/playwright/wait_helper.rb +0 -73
@@ -1,6 +1,6 @@
|
|
1
1
|
module Playwright
|
2
2
|
define_api_implementation :APIResponseImpl do
|
3
|
-
include Utils::Errors::
|
3
|
+
include Utils::Errors::TargetClosedErrorMethods
|
4
4
|
|
5
5
|
# @params context [APIRequestContext]
|
6
6
|
# @params initializer [Hash]
|
@@ -50,7 +50,7 @@ module Playwright
|
|
50
50
|
raise AlreadyDisposedError.new unless binary
|
51
51
|
Base64.strict_decode64(binary)
|
52
52
|
rescue => err
|
53
|
-
if
|
53
|
+
if target_closed_error?(err)
|
54
54
|
raise AlreadyDisposedError.new
|
55
55
|
else
|
56
56
|
raise
|
@@ -115,12 +115,12 @@ module Playwright
|
|
115
115
|
case data
|
116
116
|
when String
|
117
117
|
if headers_obj&.any? { |key, value| key.downcase == 'content-type' && value == 'application/json' }
|
118
|
-
json_data = data
|
118
|
+
json_data = json_parsable?(data) ? data : data.to_json
|
119
119
|
else
|
120
120
|
post_data_buffer = data
|
121
121
|
end
|
122
122
|
when Hash, Array, Numeric, true, false
|
123
|
-
json_data = data
|
123
|
+
json_data = data.to_json
|
124
124
|
else
|
125
125
|
raise ArgumentError.new("Unsupported 'data' type: #{data.class}")
|
126
126
|
end
|
@@ -142,7 +142,6 @@ module Playwright
|
|
142
142
|
if post_data_buffer
|
143
143
|
fetch_params[:postData] = Base64.strict_encode64(post_data_buffer)
|
144
144
|
end
|
145
|
-
|
146
145
|
fetch_params[:jsonData] = json_data
|
147
146
|
fetch_params[:formData] = form_data
|
148
147
|
fetch_params[:multipartData] = multipart_data
|
@@ -174,5 +173,15 @@ module Playwright
|
|
174
173
|
{ name: key, value: value.to_s }
|
175
174
|
end
|
176
175
|
end
|
176
|
+
|
177
|
+
private def json_parsable?(data)
|
178
|
+
return false unless data.is_a?(String)
|
179
|
+
begin
|
180
|
+
JSON.parse(data)
|
181
|
+
true
|
182
|
+
rescue JSON::ParserError
|
183
|
+
false
|
184
|
+
end
|
185
|
+
end
|
177
186
|
end
|
178
187
|
end
|
@@ -3,17 +3,21 @@ require 'fileutils'
|
|
3
3
|
module Playwright
|
4
4
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser.py
|
5
5
|
define_channel_owner :Browser do
|
6
|
-
include Utils::Errors::
|
6
|
+
include Utils::Errors::TargetClosedErrorMethods
|
7
7
|
include Utils::PrepareBrowserContextOptions
|
8
8
|
|
9
9
|
private def after_initialize
|
10
10
|
@browser_type = @parent
|
11
11
|
@connected = true
|
12
|
-
@closed_or_closing = false
|
13
12
|
@should_close_connection_on_close = false
|
14
13
|
|
15
14
|
@contexts = Set.new
|
16
15
|
@channel.on('close', method(:on_close))
|
16
|
+
@close_reason = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
private def close_reason
|
20
|
+
@close_reason
|
17
21
|
end
|
18
22
|
|
19
23
|
def contexts
|
@@ -63,16 +67,16 @@ module Playwright
|
|
63
67
|
@browser_type = browser_type
|
64
68
|
end
|
65
69
|
|
66
|
-
def close
|
67
|
-
|
68
|
-
@closed_or_closing = true
|
69
|
-
@channel.send_message_to_server('close')
|
70
|
+
def close(reason: nil)
|
71
|
+
@close_reason = reason
|
70
72
|
if @should_close_connection_on_close
|
71
73
|
@connection.stop
|
74
|
+
else
|
75
|
+
@channel.send_message_to_server('close', { reason: reason }.compact)
|
72
76
|
end
|
73
77
|
nil
|
74
78
|
rescue => err
|
75
|
-
raise unless
|
79
|
+
raise unless target_closed_error?(err)
|
76
80
|
end
|
77
81
|
|
78
82
|
def version
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Playwright
|
2
2
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser_context.py
|
3
3
|
define_channel_owner :BrowserContext do
|
4
|
-
include Utils::Errors::SafeCloseError
|
5
4
|
include Utils::PrepareBrowserContextOptions
|
6
5
|
|
7
6
|
attr_accessor :browser
|
@@ -68,6 +67,9 @@ module Playwright
|
|
68
67
|
ChannelOwners::Page.from_nullable(params['page']),
|
69
68
|
)
|
70
69
|
})
|
70
|
+
|
71
|
+
@closed_promise = Concurrent::Promises.resolvable_future
|
72
|
+
@close_reason = nil
|
71
73
|
set_event_to_subscription_mapping({
|
72
74
|
Events::BrowserContext::Console => 'console',
|
73
75
|
Events::BrowserContext::Dialog => 'dialog',
|
@@ -77,7 +79,7 @@ module Playwright
|
|
77
79
|
Events::BrowserContext::RequestFailed => "requestFailed",
|
78
80
|
})
|
79
81
|
|
80
|
-
@
|
82
|
+
@close_was_called = false
|
81
83
|
end
|
82
84
|
|
83
85
|
private def update_options(context_options:, browser_options:)
|
@@ -333,6 +335,11 @@ module Playwright
|
|
333
335
|
update_interception_patterns
|
334
336
|
end
|
335
337
|
|
338
|
+
def unroute_all(behavior: nil)
|
339
|
+
@routes.clear
|
340
|
+
update_interception_patterns
|
341
|
+
end
|
342
|
+
|
336
343
|
def unroute(url, handler: nil)
|
337
344
|
@routes.reject! do |handler_entry|
|
338
345
|
handler_entry.same_value?(url: url, handler: handler)
|
@@ -382,13 +389,17 @@ module Playwright
|
|
382
389
|
end
|
383
390
|
|
384
391
|
def expect_event(event, predicate: nil, timeout: nil, &block)
|
385
|
-
|
386
|
-
|
387
|
-
|
392
|
+
waiter = Waiter.new(self, wait_name: "browser_context.expect_event(#{event})")
|
393
|
+
timeout_value = timeout || @timeout_settings.timeout
|
394
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout}ms exceeded while waiting for event \"#{event}\"")
|
395
|
+
unless event == Events::BrowserContext::Close
|
396
|
+
waiter.reject_on_event(self, Events::BrowserContext::Close, TargetClosedError.new)
|
397
|
+
end
|
398
|
+
waiter.wait_for_event(self, event, predicate: predicate)
|
388
399
|
|
389
400
|
block&.call
|
390
401
|
|
391
|
-
|
402
|
+
waiter.result.value!
|
392
403
|
end
|
393
404
|
|
394
405
|
private def on_close
|
@@ -397,7 +408,18 @@ module Playwright
|
|
397
408
|
@closed_promise.fulfill(true)
|
398
409
|
end
|
399
410
|
|
400
|
-
def close
|
411
|
+
def close(reason: nil)
|
412
|
+
return if @close_was_called
|
413
|
+
@close_was_called = true
|
414
|
+
@close_reason = reason
|
415
|
+
|
416
|
+
inner_close
|
417
|
+
@channel.send_message_to_server('close', { reason: reason }.compact)
|
418
|
+
@closed_promise.value!
|
419
|
+
nil
|
420
|
+
end
|
421
|
+
|
422
|
+
private def inner_close
|
401
423
|
@har_recorders.each do |har_id, params|
|
402
424
|
har = ChannelOwners::Artifact.from(@channel.send_message_to_server('harExport', harId: har_id))
|
403
425
|
# Server side will compress artifact if content is attach or if file is .zip.
|
@@ -413,11 +435,6 @@ module Playwright
|
|
413
435
|
|
414
436
|
har.delete
|
415
437
|
end
|
416
|
-
@channel.send_message_to_server('close')
|
417
|
-
@closed_promise.value!
|
418
|
-
nil
|
419
|
-
rescue => err
|
420
|
-
raise unless safe_close_error?(err)
|
421
438
|
end
|
422
439
|
|
423
440
|
# REMARK: enable_debug_console is playwright-ruby-client specific method.
|
@@ -459,6 +476,10 @@ module Playwright
|
|
459
476
|
end
|
460
477
|
end
|
461
478
|
|
479
|
+
private def effective_close_reason
|
480
|
+
@close_reason || @browser&.send(:close_reason)
|
481
|
+
end
|
482
|
+
|
462
483
|
def expect_console_message(predicate: nil, timeout: nil, &block)
|
463
484
|
params = {
|
464
485
|
predicate: predicate,
|
@@ -502,10 +523,14 @@ module Playwright
|
|
502
523
|
end
|
503
524
|
|
504
525
|
# called from InputFiles
|
505
|
-
# @param
|
526
|
+
# @param filepath [string]
|
506
527
|
# @return [WritableStream]
|
507
|
-
private def create_temp_file(
|
508
|
-
result = @channel.send_message_to_server(
|
528
|
+
private def create_temp_file(filepath)
|
529
|
+
result = @channel.send_message_to_server(
|
530
|
+
'createTempFile',
|
531
|
+
name: File.basename(filepath),
|
532
|
+
lastModifiedMs: File.mtime(filepath).to_i * 1000,
|
533
|
+
)
|
509
534
|
ChannelOwners::WritableStream.from(result)
|
510
535
|
end
|
511
536
|
end
|
@@ -301,6 +301,7 @@ module Playwright
|
|
301
301
|
path: nil,
|
302
302
|
quality: nil,
|
303
303
|
scale: nil,
|
304
|
+
style: nil,
|
304
305
|
timeout: nil,
|
305
306
|
type: nil)
|
306
307
|
|
@@ -312,6 +313,7 @@ module Playwright
|
|
312
313
|
path: path,
|
313
314
|
quality: quality,
|
314
315
|
scale: scale,
|
316
|
+
style: style,
|
315
317
|
timeout: timeout,
|
316
318
|
type: type,
|
317
319
|
}.compact
|
@@ -71,12 +71,24 @@ module Playwright
|
|
71
71
|
ChannelOwners::Response.from_nullable(resp)
|
72
72
|
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
class CrashedError < StandardError
|
75
|
+
def initialize
|
76
|
+
super('Navigation failed because page crashed!')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class FrameAlreadyDetachedError < StandardError
|
81
|
+
def initialize
|
82
|
+
super('Navigating frame was detached!')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private def setup_navigation_waiter(wait_name:, timeout_value:)
|
87
|
+
Waiter.new(page, wait_name: "frame.#{wait_name}").tap do |waiter|
|
88
|
+
waiter.reject_on_event(@page, Events::Page::Close, -> { @page.send(:close_error_with_reason) })
|
89
|
+
waiter.reject_on_event(@page, Events::Page::Crash, CrashedError.new)
|
90
|
+
waiter.reject_on_event(@page, Events::Page::FrameDetached, FrameAlreadyDetachedError.new, predicate: -> (frame) { frame == self })
|
91
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout_value}ms exceeded.")
|
80
92
|
end
|
81
93
|
end
|
82
94
|
|
@@ -85,21 +97,30 @@ module Playwright
|
|
85
97
|
option_timeout = timeout || @page.send(:timeout_settings).navigation_timeout
|
86
98
|
time_start = Time.now
|
87
99
|
|
88
|
-
|
100
|
+
waiter = setup_navigation_waiter(wait_name: :expect_navigation, timeout_value: option_timeout)
|
89
101
|
|
102
|
+
to_url = url ? " to \"#{url}\"" : ''
|
103
|
+
waiter.log("waiting for navigation#{to_url} until '#{option_wait_until}'")
|
90
104
|
predicate =
|
91
105
|
if url
|
92
106
|
matcher = UrlMatcher.new(url, base_url: @page.context.send(:base_url))
|
93
|
-
->(event) {
|
107
|
+
->(event) {
|
108
|
+
if event['error']
|
109
|
+
true
|
110
|
+
else
|
111
|
+
waiter.log(" navigated to \"#{event['url']}\"")
|
112
|
+
matcher.match?(event['url'])
|
113
|
+
end
|
114
|
+
}
|
94
115
|
else
|
95
116
|
->(_) { true }
|
96
117
|
end
|
97
118
|
|
98
|
-
|
119
|
+
waiter.wait_for_event(@event_emitter, 'navigated', predicate: predicate)
|
99
120
|
|
100
121
|
block&.call
|
101
122
|
|
102
|
-
event =
|
123
|
+
event = waiter.result.value!
|
103
124
|
if event['error']
|
104
125
|
raise event['error']
|
105
126
|
end
|
@@ -135,11 +156,14 @@ module Playwright
|
|
135
156
|
return
|
136
157
|
end
|
137
158
|
|
138
|
-
|
159
|
+
waiter = setup_navigation_waiter(wait_name: :wait_for_load_state, timeout_value: option_timeout)
|
139
160
|
|
140
|
-
predicate = ->(
|
141
|
-
|
142
|
-
|
161
|
+
predicate = ->(actual_state) {
|
162
|
+
waiter.log("\"#{actual_state}\" event fired")
|
163
|
+
actual_state == option_state
|
164
|
+
}
|
165
|
+
waiter.wait_for_event(@event_emitter, 'loadstate', predicate: predicate)
|
166
|
+
waiter.result.value!
|
143
167
|
|
144
168
|
nil
|
145
169
|
end
|
@@ -4,7 +4,7 @@ require_relative '../locator_utils'
|
|
4
4
|
module Playwright
|
5
5
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_page.py
|
6
6
|
define_channel_owner :Page do
|
7
|
-
include Utils::Errors::
|
7
|
+
include Utils::Errors::TargetClosedErrorMethods
|
8
8
|
include LocatorUtils
|
9
9
|
attr_writer :owned_context
|
10
10
|
|
@@ -33,10 +33,12 @@ module Playwright
|
|
33
33
|
@frames = Set.new
|
34
34
|
@frames << @main_frame
|
35
35
|
@opener = ChannelOwners::Page.from_nullable(@initializer['opener'])
|
36
|
+
@close_reason = nil
|
36
37
|
|
37
38
|
@channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
|
39
|
+
@closed_or_crashed_promise = Concurrent::Promises.resolvable_future
|
38
40
|
@channel.once('close', ->(_) { on_close })
|
39
|
-
@channel.on('crash', ->(_) {
|
41
|
+
@channel.on('crash', ->(_) { on_crash })
|
40
42
|
@channel.on('download', method(:on_download))
|
41
43
|
@channel.on('fileChooser', ->(params) {
|
42
44
|
chooser = FileChooserImpl.new(
|
@@ -147,9 +149,19 @@ module Playwright
|
|
147
149
|
@closed = true
|
148
150
|
@browser_context.send(:remove_page, self)
|
149
151
|
@browser_context.send(:remove_background_page, self)
|
152
|
+
if @closed_or_crashed_promise.pending?
|
153
|
+
@closed_or_crashed_promise.fulfill(close_error_with_reason)
|
154
|
+
end
|
150
155
|
emit(Events::Page::Close)
|
151
156
|
end
|
152
157
|
|
158
|
+
private def on_crash
|
159
|
+
if @closed_or_crashed_promise.pending?
|
160
|
+
@closed_or_crashed_promise.fulfill(TargetClosedError.new)
|
161
|
+
end
|
162
|
+
emit(Events::Page::Crash)
|
163
|
+
end
|
164
|
+
|
153
165
|
private def on_download(params)
|
154
166
|
artifact = ChannelOwners::Artifact.from(params['artifact'])
|
155
167
|
download = DownloadImpl.new(
|
@@ -402,6 +414,11 @@ module Playwright
|
|
402
414
|
update_interception_patterns
|
403
415
|
end
|
404
416
|
|
417
|
+
def unroute_all(behavior: nil)
|
418
|
+
@routes.clear
|
419
|
+
update_interception_patterns
|
420
|
+
end
|
421
|
+
|
405
422
|
def unroute(url, handler: nil)
|
406
423
|
@routes.reject! do |handler_entry|
|
407
424
|
handler_entry.same_value?(url: url, handler: handler)
|
@@ -445,6 +462,7 @@ module Playwright
|
|
445
462
|
path: nil,
|
446
463
|
quality: nil,
|
447
464
|
scale: nil,
|
465
|
+
style: nil,
|
448
466
|
timeout: nil,
|
449
467
|
type: nil)
|
450
468
|
|
@@ -458,6 +476,7 @@ module Playwright
|
|
458
476
|
animations: animations,
|
459
477
|
caret: caret,
|
460
478
|
scale: scale,
|
479
|
+
style: style,
|
461
480
|
timeout: timeout,
|
462
481
|
}.compact
|
463
482
|
if mask.is_a?(Enumerable)
|
@@ -479,7 +498,8 @@ module Playwright
|
|
479
498
|
@main_frame.title
|
480
499
|
end
|
481
500
|
|
482
|
-
def close(runBeforeUnload: nil)
|
501
|
+
def close(runBeforeUnload: nil, reason: nil)
|
502
|
+
@close_reason = reason
|
483
503
|
if @owned_context
|
484
504
|
@owned_context.close
|
485
505
|
else
|
@@ -488,7 +508,7 @@ module Playwright
|
|
488
508
|
end
|
489
509
|
nil
|
490
510
|
rescue => err
|
491
|
-
raise if !
|
511
|
+
raise if !target_closed_error?(err) || !runBeforeUnload
|
492
512
|
end
|
493
513
|
|
494
514
|
def closed?
|
@@ -878,34 +898,34 @@ module Playwright
|
|
878
898
|
end
|
879
899
|
end
|
880
900
|
|
881
|
-
class AlreadyClosedError < StandardError
|
882
|
-
def initialize
|
883
|
-
super('Page closed')
|
884
|
-
end
|
885
|
-
end
|
886
|
-
|
887
901
|
class FrameAlreadyDetachedError < StandardError
|
888
902
|
def initialize
|
889
903
|
super('Navigating frame was detached!')
|
890
904
|
end
|
891
905
|
end
|
892
906
|
|
907
|
+
private def close_error_with_reason
|
908
|
+
reason = @close_reason || @browser_context.send(:effective_close_reason)
|
909
|
+
TargetClosedError.new(message: reason)
|
910
|
+
end
|
911
|
+
|
893
912
|
def expect_event(event, predicate: nil, timeout: nil, &block)
|
894
|
-
|
895
|
-
|
913
|
+
waiter = Waiter.new(self, wait_name: "Page.expect_event(#{event})")
|
914
|
+
timeout_value = timeout || @timeout_settings.timeout
|
915
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout_value}ms exceeded while waiting for event \"#{event}\"")
|
896
916
|
|
897
917
|
unless event == Events::Page::Crash
|
898
|
-
|
918
|
+
waiter.reject_on_event(self, Events::Page::Crash, CrashedError.new)
|
899
919
|
end
|
900
920
|
|
901
921
|
unless event == Events::Page::Close
|
902
|
-
|
922
|
+
waiter.reject_on_event(self, Events::Page::Close, -> { close_error_with_reason })
|
903
923
|
end
|
904
924
|
|
905
|
-
|
925
|
+
waiter.wait_for_event(self, event, predicate: predicate)
|
906
926
|
block&.call
|
907
927
|
|
908
|
-
|
928
|
+
waiter.result.value!
|
909
929
|
end
|
910
930
|
|
911
931
|
def expect_console_message(predicate: nil, timeout: nil, &block)
|
@@ -33,29 +33,24 @@ module Playwright
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
class PageClosedError < StandardError
|
37
|
-
def initialize
|
38
|
-
super('Page closed')
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
36
|
def expect_event(event, predicate: nil, timeout: nil, &block)
|
43
|
-
|
44
|
-
|
37
|
+
waiter = Waiter.new(self, wait_name: "WebSocket.expect_event(#{event})")
|
38
|
+
timeout_value = timeout || @parent.send(:timeout_settings).timeout
|
39
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout_value}ms exceeded while waiting for event \"#{event}\"")
|
45
40
|
|
46
41
|
unless event == Events::WebSocket::Close
|
47
|
-
|
42
|
+
waiter.reject_on_event(self, Events::WebSocket::Close, SocketClosedError.new)
|
48
43
|
end
|
49
44
|
|
50
45
|
unless event == Events::WebSocket::Error
|
51
|
-
|
46
|
+
waiter.reject_on_event(self, Events::WebSocket::Error, SocketError.new)
|
52
47
|
end
|
53
48
|
|
54
|
-
|
55
|
-
|
49
|
+
waiter.reject_on_event(@parent, 'close', -> { @parent.send(:close_error_with_reason) })
|
50
|
+
waiter.wait_for_event(self, event, predicate: predicate)
|
56
51
|
block&.call
|
57
52
|
|
58
|
-
|
53
|
+
waiter.result.value!
|
59
54
|
end
|
60
55
|
alias_method :wait_for_event, :expect_event
|
61
56
|
|
@@ -23,6 +23,7 @@ module Playwright
|
|
23
23
|
@root_object = RootChannelOwner.new(self)
|
24
24
|
@remote = false
|
25
25
|
@tracing_count = 0
|
26
|
+
@closed_error = nil
|
26
27
|
end
|
27
28
|
|
28
29
|
attr_reader :local_utils
|
@@ -41,6 +42,15 @@ module Playwright
|
|
41
42
|
|
42
43
|
def stop
|
43
44
|
@transport.stop
|
45
|
+
cleanup
|
46
|
+
end
|
47
|
+
|
48
|
+
def cleanup(cause: nil)
|
49
|
+
@closed_error = cause || TargetClosedError.new
|
50
|
+
@callbacks.each_value do |callback|
|
51
|
+
callback.reject(@closed_error)
|
52
|
+
end
|
53
|
+
@callbacks.clear
|
44
54
|
end
|
45
55
|
|
46
56
|
def initialize_playwright
|
@@ -60,6 +70,8 @@ module Playwright
|
|
60
70
|
end
|
61
71
|
|
62
72
|
def async_send_message_to_server(guid, method, params, metadata: nil)
|
73
|
+
return if @closed_error
|
74
|
+
|
63
75
|
callback = Concurrent::Promises.resolvable_future
|
64
76
|
|
65
77
|
with_generated_id do |id|
|
@@ -130,6 +142,8 @@ module Playwright
|
|
130
142
|
end
|
131
143
|
|
132
144
|
def dispatch(msg)
|
145
|
+
return if @closed_error
|
146
|
+
|
133
147
|
id = msg['id']
|
134
148
|
if id
|
135
149
|
callback = @callbacks.delete(id)
|
@@ -139,8 +153,10 @@ module Playwright
|
|
139
153
|
end
|
140
154
|
|
141
155
|
error = msg['error']
|
142
|
-
if error
|
143
|
-
|
156
|
+
if error && !msg['result']
|
157
|
+
parsed_error = ::Playwright::Error.parse(error['error'])
|
158
|
+
parsed_error.log = msg['log']
|
159
|
+
callback.reject(parsed_error)
|
144
160
|
else
|
145
161
|
result = replace_guids_with_channels(msg['result'])
|
146
162
|
callback.fulfill(result)
|
data/lib/playwright/errors.rb
CHANGED
@@ -7,6 +7,11 @@ module Playwright
|
|
7
7
|
message: error_payload['message'],
|
8
8
|
stack: error_payload['stack'],
|
9
9
|
)
|
10
|
+
elsif error_payload['name'] == 'TargetClosedError'
|
11
|
+
TargetClosedError.new(
|
12
|
+
message: error_payload['message'],
|
13
|
+
stack: error_payload['stack'],
|
14
|
+
)
|
10
15
|
else
|
11
16
|
new(
|
12
17
|
name: error_payload['name'],
|
@@ -19,14 +24,20 @@ module Playwright
|
|
19
24
|
# @param name [String]
|
20
25
|
# @param message [String]
|
21
26
|
# @param stack [Array<String>]
|
22
|
-
def initialize(
|
23
|
-
super(
|
27
|
+
def initialize(message:, name: nil, stack: nil)
|
28
|
+
super(message)
|
24
29
|
@name = name
|
25
30
|
@message = message
|
26
31
|
@stack = stack
|
27
32
|
end
|
28
33
|
|
29
34
|
attr_reader :name, :message, :stack
|
35
|
+
|
36
|
+
def log=(log)
|
37
|
+
return unless log
|
38
|
+
format_call_log = log.join("\n - ")
|
39
|
+
@message = "#{@message}\nCall log:\n#{format_call_log}\n"
|
40
|
+
end
|
30
41
|
end
|
31
42
|
|
32
43
|
class DriverCrashedError < StandardError
|
@@ -41,6 +52,13 @@ module Playwright
|
|
41
52
|
end
|
42
53
|
end
|
43
54
|
|
55
|
+
class TargetClosedError < Error
|
56
|
+
def initialize(message: nil, stack: [])
|
57
|
+
_message = message || 'Target page, context or browser has been closed'
|
58
|
+
super(name: 'TargetClosedError', message: _message, stack: stack)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
44
62
|
class WebError
|
45
63
|
def initialize(error, page)
|
46
64
|
@error = error
|
@@ -15,7 +15,7 @@ module Playwright
|
|
15
15
|
|
16
16
|
def as_method_and_params
|
17
17
|
if has_large_file?
|
18
|
-
['
|
18
|
+
['setInputFiles', params_for_set_input_file_paths]
|
19
19
|
else
|
20
20
|
['setInputFiles', params_for_set_input_files]
|
21
21
|
end
|
@@ -40,7 +40,7 @@ module Playwright
|
|
40
40
|
writable_streams = @files.map do |file|
|
41
41
|
case file
|
42
42
|
when String
|
43
|
-
writable_stream = @context.send(:create_temp_file,
|
43
|
+
writable_stream = @context.send(:create_temp_file, file)
|
44
44
|
|
45
45
|
File.open(file, 'rb') do |file|
|
46
46
|
writable_stream.write(file)
|
@@ -48,7 +48,7 @@ module Playwright
|
|
48
48
|
|
49
49
|
writable_stream.channel
|
50
50
|
when File
|
51
|
-
writable_stream = @context.send(:create_temp_file,
|
51
|
+
writable_stream = @context.send(:create_temp_file, file.path)
|
52
52
|
writable_stream.write(file)
|
53
53
|
|
54
54
|
writable_stream.channel
|
@@ -78,7 +78,7 @@ module Playwright
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
{
|
81
|
+
{ payloads: file_payloads }
|
82
82
|
end
|
83
83
|
|
84
84
|
private def raise_argument_error
|