playwright-ruby-client 1.59.1 → 1.61.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.md +25 -1
- data/documentation/docs/api/api_request_context.md +13 -11
- data/documentation/docs/api/api_response.md +18 -0
- data/documentation/docs/api/browser.md +18 -0
- data/documentation/docs/api/browser_context.md +7 -1
- data/documentation/docs/api/browser_type.md +19 -0
- data/documentation/docs/api/credentials.md +132 -0
- data/documentation/docs/api/frame.md +5 -4
- data/documentation/docs/api/frame_locator.md +1 -0
- data/documentation/docs/api/locator.md +37 -2
- data/documentation/docs/api/locator_assertions.md +1 -1
- data/documentation/docs/api/page.md +24 -4
- data/documentation/docs/api/page_assertions.md +28 -0
- data/documentation/docs/api/playwright.md +5 -0
- data/documentation/docs/api/touchscreen.md +1 -1
- data/documentation/docs/api/tracing.md +29 -0
- data/documentation/docs/api/web_storage.md +65 -0
- data/documentation/docs/include/api_coverage.md +30 -56
- data/lib/playwright/api_request_impl.rb +70 -0
- data/lib/playwright/api_response_impl.rb +8 -0
- data/lib/playwright/channel_owners/api_request_context.rb +5 -1
- data/lib/playwright/channel_owners/binding_call.rb +3 -9
- data/lib/playwright/channel_owners/browser.rb +17 -0
- data/lib/playwright/channel_owners/browser_context.rb +12 -55
- data/lib/playwright/channel_owners/browser_type.rb +35 -1
- data/lib/playwright/channel_owners/frame.rb +118 -13
- data/lib/playwright/channel_owners/json_pipe.rb +4 -0
- data/lib/playwright/channel_owners/local_utils.rb +11 -2
- data/lib/playwright/channel_owners/page.rb +28 -13
- data/lib/playwright/channel_owners/playwright.rb +4 -0
- data/lib/playwright/channel_owners/tracing.rb +105 -4
- data/lib/playwright/connection.rb +12 -2
- data/lib/playwright/console_message_impl.rb +10 -1
- data/lib/playwright/credentials_impl.rb +35 -0
- data/lib/playwright/errors.rb +7 -3
- data/lib/playwright/events.rb +7 -0
- data/lib/playwright/json_pipe_transport.rb +40 -0
- data/lib/playwright/locator_assertions_impl.rb +21 -4
- data/lib/playwright/locator_impl.rb +17 -3
- data/lib/playwright/locator_utils.rb +11 -1
- data/lib/playwright/page_assertions_impl.rb +33 -3
- data/lib/playwright/screencast.rb +8 -2
- data/lib/playwright/url_matcher.rb +35 -0
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/waiter.rb +9 -41
- data/lib/playwright/web_storage_impl.rb +34 -0
- data/lib/playwright.rb +1 -0
- data/lib/playwright_api/api_request.rb +1 -1
- data/lib/playwright_api/api_request_context.rb +21 -17
- data/lib/playwright_api/api_response.rb +12 -0
- data/lib/playwright_api/browser.rb +8 -8
- data/lib/playwright_api/browser_context.rb +20 -13
- data/lib/playwright_api/browser_type.rb +12 -9
- data/lib/playwright_api/cdp_session.rb +6 -6
- data/lib/playwright_api/credentials.rb +120 -0
- data/lib/playwright_api/dialog.rb +6 -6
- data/lib/playwright_api/element_handle.rb +6 -6
- data/lib/playwright_api/frame.rb +25 -14
- data/lib/playwright_api/frame_locator.rb +2 -1
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/locator.rb +39 -10
- data/lib/playwright_api/locator_assertions.rb +2 -2
- data/lib/playwright_api/page.rb +44 -25
- data/lib/playwright_api/page_assertions.rb +22 -0
- data/lib/playwright_api/playwright.rb +7 -7
- data/lib/playwright_api/request.rb +8 -8
- data/lib/playwright_api/response.rb +6 -6
- data/lib/playwright_api/route.rb +6 -6
- data/lib/playwright_api/touchscreen.rb +1 -1
- data/lib/playwright_api/tracing.rb +27 -4
- data/lib/playwright_api/web_socket.rb +6 -6
- data/lib/playwright_api/web_storage.rb +48 -0
- data/lib/playwright_api/worker.rb +8 -8
- data/sig/playwright.rbs +51 -39
- metadata +11 -12
- data/documentation/docs/api/experimental/android.md +0 -42
- data/documentation/docs/api/experimental/android_device.md +0 -109
- data/documentation/docs/api/experimental/android_input.md +0 -43
- data/documentation/docs/api/experimental/android_socket.md +0 -7
- data/documentation/docs/api/experimental/android_web_view.md +0 -7
- data/lib/playwright_api/android.rb +0 -68
- data/lib/playwright_api/android_device.rb +0 -229
- data/lib/playwright_api/android_input.rb +0 -34
- data/lib/playwright_api/android_socket.rb +0 -18
- data/lib/playwright_api/android_web_view.rb +0 -24
|
@@ -37,8 +37,12 @@ module Playwright
|
|
|
37
37
|
@channel.async_send_message_to_server('harClose', harId: har_id)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
def har_unzip(zip_file, har_file)
|
|
41
|
-
@channel.send_message_to_server('harUnzip',
|
|
40
|
+
def har_unzip(zip_file, har_file, resources_dir: nil)
|
|
41
|
+
@channel.send_message_to_server('harUnzip', {
|
|
42
|
+
zipFile: zip_file,
|
|
43
|
+
harFile: har_file,
|
|
44
|
+
resourcesDir: resources_dir,
|
|
45
|
+
}.compact)
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
def tracing_started(traces_dir, trace_name)
|
|
@@ -58,6 +62,11 @@ module Playwright
|
|
|
58
62
|
nil
|
|
59
63
|
end
|
|
60
64
|
|
|
65
|
+
def connect(params)
|
|
66
|
+
result = @channel.send_message_to_server_result('connect', params)
|
|
67
|
+
ChannelOwners::JsonPipe.from(result['pipe'])
|
|
68
|
+
end
|
|
69
|
+
|
|
61
70
|
private def parse_device_descriptor(descriptor)
|
|
62
71
|
# This return value can be passed into Browser#new_context as it is.
|
|
63
72
|
# ex:
|
|
@@ -53,7 +53,7 @@ module Playwright
|
|
|
53
53
|
on_frame_detached(ChannelOwners::Frame.from(params['frame']))
|
|
54
54
|
})
|
|
55
55
|
@channel.on('pageError', ->(params) {
|
|
56
|
-
emit(Events::Page::PageError, Error.parse(params
|
|
56
|
+
emit(Events::Page::PageError, Error.parse(params.dig('error', 'error') || params['error']))
|
|
57
57
|
})
|
|
58
58
|
@channel.on('route', ->(params) { on_route(ChannelOwners::Route.from(params['route'])) })
|
|
59
59
|
if @initializer['video']
|
|
@@ -86,16 +86,26 @@ module Playwright
|
|
|
86
86
|
:viewport_size,
|
|
87
87
|
:main_frame
|
|
88
88
|
|
|
89
|
+
def local_storage
|
|
90
|
+
@local_storage ||= WebStorageImpl.new(self, 'local')
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def session_storage
|
|
94
|
+
@session_storage ||= WebStorageImpl.new(self, 'session')
|
|
95
|
+
end
|
|
96
|
+
|
|
89
97
|
private def on_frame_attached(frame)
|
|
90
98
|
frame.send(:update_page_from_page, self)
|
|
91
99
|
@frames << frame
|
|
92
100
|
emit(Events::Page::FrameAttached, frame)
|
|
101
|
+
@browser_context.emit(Events::BrowserContext::FrameAttached, frame)
|
|
93
102
|
end
|
|
94
103
|
|
|
95
104
|
private def on_frame_detached(frame)
|
|
96
105
|
@frames.delete(frame)
|
|
97
106
|
frame.detached = true
|
|
98
107
|
emit(Events::Page::FrameDetached, frame)
|
|
108
|
+
@browser_context.emit(Events::BrowserContext::FrameDetached, frame)
|
|
99
109
|
end
|
|
100
110
|
|
|
101
111
|
private def on_route(route)
|
|
@@ -153,6 +163,7 @@ module Playwright
|
|
|
153
163
|
@closed_or_crashed_promise.fulfill(close_error_with_reason)
|
|
154
164
|
end
|
|
155
165
|
emit(Events::Page::Close)
|
|
166
|
+
@browser_context.emit(Events::BrowserContext::PageClose, self)
|
|
156
167
|
end
|
|
157
168
|
|
|
158
169
|
private def on_crash
|
|
@@ -171,6 +182,7 @@ module Playwright
|
|
|
171
182
|
artifact: artifact,
|
|
172
183
|
)
|
|
173
184
|
emit(Events::Page::Download, download)
|
|
185
|
+
@browser_context.emit(Events::BrowserContext::Download, download)
|
|
174
186
|
end
|
|
175
187
|
|
|
176
188
|
private def on_viewport_size_changed(params)
|
|
@@ -309,12 +321,8 @@ module Playwright
|
|
|
309
321
|
ChannelOwners::Disposable.from(result['disposable'])
|
|
310
322
|
end
|
|
311
323
|
|
|
312
|
-
def expose_binding(name, callback
|
|
313
|
-
|
|
314
|
-
name: name,
|
|
315
|
-
needsHandle: handle,
|
|
316
|
-
}.compact
|
|
317
|
-
result = @channel.send_message_to_server_result('exposeBinding', params)
|
|
324
|
+
def expose_binding(name, callback)
|
|
325
|
+
result = @channel.send_message_to_server_result('exposeBinding', name: name)
|
|
318
326
|
@bindings[name] = callback
|
|
319
327
|
ChannelOwners::Disposable.from(result['disposable'])
|
|
320
328
|
end
|
|
@@ -436,7 +444,7 @@ module Playwright
|
|
|
436
444
|
|
|
437
445
|
def route_from_har(har, notFound: nil, update: nil, url: nil, updateContent: nil, updateMode: nil)
|
|
438
446
|
if update
|
|
439
|
-
@browser_context.send(:record_into_har, har, self, url: url, update_content: updateContent, update_mode: updateMode)
|
|
447
|
+
@browser_context.tracing.send(:record_into_har, har, self, url: url, update_content: updateContent, update_mode: updateMode)
|
|
440
448
|
return
|
|
441
449
|
end
|
|
442
450
|
|
|
@@ -513,13 +521,15 @@ module Playwright
|
|
|
513
521
|
end
|
|
514
522
|
if @owned_context
|
|
515
523
|
@owned_context.close
|
|
524
|
+
elsif runBeforeUnload
|
|
525
|
+
@channel.send_message_to_server('runBeforeUnload')
|
|
516
526
|
else
|
|
517
|
-
options = {
|
|
527
|
+
options = { reason: reason }.compact
|
|
518
528
|
@channel.send_message_to_server('close', options)
|
|
519
529
|
end
|
|
520
530
|
nil
|
|
521
531
|
rescue => err
|
|
522
|
-
raise if !target_closed_error?(err) ||
|
|
532
|
+
raise if !target_closed_error?(err) || runBeforeUnload
|
|
523
533
|
end
|
|
524
534
|
|
|
525
535
|
def closed?
|
|
@@ -676,9 +686,14 @@ module Playwright
|
|
|
676
686
|
@channel.send_message_to_server('cancelPickLocator')
|
|
677
687
|
end
|
|
678
688
|
|
|
679
|
-
def
|
|
689
|
+
def hide_highlight
|
|
690
|
+
@channel.send_message_to_server('hideHighlight')
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
680
694
|
params = { selector: 'body' }
|
|
681
695
|
params[:timeout] = @timeout_settings.timeout(timeout)
|
|
696
|
+
params[:boxes] = boxes unless boxes.nil?
|
|
682
697
|
params[:depth] = depth if depth
|
|
683
698
|
params[:mode] = mode if mode
|
|
684
699
|
if _track
|
|
@@ -947,8 +962,8 @@ module Playwright
|
|
|
947
962
|
@main_frame.locator(result['selector'])
|
|
948
963
|
end
|
|
949
964
|
|
|
950
|
-
def snapshot_for_ai(timeout: nil, depth: nil, _track: nil)
|
|
951
|
-
aria_snapshot(mode: 'ai', timeout: timeout, depth: depth, _track: _track)
|
|
965
|
+
def snapshot_for_ai(timeout: nil, depth: nil, boxes: nil, _track: nil)
|
|
966
|
+
aria_snapshot(mode: 'ai', timeout: timeout, depth: depth, boxes: boxes, _track: _track)
|
|
952
967
|
end
|
|
953
968
|
|
|
954
969
|
def _assertions(timeout, is_not, message)
|
|
@@ -34,6 +34,10 @@ module Playwright
|
|
|
34
34
|
@connection.local_utils.devices
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
def request
|
|
38
|
+
@request ||= APIRequestImpl.new(self)
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
# used only from Playwright#connect_to_browser_server
|
|
38
42
|
private def pre_launched_browser
|
|
39
43
|
unless @initializer['preLaunchedBrowser']
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
define_channel_owner :Tracing do
|
|
3
|
+
private def after_initialize
|
|
4
|
+
@har_recorders = {}
|
|
5
|
+
@har_id = nil
|
|
6
|
+
end
|
|
7
|
+
|
|
3
8
|
def start(name: nil, title: nil, screenshots: nil, snapshots: nil, sources: nil, live: nil)
|
|
4
9
|
params = {
|
|
5
10
|
name: name,
|
|
@@ -38,10 +43,7 @@ module Playwright
|
|
|
38
43
|
end
|
|
39
44
|
|
|
40
45
|
private def do_stop_chunk(file_path:)
|
|
41
|
-
|
|
42
|
-
@is_tracing = false
|
|
43
|
-
@connection.set_in_tracing(false)
|
|
44
|
-
end
|
|
46
|
+
reset_stack_counter
|
|
45
47
|
local_utils = @connection.local_utils
|
|
46
48
|
|
|
47
49
|
unless file_path
|
|
@@ -99,6 +101,105 @@ module Playwright
|
|
|
99
101
|
)
|
|
100
102
|
end
|
|
101
103
|
|
|
104
|
+
def start_har(path, content: nil, mode: nil, urlFilter: nil, resourcesDir: nil)
|
|
105
|
+
raise 'HAR recording has already been started' if @har_id
|
|
106
|
+
if resourcesDir && path.end_with?('.zip')
|
|
107
|
+
raise 'resourcesDir option is not compatible with a .zip har file'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
default_content = path.end_with?('.zip') ? 'attach' : 'embed'
|
|
111
|
+
@har_id = record_into_har(path, nil,
|
|
112
|
+
url: urlFilter,
|
|
113
|
+
update_content: content || default_content,
|
|
114
|
+
update_mode: mode || 'full',
|
|
115
|
+
resources_dir: resourcesDir,
|
|
116
|
+
)
|
|
117
|
+
DisposableStub.new { stop_har }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def stop_har
|
|
121
|
+
har_id = @har_id
|
|
122
|
+
raise 'HAR recording has not been started' unless har_id
|
|
123
|
+
|
|
124
|
+
@har_id = nil
|
|
125
|
+
export_har(har_id)
|
|
126
|
+
nil
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private def record_into_har(har, page, url:, update_content:, update_mode:, resources_dir: nil)
|
|
130
|
+
options = {
|
|
131
|
+
content: update_content || 'attach',
|
|
132
|
+
mode: update_mode || 'minimal',
|
|
133
|
+
harPath: har.end_with?('.zip') ? nil : har,
|
|
134
|
+
resourcesDir: resources_dir,
|
|
135
|
+
}.compact
|
|
136
|
+
|
|
137
|
+
if url.is_a?(Regexp)
|
|
138
|
+
regex = ::Playwright::JavaScript::Regex.new(url)
|
|
139
|
+
options[:urlRegexSource] = regex.source
|
|
140
|
+
options[:urlRegexFlags] = regex.flag
|
|
141
|
+
elsif url.is_a?(String)
|
|
142
|
+
options[:urlGlob] = url
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
params = { options: options }
|
|
146
|
+
params[:page] = page.channel if page
|
|
147
|
+
|
|
148
|
+
result = @channel.send_message_to_server_result('harStart', params)
|
|
149
|
+
har_id = result['harId'] || result[:harId]
|
|
150
|
+
@har_recorders[har_id] = { path: har, resources_dir: resources_dir }
|
|
151
|
+
har_id
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private def export_har(har_id)
|
|
155
|
+
har_params = @har_recorders.delete(har_id)
|
|
156
|
+
return unless har_params
|
|
157
|
+
|
|
158
|
+
path = har_params[:path]
|
|
159
|
+
is_zip = path.end_with?('.zip')
|
|
160
|
+
local_utils = @connection.local_utils
|
|
161
|
+
|
|
162
|
+
if !@connection.remote?
|
|
163
|
+
result = @channel.send_message_to_server_result('harExport', harId: har_id, mode: 'entries')
|
|
164
|
+
return unless is_zip
|
|
165
|
+
raise 'Cannot save zipped HAR because localUtils is unavailable.' unless local_utils
|
|
166
|
+
|
|
167
|
+
local_utils.zip(
|
|
168
|
+
zipFile: path,
|
|
169
|
+
entries: result['entries'],
|
|
170
|
+
mode: 'write',
|
|
171
|
+
includeSources: false,
|
|
172
|
+
)
|
|
173
|
+
return
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
result = @channel.send_message_to_server_result('harExport', harId: har_id, mode: 'archive')
|
|
177
|
+
artifact = ChannelOwners::Artifact.from(result['artifact'])
|
|
178
|
+
if is_zip
|
|
179
|
+
artifact.save_as(path)
|
|
180
|
+
artifact.delete
|
|
181
|
+
return
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
raise 'Uncompressed har is not supported in thin clients' unless local_utils
|
|
185
|
+
|
|
186
|
+
tmp_path = "#{path}.tmp"
|
|
187
|
+
artifact.save_as(tmp_path)
|
|
188
|
+
local_utils.har_unzip(tmp_path, path, resources_dir: har_params[:resources_dir])
|
|
189
|
+
artifact.delete
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private def export_all_hars
|
|
193
|
+
@har_recorders.keys.each { |har_id| export_har(har_id) }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private def reset_stack_counter
|
|
197
|
+
if @is_tracing
|
|
198
|
+
@is_tracing = false
|
|
199
|
+
@connection.set_in_tracing(false)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
102
203
|
private def update_traces_dir(traces_dir)
|
|
103
204
|
@traces_dir = traces_dir
|
|
104
205
|
end
|
|
@@ -74,14 +74,18 @@ module Playwright
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def async_send_message_to_server(guid, method, params, metadata: nil)
|
|
77
|
+
if method == '__waitInfo__' && @closed_error
|
|
78
|
+
return Concurrent::Promises.fulfilled_future(nil)
|
|
79
|
+
end
|
|
77
80
|
return if @closed_error
|
|
78
81
|
|
|
79
82
|
callback = Concurrent::Promises.resolvable_future
|
|
83
|
+
fire_and_forget = method == '__waitInfo__'
|
|
80
84
|
|
|
81
85
|
with_generated_id do |id|
|
|
82
86
|
# register callback promise object first.
|
|
83
87
|
# @see https://github.com/YusukeIwaki/puppeteer-ruby/pull/34
|
|
84
|
-
@callbacks_mutex.synchronize { @callbacks[id] = callback }
|
|
88
|
+
@callbacks_mutex.synchronize { @callbacks[id] = callback } unless fire_and_forget
|
|
85
89
|
|
|
86
90
|
_metadata = {}
|
|
87
91
|
frames = []
|
|
@@ -112,6 +116,7 @@ module Playwright
|
|
|
112
116
|
callback.reject(err)
|
|
113
117
|
raise unless err.is_a?(Transport::AlreadyDisconnectedError)
|
|
114
118
|
end
|
|
119
|
+
callback.fulfill(nil) if fire_and_forget
|
|
115
120
|
|
|
116
121
|
if @tracing_count > 0 && !frames.empty? && guid != 'localUtils' && !remote?
|
|
117
122
|
@local_utils.add_stack_to_tracing_no_reply(id, frames)
|
|
@@ -168,6 +173,7 @@ module Playwright
|
|
|
168
173
|
if error && !msg['result']
|
|
169
174
|
parsed_error = ::Playwright::Error.parse(error['error'])
|
|
170
175
|
parsed_error.log = msg['log']
|
|
176
|
+
parsed_error.details = msg['errorDetails']
|
|
171
177
|
callback.reject(parsed_error)
|
|
172
178
|
else
|
|
173
179
|
result = replace_guids_with_channels(msg['result'])
|
|
@@ -213,7 +219,11 @@ module Playwright
|
|
|
213
219
|
return
|
|
214
220
|
end
|
|
215
221
|
|
|
216
|
-
object.
|
|
222
|
+
if object.is_a?(ChannelOwners::JsonPipe) && method == 'message'
|
|
223
|
+
object.channel.emit(method, params)
|
|
224
|
+
else
|
|
225
|
+
object.channel.emit(method, replace_guids_with_channels(params))
|
|
226
|
+
end
|
|
217
227
|
end
|
|
218
228
|
|
|
219
229
|
def replace_channels_with_guids(payload)
|
|
@@ -23,7 +23,16 @@ module Playwright
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def location
|
|
26
|
-
@event['location']
|
|
26
|
+
location = @event['location']
|
|
27
|
+
return location unless location
|
|
28
|
+
|
|
29
|
+
{
|
|
30
|
+
'url' => location['url'],
|
|
31
|
+
'line' => location['lineNumber'],
|
|
32
|
+
'column' => location['columnNumber'],
|
|
33
|
+
'lineNumber' => location['lineNumber'],
|
|
34
|
+
'columnNumber' => location['columnNumber'],
|
|
35
|
+
}
|
|
27
36
|
end
|
|
28
37
|
|
|
29
38
|
def timestamp
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Playwright
|
|
2
|
+
# ref: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/credentials.ts
|
|
3
|
+
define_api_implementation :CredentialsImpl do
|
|
4
|
+
# @param browser_context [ChannelOwners::BrowserContext]
|
|
5
|
+
def initialize(browser_context)
|
|
6
|
+
@browser_context = browser_context
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def install
|
|
10
|
+
@browser_context.channel.send_message_to_server('credentialsInstall')
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create(rpId, id: nil, userHandle: nil, privateKey: nil, publicKey: nil)
|
|
15
|
+
params = {
|
|
16
|
+
rpId: rpId,
|
|
17
|
+
id: id,
|
|
18
|
+
userHandle: userHandle,
|
|
19
|
+
privateKey: privateKey,
|
|
20
|
+
publicKey: publicKey,
|
|
21
|
+
}.compact
|
|
22
|
+
@browser_context.channel.send_message_to_server('credentialsCreate', params)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get(id: nil, rpId: nil)
|
|
26
|
+
params = { id: id, rpId: rpId }.compact
|
|
27
|
+
@browser_context.channel.send_message_to_server('credentialsGet', params)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delete(id)
|
|
31
|
+
@browser_context.channel.send_message_to_server('credentialsDelete', id: id)
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/playwright/errors.rb
CHANGED
|
@@ -31,10 +31,13 @@ module Playwright
|
|
|
31
31
|
@stack = stack
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
attr_reader :name, :message, :stack
|
|
34
|
+
attr_reader :name, :message, :stack, :raw_log
|
|
35
|
+
# Error details for `expect` failures (received value, timedOut, customErrorMessage).
|
|
36
|
+
attr_accessor :details
|
|
35
37
|
|
|
36
38
|
def log=(log)
|
|
37
39
|
return unless log
|
|
40
|
+
@raw_log = log
|
|
38
41
|
format_call_log = log.join("\n - ")
|
|
39
42
|
@message = "#{@message}\nCall log:\n#{format_call_log}\n"
|
|
40
43
|
end
|
|
@@ -60,12 +63,13 @@ module Playwright
|
|
|
60
63
|
end
|
|
61
64
|
|
|
62
65
|
class WebError
|
|
63
|
-
def initialize(error, page)
|
|
66
|
+
def initialize(error, page, location = nil)
|
|
64
67
|
@error = error
|
|
65
68
|
@page = PlaywrightApi.wrap(page)
|
|
69
|
+
@location = location
|
|
66
70
|
end
|
|
67
71
|
|
|
68
|
-
attr_reader :error, :page
|
|
72
|
+
attr_reader :error, :page, :location
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
class AssertionError < StandardError; end
|
data/lib/playwright/events.rb
CHANGED
|
@@ -20,6 +20,7 @@ end
|
|
|
20
20
|
},
|
|
21
21
|
|
|
22
22
|
Browser: {
|
|
23
|
+
Context: 'context',
|
|
23
24
|
Disconnected: 'disconnected'
|
|
24
25
|
},
|
|
25
26
|
|
|
@@ -28,7 +29,13 @@ end
|
|
|
28
29
|
Close: 'close',
|
|
29
30
|
Console: 'console',
|
|
30
31
|
Dialog: 'dialog',
|
|
32
|
+
Download: 'download',
|
|
33
|
+
FrameAttached: 'frameattached',
|
|
34
|
+
FrameDetached: 'framedetached',
|
|
35
|
+
FrameNavigated: 'framenavigated',
|
|
31
36
|
Page: 'page',
|
|
37
|
+
PageClose: 'pageclose',
|
|
38
|
+
PageLoad: 'pageload',
|
|
32
39
|
WebError: 'weberror',
|
|
33
40
|
ServiceWorker: 'serviceworker',
|
|
34
41
|
Request: 'request',
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Playwright
|
|
4
|
+
class JsonPipeTransport
|
|
5
|
+
def initialize(local_utils, params)
|
|
6
|
+
@local_utils = local_utils
|
|
7
|
+
@params = params
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def on_message_received(&block)
|
|
11
|
+
@on_message = block
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def on_driver_closed(&block)
|
|
15
|
+
@on_driver_closed = block
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def on_driver_crashed(&block)
|
|
19
|
+
@on_driver_crashed = block
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def send_message(message)
|
|
23
|
+
@pipe.channel.send_message_to_server('send', message: message)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def stop
|
|
27
|
+
@pipe&.channel&.send_message_to_server('close')
|
|
28
|
+
rescue TargetClosedError
|
|
29
|
+
nil
|
|
30
|
+
ensure
|
|
31
|
+
@pipe = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def async_run
|
|
35
|
+
@pipe = @local_utils.connect(@params)
|
|
36
|
+
@pipe.channel.on('message', ->(params) { @on_message&.call(params['message']) })
|
|
37
|
+
@pipe.channel.on('closed', ->(_params) { @on_driver_closed&.call })
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -27,7 +27,7 @@ module Playwright
|
|
|
27
27
|
result = @locator.expect(expression, expect_options, title)
|
|
28
28
|
|
|
29
29
|
if result["matches"] == @is_not
|
|
30
|
-
actual = result
|
|
30
|
+
actual = received_actual(result)
|
|
31
31
|
|
|
32
32
|
log =
|
|
33
33
|
if result.key?("log")
|
|
@@ -52,19 +52,35 @@ module Playwright
|
|
|
52
52
|
if result['errorMessage']
|
|
53
53
|
error_message = "\n#{result['errorMessage']}"
|
|
54
54
|
end
|
|
55
|
-
out = "#{out_message}\nActual value #{actual}#{error_message} #{log}"
|
|
55
|
+
out = "#{out_message}\nActual value #{actual}#{error_message} #{log}#{aria_snapshot(result)}"
|
|
56
56
|
raise AssertionError.new(out)
|
|
57
57
|
else
|
|
58
58
|
true
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
private def received_actual(result)
|
|
63
|
+
received = result['received']
|
|
64
|
+
if received.is_a?(Hash)
|
|
65
|
+
received['value']
|
|
66
|
+
else
|
|
67
|
+
received
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private def aria_snapshot(result)
|
|
72
|
+
aria_snapshot = result.dig('received', 'ariaSnapshot')
|
|
73
|
+
return '' unless aria_snapshot
|
|
74
|
+
|
|
75
|
+
"\nAria snapshot:\n#{aria_snapshot}\n"
|
|
76
|
+
end
|
|
77
|
+
|
|
62
78
|
private def _not # "not" is reserved in Ruby
|
|
63
79
|
LocatorAssertionsImpl.new(
|
|
64
80
|
@locator,
|
|
65
81
|
@default_expect_timeout,
|
|
66
82
|
!@is_not,
|
|
67
|
-
@
|
|
83
|
+
@custom_message
|
|
68
84
|
)
|
|
69
85
|
end
|
|
70
86
|
|
|
@@ -292,12 +308,13 @@ module Playwright
|
|
|
292
308
|
end
|
|
293
309
|
_define_negation :to_have_count
|
|
294
310
|
|
|
295
|
-
def to_have_css(name, value, timeout: nil)
|
|
311
|
+
def to_have_css(name, value, pseudo: nil, timeout: nil)
|
|
296
312
|
expected_text = to_expected_text_values([value])
|
|
297
313
|
expect_impl(
|
|
298
314
|
"to.have.css",
|
|
299
315
|
{
|
|
300
316
|
expressionArg: name,
|
|
317
|
+
pseudo: pseudo,
|
|
301
318
|
expectedText: expected_text,
|
|
302
319
|
timeout: timeout,
|
|
303
320
|
},
|
|
@@ -426,11 +426,12 @@ module Playwright
|
|
|
426
426
|
end
|
|
427
427
|
end
|
|
428
428
|
|
|
429
|
-
def aria_snapshot(depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
429
|
+
def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
430
430
|
params = {
|
|
431
431
|
selector: @selector,
|
|
432
432
|
timeout: _timeout(timeout),
|
|
433
433
|
}
|
|
434
|
+
params[:boxes] = boxes unless boxes.nil?
|
|
434
435
|
params[:depth] = depth if depth
|
|
435
436
|
params[:mode] = mode if mode
|
|
436
437
|
if _track
|
|
@@ -485,6 +486,14 @@ module Playwright
|
|
|
485
486
|
@frame.set_input_files(@selector, files, strict: true, noWaitAfter: noWaitAfter, timeout: timeout)
|
|
486
487
|
end
|
|
487
488
|
|
|
489
|
+
def drop(payload, position: nil, timeout: nil)
|
|
490
|
+
@frame.drop(@selector,
|
|
491
|
+
payload,
|
|
492
|
+
strict: true,
|
|
493
|
+
position: position,
|
|
494
|
+
timeout: timeout)
|
|
495
|
+
end
|
|
496
|
+
|
|
488
497
|
def tap_point(
|
|
489
498
|
force: nil,
|
|
490
499
|
modifiers: nil,
|
|
@@ -549,8 +558,13 @@ module Playwright
|
|
|
549
558
|
@frame.eval_on_selector_all(@selector, "ee => ee.map(e => e.textContent || '')")
|
|
550
559
|
end
|
|
551
560
|
|
|
552
|
-
def highlight
|
|
553
|
-
@frame.highlight(@selector)
|
|
561
|
+
def highlight(style: nil)
|
|
562
|
+
@frame.highlight(@selector, style: style)
|
|
563
|
+
DisposableStub.new { hide_highlight }
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def hide_highlight
|
|
567
|
+
@frame.hide_highlight(@selector)
|
|
554
568
|
end
|
|
555
569
|
|
|
556
570
|
def _assertions(timeout, is_not, message)
|
|
@@ -39,7 +39,15 @@ module Playwright
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
private def get_by_test_id_selector(test_id_attribute_name, test_id)
|
|
42
|
-
"internal:testid=[#{test_id_attribute_name}=#{escape_for_attribute_selector_or_regex(test_id, true)}]"
|
|
42
|
+
"internal:testid=[#{encode_test_id_attribute_name(test_id_attribute_name)}=#{escape_for_attribute_selector_or_regex(test_id, true)}]"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private def encode_test_id_attribute_name(test_id_attribute_name)
|
|
46
|
+
if test_id_attribute_name.include?(',')
|
|
47
|
+
JSON.generate(test_id_attribute_name)
|
|
48
|
+
else
|
|
49
|
+
test_id_attribute_name
|
|
50
|
+
end
|
|
43
51
|
end
|
|
44
52
|
|
|
45
53
|
private def get_by_label_selector(text, exact:)
|
|
@@ -66,12 +74,14 @@ module Playwright
|
|
|
66
74
|
props = []
|
|
67
75
|
|
|
68
76
|
ex = {
|
|
77
|
+
description: -> (value) { ['description', escape_for_attribute_selector_or_regex(value, options[:exact])]},
|
|
69
78
|
includeHidden: -> (value) { ['include-hidden', value.to_s] },
|
|
70
79
|
name: -> (value) { ['name', escape_for_attribute_selector_or_regex(value, options[:exact])]},
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
%i[
|
|
74
83
|
checked
|
|
84
|
+
description
|
|
75
85
|
disabled
|
|
76
86
|
selected
|
|
77
87
|
expanded
|