playwright-ruby-client 0.2.0 → 0.5.4
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 +17 -5
- data/docs/api_coverage.md +116 -74
- data/lib/playwright.rb +48 -9
- data/lib/playwright/channel.rb +12 -2
- data/lib/playwright/channel_owners/artifact.rb +30 -0
- data/lib/playwright/channel_owners/binding_call.rb +3 -0
- data/lib/playwright/channel_owners/browser.rb +21 -0
- data/lib/playwright/channel_owners/browser_context.rb +154 -3
- data/lib/playwright/channel_owners/browser_type.rb +28 -0
- data/lib/playwright/channel_owners/dialog.rb +28 -0
- data/lib/playwright/channel_owners/element_handle.rb +6 -4
- data/lib/playwright/channel_owners/frame.rb +25 -2
- data/lib/playwright/channel_owners/js_handle.rb +2 -2
- data/lib/playwright/channel_owners/page.rb +141 -25
- data/lib/playwright/channel_owners/playwright.rb +24 -27
- data/lib/playwright/channel_owners/request.rb +26 -2
- data/lib/playwright/channel_owners/response.rb +60 -0
- data/lib/playwright/channel_owners/route.rb +78 -0
- data/lib/playwright/channel_owners/selectors.rb +19 -1
- data/lib/playwright/channel_owners/stream.rb +15 -0
- data/lib/playwright/connection.rb +11 -32
- data/lib/playwright/download.rb +27 -0
- data/lib/playwright/errors.rb +6 -0
- data/lib/playwright/events.rb +2 -5
- data/lib/playwright/keyboard_impl.rb +1 -1
- data/lib/playwright/mouse_impl.rb +41 -0
- data/lib/playwright/playwright_api.rb +3 -1
- data/lib/playwright/route_handler_entry.rb +28 -0
- data/lib/playwright/transport.rb +29 -7
- data/lib/playwright/url_matcher.rb +1 -1
- data/lib/playwright/utils.rb +9 -0
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright/video.rb +51 -0
- data/lib/playwright/wait_helper.rb +2 -2
- data/lib/playwright_api/accessibility.rb +39 -1
- data/lib/playwright_api/android.rb +74 -2
- data/lib/playwright_api/android_device.rb +141 -23
- data/lib/playwright_api/android_input.rb +17 -13
- data/lib/playwright_api/android_socket.rb +16 -0
- data/lib/playwright_api/android_web_view.rb +21 -0
- data/lib/playwright_api/browser.rb +77 -2
- data/lib/playwright_api/browser_context.rb +182 -29
- data/lib/playwright_api/browser_type.rb +40 -9
- data/lib/playwright_api/dialog.rb +54 -7
- data/lib/playwright_api/element_handle.rb +105 -31
- data/lib/playwright_api/file_chooser.rb +6 -1
- data/lib/playwright_api/frame.rb +229 -36
- data/lib/playwright_api/js_handle.rb +23 -0
- data/lib/playwright_api/keyboard.rb +48 -1
- data/lib/playwright_api/mouse.rb +26 -5
- data/lib/playwright_api/page.rb +491 -81
- data/lib/playwright_api/playwright.rb +21 -4
- data/lib/playwright_api/request.rb +30 -2
- data/lib/playwright_api/response.rb +21 -11
- data/lib/playwright_api/route.rb +51 -5
- data/lib/playwright_api/selectors.rb +27 -1
- data/lib/playwright_api/touchscreen.rb +1 -1
- data/lib/playwright_api/worker.rb +25 -1
- data/playwright.gemspec +4 -2
- metadata +42 -14
- data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
- data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
- data/lib/playwright/channel_owners/download.rb +0 -27
- data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
- data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
- data/lib/playwright_api/binding_call.rb +0 -27
- data/lib/playwright_api/chromium_browser_context.rb +0 -59
- data/lib/playwright_api/download.rb +0 -95
- data/lib/playwright_api/video.rb +0 -24
@@ -0,0 +1,30 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_channel_owner :Artifact do
|
3
|
+
private def after_initialize
|
4
|
+
@is_remote = false
|
5
|
+
@absolute_path = @initializer['absolutePath']
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :absolute_path
|
9
|
+
|
10
|
+
def path_after_finished
|
11
|
+
if @is_remote
|
12
|
+
raise "Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
|
13
|
+
end
|
14
|
+
@channel.send_message_to_server('pathAfterFinished')
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_as(path)
|
18
|
+
stream = ChannelOwners::Stream.from(@channel.send_message_to_server('saveAsStream'))
|
19
|
+
stream.save_as(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def failure
|
23
|
+
@channel.send_message_to_server('failure')
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete
|
27
|
+
@channel.send_message_to_server('delete')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -59,12 +59,33 @@ module Playwright
|
|
59
59
|
@initializer['version']
|
60
60
|
end
|
61
61
|
|
62
|
+
def start_tracing(page: nil, categories: nil, path: nil, screenshots: nil)
|
63
|
+
params = {
|
64
|
+
page: page&.channel,
|
65
|
+
categories: categories,
|
66
|
+
path: path,
|
67
|
+
screenshots: screenshots,
|
68
|
+
}.compact
|
69
|
+
|
70
|
+
@channel.send_message_to_server('startTracing', params)
|
71
|
+
end
|
72
|
+
|
73
|
+
def stop_tracing
|
74
|
+
encoded_binary = @channel.send_message_to_server("stopTracing")
|
75
|
+
return Base64.strict_decode64(encoded_binary)
|
76
|
+
end
|
77
|
+
|
62
78
|
private def on_close(_ = {})
|
63
79
|
@connected = false
|
64
80
|
emit(Events::Browser::Disconnected)
|
65
81
|
@closed_or_closing = false
|
66
82
|
end
|
67
83
|
|
84
|
+
# called from BrowserType#connectOverCDP
|
85
|
+
private def add_context(context)
|
86
|
+
@contexts << context
|
87
|
+
end
|
88
|
+
|
68
89
|
# called from BrowserContext#on_close with send(:remove_context), so keep private.
|
69
90
|
private def remove_context(context)
|
70
91
|
@contexts.delete(context)
|
@@ -2,11 +2,16 @@ 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
4
|
include Utils::Errors::SafeCloseError
|
5
|
-
|
5
|
+
attr_accessor :browser
|
6
|
+
attr_writer :owner_page, :options
|
6
7
|
|
7
8
|
private def after_initialize
|
8
9
|
@pages = Set.new
|
10
|
+
@routes = Set.new
|
11
|
+
@bindings = {}
|
12
|
+
@timeout_settings = TimeoutSettings.new
|
9
13
|
|
14
|
+
@channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
|
10
15
|
@channel.once('close', ->(_) { on_close })
|
11
16
|
@channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
|
12
17
|
@channel.on('route', ->(params) {
|
@@ -18,11 +23,36 @@ module Playwright
|
|
18
23
|
page.send(:update_browser_context, self)
|
19
24
|
@pages << page
|
20
25
|
emit(Events::BrowserContext::Page, page)
|
26
|
+
page.send(:emit_popup_event_from_browser_context)
|
21
27
|
end
|
22
28
|
|
23
29
|
private def on_route(route, request)
|
24
|
-
#
|
25
|
-
|
30
|
+
# It is not desired to use PlaywrightApi.wrap directly.
|
31
|
+
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
32
|
+
# Just a workaround...
|
33
|
+
wrapped_route = PlaywrightApi.wrap(route)
|
34
|
+
wrapped_request = PlaywrightApi.wrap(request)
|
35
|
+
|
36
|
+
if @routes.none? { |handler_entry| handler_entry.handle(wrapped_route, wrapped_request) }
|
37
|
+
route.continue
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private def on_binding(binding_call)
|
42
|
+
func = @binding[binding_call.name]
|
43
|
+
if func
|
44
|
+
binding_call.call(func)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def set_default_navigation_timeout(timeout)
|
49
|
+
@timeout_settings.default_navigation_timeout = timeout
|
50
|
+
@channel.send_message_to_server('setDefaultNavigationTimeoutNoReply', timeout: timeout)
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_default_timeout(timeout)
|
54
|
+
@timeout_settings.default_timeout = timeout
|
55
|
+
@channel.send_message_to_server('setDefaultTimeoutNoReply', timeout: timeout)
|
26
56
|
end
|
27
57
|
|
28
58
|
def pages
|
@@ -36,6 +66,111 @@ module Playwright
|
|
36
66
|
ChannelOwners::Page.from(resp)
|
37
67
|
end
|
38
68
|
|
69
|
+
def cookies(urls: nil)
|
70
|
+
target_urls =
|
71
|
+
if urls.nil?
|
72
|
+
[]
|
73
|
+
elsif urls.is_a?(Enumerable)
|
74
|
+
urls
|
75
|
+
else
|
76
|
+
[urls]
|
77
|
+
end
|
78
|
+
@channel.send_message_to_server('cookies', urls: urls)
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_cookies(cookies)
|
82
|
+
@channel.send_message_to_server('addCookies', cookies: cookies)
|
83
|
+
end
|
84
|
+
|
85
|
+
def clear_cookies
|
86
|
+
@channel.send_message_to_server('clearCookies')
|
87
|
+
end
|
88
|
+
|
89
|
+
def grant_permissions(permissions, origin: nil)
|
90
|
+
params = {
|
91
|
+
permissions: permissions,
|
92
|
+
origin: origin,
|
93
|
+
}.compact
|
94
|
+
@channel.send_message_to_server('grantPermissions', params)
|
95
|
+
end
|
96
|
+
|
97
|
+
def clear_permissions
|
98
|
+
@channel.send_message_to_server('clearPermissions')
|
99
|
+
end
|
100
|
+
|
101
|
+
def set_geolocation(geolocation)
|
102
|
+
@channel.send_message_to_server('setGeolocation', geolocation: geolocation)
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_extra_http_headers(headers)
|
106
|
+
@channel.send_message_to_server('setExtraHTTPHeaders',
|
107
|
+
headers: HttpHeaders.new(headers).as_serialized)
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_offline(offline)
|
111
|
+
@channel.send_message_to_server('setOffline', offline: offline)
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_init_script(path: nil, script: nil)
|
115
|
+
source =
|
116
|
+
if path
|
117
|
+
File.read(path)
|
118
|
+
elsif script
|
119
|
+
script
|
120
|
+
else
|
121
|
+
raise ArgumentError.new('Either path or script parameter must be specified')
|
122
|
+
end
|
123
|
+
|
124
|
+
@channel.send_message_to_server('addInitScript', source: script)
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
def expose_binding(name, callback, handle: nil)
|
129
|
+
if @pages.any? { |page| page.send(:has_bindings?, name) }
|
130
|
+
raise ArgumentError.new("Function \"#{name}\" has been already registered in one of the pages")
|
131
|
+
end
|
132
|
+
if @bindings.key?(name)
|
133
|
+
raise ArgumentError.new("Function \"#{name}\" has been already registered")
|
134
|
+
end
|
135
|
+
params = {
|
136
|
+
name: name,
|
137
|
+
needsHandle: handle,
|
138
|
+
}.compact
|
139
|
+
@bindings[name] = callback
|
140
|
+
@channel.send_message_to_server('exposeBinding', params)
|
141
|
+
end
|
142
|
+
|
143
|
+
def expose_function(name, callback)
|
144
|
+
expose_binding(name, ->(_source, *args) { callback.call(*args) }, )
|
145
|
+
end
|
146
|
+
|
147
|
+
def route(url, handler)
|
148
|
+
entry = RouteHandlerEntry.new(url, handler)
|
149
|
+
@routes << entry
|
150
|
+
if @routes.count >= 1
|
151
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: true)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def unroute(url, handler: nil)
|
156
|
+
@routes.reject! do |handler_entry|
|
157
|
+
handler_entry.same_value?(url: url, handler: handler)
|
158
|
+
end
|
159
|
+
if @routes.count == 0
|
160
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def expect_event(event, predicate: nil, timeout: nil, &block)
|
165
|
+
wait_helper = WaitHelper.new
|
166
|
+
wait_helper.reject_on_timeout(timeout || @timeout_settings.timeout, "Timeout while waiting for event \"#{event}\"")
|
167
|
+
wait_helper.wait_for_event(self, event, predicate: predicate)
|
168
|
+
|
169
|
+
block&.call
|
170
|
+
|
171
|
+
wait_helper.promise.value!
|
172
|
+
end
|
173
|
+
|
39
174
|
private def on_close
|
40
175
|
@closed_or_closing = true
|
41
176
|
@browser&.send(:remove_context, self)
|
@@ -51,6 +186,18 @@ module Playwright
|
|
51
186
|
raise unless safe_close_error?(err)
|
52
187
|
end
|
53
188
|
|
189
|
+
def pause
|
190
|
+
@channel.send_message_to_server('pause')
|
191
|
+
end
|
192
|
+
|
193
|
+
def expect_page(predicate: nil, timeout: nil)
|
194
|
+
params = {
|
195
|
+
predicate: predicate,
|
196
|
+
timeout: timeout,
|
197
|
+
}.compact
|
198
|
+
expect_event(Events::BrowserContext::Page, params)
|
199
|
+
end
|
200
|
+
|
54
201
|
# called from Page#on_close with send(:remove_page, page), so keep private
|
55
202
|
private def remove_page(page)
|
56
203
|
@pages.delete(page)
|
@@ -60,5 +207,9 @@ module Playwright
|
|
60
207
|
private def _timeout_settings
|
61
208
|
@timeout_settings
|
62
209
|
end
|
210
|
+
|
211
|
+
private def has_record_video_option?
|
212
|
+
@options.key?(:recordVideo)
|
213
|
+
end
|
63
214
|
end
|
64
215
|
end
|
@@ -22,5 +22,33 @@ module Playwright
|
|
22
22
|
browser
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
def connect_over_cdp(endpointURL, slowMo: nil, timeout: nil, &block)
|
27
|
+
raise 'Connecting over CDP is only supported in Chromium.' unless name == 'chromium'
|
28
|
+
|
29
|
+
params = {
|
30
|
+
sdkLanguage: 'ruby',
|
31
|
+
endpointURL: endpointURL,
|
32
|
+
slowMo: slowMo,
|
33
|
+
timeout: timeout,
|
34
|
+
}.compact
|
35
|
+
result = @channel.send_message_to_server_result('connectOverCDP', params)
|
36
|
+
browser = ChannelOwners::Browser.from(result['browser'])
|
37
|
+
|
38
|
+
if result['defaultContext']
|
39
|
+
context = ChannelOwners::BrowserContext.from(result['defaultContext'])
|
40
|
+
browser.send(:add_context, context)
|
41
|
+
end
|
42
|
+
|
43
|
+
if block
|
44
|
+
begin
|
45
|
+
block.call(browser)
|
46
|
+
ensure
|
47
|
+
browser.close
|
48
|
+
end
|
49
|
+
else
|
50
|
+
browser
|
51
|
+
end
|
52
|
+
end
|
25
53
|
end
|
26
54
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_channel_owner :Dialog do
|
3
|
+
def type
|
4
|
+
@initializer['type']
|
5
|
+
end
|
6
|
+
|
7
|
+
def message
|
8
|
+
@initializer['message']
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_value
|
12
|
+
@initializer['defaultValue']
|
13
|
+
end
|
14
|
+
|
15
|
+
def accept(promptText: nil)
|
16
|
+
accept_async(prompt_text: promptText).value!
|
17
|
+
end
|
18
|
+
|
19
|
+
def accept_async(promptText: nil)
|
20
|
+
params = { promptText: promptText }.compact
|
21
|
+
@channel.async_send_message_to_server('accept', params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def dismiss
|
25
|
+
@channel.async_send_message_to_server('dismiss')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -82,7 +82,7 @@ module Playwright
|
|
82
82
|
modifiers: modifiers,
|
83
83
|
position: position,
|
84
84
|
timeout: timeout,
|
85
|
-
}
|
85
|
+
}.compact
|
86
86
|
@channel.send_message_to_server('hover', params)
|
87
87
|
|
88
88
|
nil
|
@@ -179,7 +179,7 @@ module Playwright
|
|
179
179
|
value: value,
|
180
180
|
noWaitAfter: noWaitAfter,
|
181
181
|
timeout: timeout,
|
182
|
-
}
|
182
|
+
}.compact
|
183
183
|
@channel.send_message_to_server('fill', params)
|
184
184
|
|
185
185
|
nil
|
@@ -230,10 +230,11 @@ module Playwright
|
|
230
230
|
nil
|
231
231
|
end
|
232
232
|
|
233
|
-
def check(force: nil, noWaitAfter: nil, timeout: nil)
|
233
|
+
def check(force: nil, noWaitAfter: nil, position: nil, timeout: nil)
|
234
234
|
params = {
|
235
235
|
force: force,
|
236
236
|
noWaitAfter: noWaitAfter,
|
237
|
+
position: position,
|
237
238
|
timeout: timeout,
|
238
239
|
}.compact
|
239
240
|
@channel.send_message_to_server('check', params)
|
@@ -241,10 +242,11 @@ module Playwright
|
|
241
242
|
nil
|
242
243
|
end
|
243
244
|
|
244
|
-
def uncheck(force: nil, noWaitAfter: nil, timeout: nil)
|
245
|
+
def uncheck(force: nil, noWaitAfter: nil, position: nil, timeout: nil)
|
245
246
|
params = {
|
246
247
|
force: force,
|
247
248
|
noWaitAfter: noWaitAfter,
|
249
|
+
position: position,
|
248
250
|
timeout: timeout,
|
249
251
|
}.compact
|
250
252
|
@channel.send_message_to_server('uncheck', params)
|
@@ -98,6 +98,15 @@ module Playwright
|
|
98
98
|
request&.response
|
99
99
|
end
|
100
100
|
|
101
|
+
def wait_for_url(url, timeout: nil, waitUntil: nil)
|
102
|
+
matcher = UrlMatcher.new(url)
|
103
|
+
if matcher.match?(@url)
|
104
|
+
wait_for_load_state(state: waitUntil, timeout: timeout)
|
105
|
+
else
|
106
|
+
expect_navigation(timeout: timeout, url: url, waitUntil: waitUntil)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
101
110
|
def wait_for_load_state(state: nil, timeout: nil)
|
102
111
|
option_state = state || 'load'
|
103
112
|
option_timeout = timeout || @page.send(:timeout_settings).navigation_timeout
|
@@ -464,11 +473,18 @@ module Playwright
|
|
464
473
|
nil
|
465
474
|
end
|
466
475
|
|
467
|
-
def check(
|
476
|
+
def check(
|
477
|
+
selector,
|
478
|
+
force: nil,
|
479
|
+
noWaitAfter: nil,
|
480
|
+
position: nil,
|
481
|
+
timeout: nil)
|
482
|
+
|
468
483
|
params = {
|
469
484
|
selector: selector,
|
470
485
|
force: force,
|
471
486
|
noWaitAfter: noWaitAfter,
|
487
|
+
position: position,
|
472
488
|
timeout: timeout,
|
473
489
|
}.compact
|
474
490
|
@channel.send_message_to_server('check', params)
|
@@ -476,11 +492,18 @@ module Playwright
|
|
476
492
|
nil
|
477
493
|
end
|
478
494
|
|
479
|
-
def uncheck(
|
495
|
+
def uncheck(
|
496
|
+
selector,
|
497
|
+
force: nil,
|
498
|
+
noWaitAfter: nil,
|
499
|
+
position: nil,
|
500
|
+
timeout: nil)
|
501
|
+
|
480
502
|
params = {
|
481
503
|
selector: selector,
|
482
504
|
force: force,
|
483
505
|
noWaitAfter: noWaitAfter,
|
506
|
+
position: position,
|
484
507
|
timeout: timeout,
|
485
508
|
}.compact
|
486
509
|
@channel.send_message_to_server('uncheck', params)
|
@@ -14,12 +14,21 @@ module Playwright
|
|
14
14
|
@mouse = MouseImpl.new(@channel)
|
15
15
|
@touchscreen = TouchscreenImpl.new(@channel)
|
16
16
|
|
17
|
-
|
17
|
+
if @initializer['viewportSize']
|
18
|
+
@viewport_size = {
|
19
|
+
width: @initializer['viewportSize']['width'],
|
20
|
+
height: @initializer['viewportSize']['height'],
|
21
|
+
}
|
22
|
+
end
|
18
23
|
@closed = false
|
24
|
+
@bindings = {}
|
25
|
+
@routes = Set.new
|
26
|
+
|
19
27
|
@main_frame = ChannelOwners::Frame.from(@initializer['mainFrame'])
|
20
28
|
@main_frame.send(:update_page_from_page, self)
|
21
29
|
@frames = Set.new
|
22
30
|
@frames << @main_frame
|
31
|
+
@opener = ChannelOwners::Page.from_nullable(@initializer['opener'])
|
23
32
|
|
24
33
|
@channel.once('close', ->(_) { on_close })
|
25
34
|
@channel.on('console', ->(params) {
|
@@ -29,9 +38,7 @@ module Playwright
|
|
29
38
|
@channel.on('crash', ->(_) { emit(Events::Page::Crash) })
|
30
39
|
@channel.on('dialog', method(:on_dialog))
|
31
40
|
@channel.on('domcontentloaded', ->(_) { emit(Events::Page::DOMContentLoaded) })
|
32
|
-
@channel.on('download',
|
33
|
-
emit(Events::Page::Download, ChannelOwners::Download.from(params['download']))
|
34
|
-
})
|
41
|
+
@channel.on('download', method(:on_download))
|
35
42
|
@channel.on('fileChooser', ->(params) {
|
36
43
|
chooser = FileChooserImpl.new(
|
37
44
|
page: self,
|
@@ -49,9 +56,6 @@ module Playwright
|
|
49
56
|
@channel.on('pageError', ->(params) {
|
50
57
|
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
51
58
|
})
|
52
|
-
@channel.on('popup', ->(params) {
|
53
|
-
emit(Events::Page::Popup, ChannelOwners::Page.from(params['page']))
|
54
|
-
})
|
55
59
|
@channel.on('request', ->(params) {
|
56
60
|
emit(Events::Page::Request, ChannelOwners::Request.from(params['request']))
|
57
61
|
})
|
@@ -74,9 +78,7 @@ module Playwright
|
|
74
78
|
@channel.on('route', ->(params) {
|
75
79
|
on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
|
76
80
|
})
|
77
|
-
@channel.on('video',
|
78
|
-
video.send(:update_relative_path, params['relativePath'])
|
79
|
-
})
|
81
|
+
@channel.on('video', method(:on_video))
|
80
82
|
@channel.on('webSocket', ->(params) {
|
81
83
|
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
82
84
|
})
|
@@ -96,12 +98,12 @@ module Playwright
|
|
96
98
|
private def on_request_failed(request, response_end_timing, failure_text)
|
97
99
|
request.send(:update_failure_text, failure_text)
|
98
100
|
request.send(:update_response_end_timing, response_end_timing)
|
99
|
-
emit(Events::Page::RequestFailed)
|
101
|
+
emit(Events::Page::RequestFailed, request)
|
100
102
|
end
|
101
103
|
|
102
104
|
private def on_request_finished(request, response_end_timing)
|
103
105
|
request.send(:update_response_end_timing, response_end_timing)
|
104
|
-
emit(Events::Page::RequestFinished)
|
106
|
+
emit(Events::Page::RequestFinished, request)
|
105
107
|
end
|
106
108
|
|
107
109
|
private def on_frame_attached(frame)
|
@@ -117,8 +119,15 @@ module Playwright
|
|
117
119
|
end
|
118
120
|
|
119
121
|
private def on_route(route, request)
|
120
|
-
#
|
121
|
-
|
122
|
+
# It is not desired to use PlaywrightApi.wrap directly.
|
123
|
+
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
124
|
+
# Just a workaround...
|
125
|
+
wrapped_route = PlaywrightApi.wrap(route)
|
126
|
+
wrapped_request = PlaywrightApi.wrap(request)
|
127
|
+
|
128
|
+
if @routes.none? { |handler_entry| handler_entry.handle(wrapped_route, wrapped_request) }
|
129
|
+
@browser_context.send(:on_route, route, request)
|
130
|
+
end
|
122
131
|
end
|
123
132
|
|
124
133
|
private def on_close
|
@@ -130,14 +139,28 @@ module Playwright
|
|
130
139
|
private def on_dialog(params)
|
131
140
|
dialog = ChannelOwners::Dialog.from(params['dialog'])
|
132
141
|
unless emit(Events::Page::Dialog, dialog)
|
133
|
-
dialog.dismiss
|
142
|
+
dialog.dismiss
|
134
143
|
end
|
135
144
|
end
|
136
145
|
|
146
|
+
private def on_download(params)
|
147
|
+
download = Download.new(
|
148
|
+
url: params['url'],
|
149
|
+
suggested_filename: params['suggestedFilename'],
|
150
|
+
artifact: ChannelOwners::Artifact.from(params['artifact']),
|
151
|
+
)
|
152
|
+
emit(Events::Page::Download, download)
|
153
|
+
end
|
154
|
+
|
155
|
+
private def on_video(params)
|
156
|
+
artifact = ChannelOwners::Artifact.from(params['artifact'])
|
157
|
+
video.send(:set_artifact, artifact)
|
158
|
+
end
|
159
|
+
|
137
160
|
# @override
|
138
161
|
def on(event, callback)
|
139
162
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
140
|
-
@channel.
|
163
|
+
@channel.async_send_message_to_server('setFileChooserInterceptedNoReply', intercepted: true)
|
141
164
|
end
|
142
165
|
super
|
143
166
|
end
|
@@ -145,7 +168,7 @@ module Playwright
|
|
145
168
|
# @override
|
146
169
|
def once(event, callback)
|
147
170
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
148
|
-
@channel.
|
171
|
+
@channel.async_send_message_to_server('setFileChooserInterceptedNoReply', intercepted: true)
|
149
172
|
end
|
150
173
|
super
|
151
174
|
end
|
@@ -154,7 +177,7 @@ module Playwright
|
|
154
177
|
def off(event, callback)
|
155
178
|
super
|
156
179
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
157
|
-
@channel.
|
180
|
+
@channel.async_send_message_to_server('setFileChooserInterceptedNoReply', intercepted: false)
|
158
181
|
end
|
159
182
|
end
|
160
183
|
|
@@ -163,8 +186,17 @@ module Playwright
|
|
163
186
|
end
|
164
187
|
|
165
188
|
def opener
|
166
|
-
|
167
|
-
|
189
|
+
if @opener&.closed?
|
190
|
+
nil
|
191
|
+
else
|
192
|
+
@opener
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private def emit_popup_event_from_browser_context
|
197
|
+
if @opener && !@opener.closed?
|
198
|
+
@opener.emit(Events::Page::Popup, self)
|
199
|
+
end
|
168
200
|
end
|
169
201
|
|
170
202
|
def frame(name: nil, url: nil)
|
@@ -311,6 +343,10 @@ module Playwright
|
|
311
343
|
@main_frame.wait_for_load_state(state: state, timeout: timeout)
|
312
344
|
end
|
313
345
|
|
346
|
+
def wait_for_url(url, timeout: nil, waitUntil: nil)
|
347
|
+
@main_frame.wait_for_url(url, timeout: timeout, waitUntil: waitUntil)
|
348
|
+
end
|
349
|
+
|
314
350
|
def go_back(timeout: nil, waitUntil: nil)
|
315
351
|
params = { timeout: timeout, waitUntil: waitUntil }.compact
|
316
352
|
resp = @channel.send_message_to_server('goBack', params)
|
@@ -347,7 +383,7 @@ module Playwright
|
|
347
383
|
def add_init_script(path: nil, script: nil)
|
348
384
|
source =
|
349
385
|
if path
|
350
|
-
File.read(path
|
386
|
+
File.read(path)
|
351
387
|
elsif script
|
352
388
|
script
|
353
389
|
else
|
@@ -358,6 +394,23 @@ module Playwright
|
|
358
394
|
nil
|
359
395
|
end
|
360
396
|
|
397
|
+
def route(url, handler)
|
398
|
+
entry = RouteHandlerEntry.new(url, handler)
|
399
|
+
@routes << entry
|
400
|
+
if @routes.count >= 1
|
401
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: true)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def unroute(url, handler: nil)
|
406
|
+
@routes.reject! do |handler_entry|
|
407
|
+
handler_entry.same_value?(url: url, handler: handler)
|
408
|
+
end
|
409
|
+
if @routes.count == 0
|
410
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
361
414
|
def screenshot(
|
362
415
|
path: nil,
|
363
416
|
type: nil,
|
@@ -546,12 +599,24 @@ module Playwright
|
|
546
599
|
@main_frame.press(selector, key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
|
547
600
|
end
|
548
601
|
|
549
|
-
def check(
|
550
|
-
|
602
|
+
def check(
|
603
|
+
selector,
|
604
|
+
force: nil,
|
605
|
+
noWaitAfter: nil,
|
606
|
+
position: nil,
|
607
|
+
timeout: nil)
|
608
|
+
|
609
|
+
@main_frame.check(selector, force: force, noWaitAfter: noWaitAfter, position: position, timeout: timeout)
|
551
610
|
end
|
552
611
|
|
553
|
-
def uncheck(
|
554
|
-
|
612
|
+
def uncheck(
|
613
|
+
selector,
|
614
|
+
force: nil,
|
615
|
+
noWaitAfter: nil,
|
616
|
+
position: nil,
|
617
|
+
timeout: nil)
|
618
|
+
|
619
|
+
@main_frame.uncheck(selector, force: force, noWaitAfter: noWaitAfter, position: position, timeout: timeout)
|
555
620
|
end
|
556
621
|
|
557
622
|
def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
|
@@ -597,6 +662,36 @@ module Playwright
|
|
597
662
|
decoded_binary
|
598
663
|
end
|
599
664
|
|
665
|
+
def video
|
666
|
+
return nil unless @browser_context.send(:has_record_video_option?)
|
667
|
+
@video ||= Video.new(self)
|
668
|
+
end
|
669
|
+
|
670
|
+
def start_js_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
|
671
|
+
params = {
|
672
|
+
resetOnNavigation: resetOnNavigation,
|
673
|
+
reportAnonymousScripts: reportAnonymousScripts,
|
674
|
+
}.compact
|
675
|
+
|
676
|
+
@channel.send_message_to_server('startJSCoverage', params)
|
677
|
+
end
|
678
|
+
|
679
|
+
def stop_js_coverage
|
680
|
+
@channel.send_message_to_server('stopJSCoverage')
|
681
|
+
end
|
682
|
+
|
683
|
+
def start_css_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
|
684
|
+
params = {
|
685
|
+
resetOnNavigation: resetOnNavigation,
|
686
|
+
}.compact
|
687
|
+
|
688
|
+
@channel.send_message_to_server('startCSSCoverage', params)
|
689
|
+
end
|
690
|
+
|
691
|
+
def stop_css_coverage
|
692
|
+
@channel.send_message_to_server('stopCSSCoverage')
|
693
|
+
end
|
694
|
+
|
600
695
|
class CrashedError < StandardError
|
601
696
|
def initialize
|
602
697
|
super('Page crashed')
|
@@ -634,6 +729,18 @@ module Playwright
|
|
634
729
|
wait_helper.promise.value!
|
635
730
|
end
|
636
731
|
|
732
|
+
def expect_console_message(predicate: nil, timeout: nil, &block)
|
733
|
+
expect_event(Events::Page::Console, predicate: predicate, timeout: timeout, &block)
|
734
|
+
end
|
735
|
+
|
736
|
+
def expect_download(predicate: nil, timeout: nil, &block)
|
737
|
+
expect_event(Events::Page::Download, predicate: predicate, timeout: timeout, &block)
|
738
|
+
end
|
739
|
+
|
740
|
+
def expect_file_chooser(predicate: nil, timeout: nil, &block)
|
741
|
+
expect_event(Events::Page::FileChooser, predicate: predicate, timeout: timeout, &block)
|
742
|
+
end
|
743
|
+
|
637
744
|
def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
|
638
745
|
@main_frame.expect_navigation(
|
639
746
|
timeout: timeout,
|
@@ -642,6 +749,10 @@ module Playwright
|
|
642
749
|
&block)
|
643
750
|
end
|
644
751
|
|
752
|
+
def expect_popup(predicate: nil, timeout: nil, &block)
|
753
|
+
expect_event(Events::Page::Popup, predicate: predicate, timeout: timeout, &block)
|
754
|
+
end
|
755
|
+
|
645
756
|
def expect_request(urlOrPredicate, timeout: nil)
|
646
757
|
predicate =
|
647
758
|
case urlOrPredicate
|
@@ -682,5 +793,10 @@ module Playwright
|
|
682
793
|
private def timeout_settings
|
683
794
|
@timeout_settings
|
684
795
|
end
|
796
|
+
|
797
|
+
# called from BrowserContext#expose_binding
|
798
|
+
private def has_bindings?(name)
|
799
|
+
@bindings.key?(name)
|
800
|
+
end
|
685
801
|
end
|
686
802
|
end
|