playwright-ruby-client 0.1.0 → 0.5.3
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 +20 -8
- data/docs/api_coverage.md +123 -73
- data/lib/playwright.rb +48 -9
- data/lib/playwright/channel.rb +12 -2
- data/lib/playwright/channel_owner.rb +3 -5
- data/lib/playwright/channel_owners/android.rb +1 -1
- data/lib/playwright/channel_owners/android_device.rb +11 -11
- 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 +22 -1
- data/lib/playwright/channel_owners/browser_context.rb +155 -4
- 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 +18 -5
- data/lib/playwright/channel_owners/frame.rb +40 -5
- data/lib/playwright/channel_owners/js_handle.rb +3 -3
- data/lib/playwright/channel_owners/page.rb +172 -51
- data/lib/playwright/channel_owners/playwright.rb +24 -27
- data/lib/playwright/channel_owners/request.rb +27 -3
- 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/select_option_values.rb +14 -4
- data/lib/playwright/transport.rb +28 -7
- data/lib/playwright/url_matcher.rb +1 -1
- data/lib/playwright/utils.rb +11 -2
- 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 +72 -5
- data/lib/playwright_api/android_device.rb +139 -26
- 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 +87 -19
- data/lib/playwright_api/browser_context.rb +216 -32
- data/lib/playwright_api/browser_type.rb +45 -58
- data/lib/playwright_api/dialog.rb +54 -7
- data/lib/playwright_api/element_handle.rb +113 -33
- data/lib/playwright_api/file_chooser.rb +6 -1
- data/lib/playwright_api/frame.rb +238 -43
- data/lib/playwright_api/js_handle.rb +20 -2
- data/lib/playwright_api/keyboard.rb +48 -1
- data/lib/playwright_api/mouse.rb +26 -5
- data/lib/playwright_api/page.rb +534 -63
- data/lib/playwright_api/playwright.rb +43 -47
- data/lib/playwright_api/request.rb +38 -12
- data/lib/playwright_api/response.rb +27 -10
- data/lib/playwright_api/route.rb +51 -6
- data/lib/playwright_api/selectors.rb +28 -2
- data/lib/playwright_api/touchscreen.rb +1 -1
- data/lib/playwright_api/web_socket.rb +15 -0
- 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 -100
- data/lib/playwright_api/video.rb +0 -24
data/lib/playwright/channel.rb
CHANGED
@@ -15,8 +15,9 @@ module Playwright
|
|
15
15
|
|
16
16
|
# @param method [String]
|
17
17
|
# @param params [Hash]
|
18
|
+
# @return [Playwright::ChannelOwner|nil]
|
18
19
|
def send_message_to_server(method, params = {})
|
19
|
-
result =
|
20
|
+
result = send_message_to_server_result(method, params)
|
20
21
|
if result.is_a?(Hash)
|
21
22
|
_type, channel_owner = result.first
|
22
23
|
channel_owner
|
@@ -27,8 +28,17 @@ module Playwright
|
|
27
28
|
|
28
29
|
# @param method [String]
|
29
30
|
# @param params [Hash]
|
30
|
-
|
31
|
+
# @return [Hash]
|
32
|
+
def send_message_to_server_result(method, params)
|
33
|
+
@connection.send_message_to_server(@guid, method, params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param method [String]
|
37
|
+
# @param params [Hash]
|
38
|
+
# @returns nil
|
39
|
+
def async_send_message_to_server(method, params = {})
|
31
40
|
@connection.async_send_message_to_server(@guid, method, params)
|
41
|
+
|
32
42
|
nil
|
33
43
|
end
|
34
44
|
end
|
@@ -59,16 +59,14 @@ module Playwright
|
|
59
59
|
"#<#{@guid}>"
|
60
60
|
end
|
61
61
|
|
62
|
-
private
|
63
|
-
|
64
|
-
def after_initialize
|
62
|
+
private def after_initialize
|
65
63
|
end
|
66
64
|
|
67
|
-
def update_object_from_child(guid, child)
|
65
|
+
private def update_object_from_child(guid, child)
|
68
66
|
@objects[guid] = child
|
69
67
|
end
|
70
68
|
|
71
|
-
def delete_object_from_child(guid)
|
69
|
+
private def delete_object_from_child(guid)
|
72
70
|
@objects.delete(guid)
|
73
71
|
end
|
74
72
|
end
|
@@ -2,7 +2,7 @@ module Playwright
|
|
2
2
|
define_channel_owner :AndroidDevice do
|
3
3
|
include Utils::PrepareBrowserContextOptions
|
4
4
|
|
5
|
-
def after_initialize
|
5
|
+
private def after_initialize
|
6
6
|
@input = AndroidInputImpl.new(@channel)
|
7
7
|
end
|
8
8
|
|
@@ -104,17 +104,17 @@ module Playwright
|
|
104
104
|
isMobile: nil,
|
105
105
|
javaScriptEnabled: nil,
|
106
106
|
locale: nil,
|
107
|
-
|
107
|
+
noViewport: nil,
|
108
108
|
offline: nil,
|
109
109
|
permissions: nil,
|
110
110
|
proxy: nil,
|
111
|
-
|
112
|
-
|
111
|
+
record_har_omit_content: nil,
|
112
|
+
record_har_path: nil,
|
113
|
+
record_video_dir: nil,
|
114
|
+
record_video_size: nil,
|
113
115
|
storageState: nil,
|
114
116
|
timezoneId: nil,
|
115
117
|
userAgent: nil,
|
116
|
-
videoSize: nil,
|
117
|
-
videosPath: nil,
|
118
118
|
viewport: nil,
|
119
119
|
&block)
|
120
120
|
params = {
|
@@ -131,17 +131,17 @@ module Playwright
|
|
131
131
|
isMobile: isMobile,
|
132
132
|
javaScriptEnabled: javaScriptEnabled,
|
133
133
|
locale: locale,
|
134
|
-
|
134
|
+
noViewport: noViewport,
|
135
135
|
offline: offline,
|
136
136
|
permissions: permissions,
|
137
137
|
proxy: proxy,
|
138
|
-
|
139
|
-
|
138
|
+
record_har_omit_content: record_har_omit_content,
|
139
|
+
record_har_path: record_har_path,
|
140
|
+
record_video_dir: record_video_dir,
|
141
|
+
record_video_size: record_video_size,
|
140
142
|
storageState: storageState,
|
141
143
|
timezoneId: timezoneId,
|
142
144
|
userAgent: userAgent,
|
143
|
-
videoSize: videoSize,
|
144
|
-
videosPath: videosPath,
|
145
145
|
viewport: viewport,
|
146
146
|
}.compact
|
147
147
|
prepare_browser_context_options(params)
|
@@ -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
|
@@ -4,7 +4,7 @@ module Playwright
|
|
4
4
|
include Utils::Errors::SafeCloseError
|
5
5
|
include Utils::PrepareBrowserContextOptions
|
6
6
|
|
7
|
-
def after_initialize
|
7
|
+
private def after_initialize
|
8
8
|
@contexts = Set.new
|
9
9
|
@channel.on('close', method(:on_close))
|
10
10
|
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
|
-
def after_initialize
|
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
|