playwright-ruby-client 1.39.0 → 1.40.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/documentation/docs/api/api_request_context.md +1 -2
- data/documentation/docs/api/browser.md +10 -14
- data/documentation/docs/api/browser_context.md +32 -51
- data/documentation/docs/api/browser_type.md +8 -12
- data/documentation/docs/api/dialog.md +15 -18
- data/documentation/docs/api/download.md +10 -12
- data/documentation/docs/api/element_handle.md +9 -7
- data/documentation/docs/api/frame.md +28 -55
- data/documentation/docs/api/locator.md +24 -23
- data/documentation/docs/api/locator_assertions.md +652 -0
- data/documentation/docs/api/page.md +53 -103
- data/documentation/docs/api/playwright.md +20 -23
- data/documentation/docs/api/selectors.md +29 -34
- 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 +43 -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.rb +1 -1
- 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 +35 -15
- data/lib/playwright/channel_owners/frame.rb +38 -14
- data/lib/playwright/channel_owners/page.rb +29 -16
- data/lib/playwright/channel_owners/web_socket.rb +8 -13
- data/lib/playwright/connection.rb +18 -2
- data/lib/playwright/errors.rb +22 -2
- data/lib/playwright/input_files.rb +4 -4
- data/lib/playwright/javascript/value_serializer.rb +1 -1
- data/lib/playwright/locator_assertions_impl.rb +417 -0
- data/lib/playwright/locator_impl.rb +24 -5
- data/lib/playwright/test.rb +68 -0
- 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 +3 -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 +4 -1
- data/lib/playwright_api/frame.rb +4 -1
- data/lib/playwright_api/locator.rb +9 -1
- data/lib/playwright_api/locator_assertions.rb +561 -0
- data/lib/playwright_api/page.rb +16 -13
- data/lib/playwright_api/request.rb +4 -4
- data/lib/playwright_api/worker.rb +4 -4
- data/sig/playwright.rbs +48 -5
- metadata +9 -4
- 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
|
data/lib/playwright/channel.rb
CHANGED
@@ -48,7 +48,7 @@ module Playwright
|
|
48
48
|
|
49
49
|
private def with_logging(&block)
|
50
50
|
locations = caller_locations
|
51
|
-
first_api_call_location_idx = locations.index { |loc| loc.absolute_path
|
51
|
+
first_api_call_location_idx = locations.index { |loc| loc.absolute_path&.include?('playwright_api') }
|
52
52
|
unless first_api_call_location_idx
|
53
53
|
return block.call(nil)
|
54
54
|
end
|
@@ -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:)
|
@@ -382,13 +384,17 @@ module Playwright
|
|
382
384
|
end
|
383
385
|
|
384
386
|
def expect_event(event, predicate: nil, timeout: nil, &block)
|
385
|
-
|
386
|
-
|
387
|
-
|
387
|
+
waiter = Waiter.new(self, wait_name: "browser_context.expect_event(#{event})")
|
388
|
+
timeout_value = timeout || @timeout_settings.timeout
|
389
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout}ms exceeded while waiting for event \"#{event}\"")
|
390
|
+
unless event == Events::BrowserContext::Close
|
391
|
+
waiter.reject_on_event(self, Events::BrowserContext::Close, TargetClosedError.new)
|
392
|
+
end
|
393
|
+
waiter.wait_for_event(self, event, predicate: predicate)
|
388
394
|
|
389
395
|
block&.call
|
390
396
|
|
391
|
-
|
397
|
+
waiter.result.value!
|
392
398
|
end
|
393
399
|
|
394
400
|
private def on_close
|
@@ -397,7 +403,18 @@ module Playwright
|
|
397
403
|
@closed_promise.fulfill(true)
|
398
404
|
end
|
399
405
|
|
400
|
-
def close
|
406
|
+
def close(reason: nil)
|
407
|
+
return if @close_was_called
|
408
|
+
@close_was_called = true
|
409
|
+
@close_reason = reason
|
410
|
+
|
411
|
+
inner_close
|
412
|
+
@channel.send_message_to_server('close', { reason: reason }.compact)
|
413
|
+
@closed_promise.value!
|
414
|
+
nil
|
415
|
+
end
|
416
|
+
|
417
|
+
private def inner_close
|
401
418
|
@har_recorders.each do |har_id, params|
|
402
419
|
har = ChannelOwners::Artifact.from(@channel.send_message_to_server('harExport', harId: har_id))
|
403
420
|
# Server side will compress artifact if content is attach or if file is .zip.
|
@@ -413,11 +430,6 @@ module Playwright
|
|
413
430
|
|
414
431
|
har.delete
|
415
432
|
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
433
|
end
|
422
434
|
|
423
435
|
# REMARK: enable_debug_console is playwright-ruby-client specific method.
|
@@ -459,6 +471,10 @@ module Playwright
|
|
459
471
|
end
|
460
472
|
end
|
461
473
|
|
474
|
+
private def effective_close_reason
|
475
|
+
@close_reason || @browser&.send(:close_reason)
|
476
|
+
end
|
477
|
+
|
462
478
|
def expect_console_message(predicate: nil, timeout: nil, &block)
|
463
479
|
params = {
|
464
480
|
predicate: predicate,
|
@@ -502,10 +518,14 @@ module Playwright
|
|
502
518
|
end
|
503
519
|
|
504
520
|
# called from InputFiles
|
505
|
-
# @param
|
521
|
+
# @param filepath [string]
|
506
522
|
# @return [WritableStream]
|
507
|
-
private def create_temp_file(
|
508
|
-
result = @channel.send_message_to_server(
|
523
|
+
private def create_temp_file(filepath)
|
524
|
+
result = @channel.send_message_to_server(
|
525
|
+
'createTempFile',
|
526
|
+
name: File.basename(filepath),
|
527
|
+
lastModifiedMs: File.mtime(filepath).to_i * 1000,
|
528
|
+
)
|
509
529
|
ChannelOwners::WritableStream.from(result)
|
510
530
|
end
|
511
531
|
end
|
@@ -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(
|
@@ -479,7 +491,8 @@ module Playwright
|
|
479
491
|
@main_frame.title
|
480
492
|
end
|
481
493
|
|
482
|
-
def close(runBeforeUnload: nil)
|
494
|
+
def close(runBeforeUnload: nil, reason: nil)
|
495
|
+
@close_reason = reason
|
483
496
|
if @owned_context
|
484
497
|
@owned_context.close
|
485
498
|
else
|
@@ -488,7 +501,7 @@ module Playwright
|
|
488
501
|
end
|
489
502
|
nil
|
490
503
|
rescue => err
|
491
|
-
raise if !
|
504
|
+
raise if !target_closed_error?(err) || !runBeforeUnload
|
492
505
|
end
|
493
506
|
|
494
507
|
def closed?
|
@@ -878,34 +891,34 @@ module Playwright
|
|
878
891
|
end
|
879
892
|
end
|
880
893
|
|
881
|
-
class AlreadyClosedError < StandardError
|
882
|
-
def initialize
|
883
|
-
super('Page closed')
|
884
|
-
end
|
885
|
-
end
|
886
|
-
|
887
894
|
class FrameAlreadyDetachedError < StandardError
|
888
895
|
def initialize
|
889
896
|
super('Navigating frame was detached!')
|
890
897
|
end
|
891
898
|
end
|
892
899
|
|
900
|
+
private def close_error_with_reason
|
901
|
+
reason = @close_reason || @browser_context.send(:effective_close_reason)
|
902
|
+
TargetClosedError.new(message: reason)
|
903
|
+
end
|
904
|
+
|
893
905
|
def expect_event(event, predicate: nil, timeout: nil, &block)
|
894
|
-
|
895
|
-
|
906
|
+
waiter = Waiter.new(self, wait_name: "Page.expect_event(#{event})")
|
907
|
+
timeout_value = timeout || @timeout_settings.timeout
|
908
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout_value}ms exceeded while waiting for event \"#{event}\"")
|
896
909
|
|
897
910
|
unless event == Events::Page::Crash
|
898
|
-
|
911
|
+
waiter.reject_on_event(self, Events::Page::Crash, CrashedError.new)
|
899
912
|
end
|
900
913
|
|
901
914
|
unless event == Events::Page::Close
|
902
|
-
|
915
|
+
waiter.reject_on_event(self, Events::Page::Close, -> { close_error_with_reason })
|
903
916
|
end
|
904
917
|
|
905
|
-
|
918
|
+
waiter.wait_for_event(self, event, predicate: predicate)
|
906
919
|
block&.call
|
907
920
|
|
908
|
-
|
921
|
+
waiter.result.value!
|
909
922
|
end
|
910
923
|
|
911
924
|
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
|
@@ -49,4 +67,6 @@ module Playwright
|
|
49
67
|
|
50
68
|
attr_reader :error, :page
|
51
69
|
end
|
70
|
+
|
71
|
+
class AssertionError < StandardError; end
|
52
72
|
end
|
@@ -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
|