playwright-ruby-client 0.0.8 → 0.3.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/README.md +3 -3
- data/docs/api_coverage.md +159 -101
- data/lib/playwright.rb +5 -2
- data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
- data/lib/playwright/api_implementation.rb +18 -0
- data/lib/playwright/channel.rb +13 -6
- 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 +12 -12
- data/lib/playwright/channel_owners/binding_call.rb +3 -0
- data/lib/playwright/channel_owners/browser.rb +1 -1
- data/lib/playwright/channel_owners/browser_context.rb +157 -3
- data/lib/playwright/channel_owners/dialog.rb +28 -0
- data/lib/playwright/channel_owners/download.rb +27 -0
- data/lib/playwright/channel_owners/element_handle.rb +15 -4
- data/lib/playwright/channel_owners/frame.rb +24 -5
- data/lib/playwright/channel_owners/js_handle.rb +1 -1
- data/lib/playwright/channel_owners/page.rb +367 -29
- data/lib/playwright/channel_owners/playwright.rb +4 -0
- data/lib/playwright/channel_owners/request.rb +35 -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/errors.rb +1 -1
- data/lib/playwright/event_emitter.rb +8 -1
- data/lib/playwright/event_emitter_proxy.rb +49 -0
- data/lib/playwright/file_chooser_impl.rb +23 -0
- data/lib/playwright/http_headers.rb +20 -0
- data/lib/playwright/input_files.rb +1 -1
- data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +5 -1
- data/lib/playwright/mouse_impl.rb +7 -0
- data/lib/playwright/playwright_api.rb +59 -20
- data/lib/playwright/route_handler_entry.rb +36 -0
- data/lib/playwright/select_option_values.rb +14 -4
- data/lib/playwright/touchscreen_impl.rb +7 -0
- data/lib/playwright/utils.rb +4 -3
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright/wait_helper.rb +1 -1
- data/lib/playwright_api/android.rb +82 -11
- data/lib/playwright_api/android_device.rb +148 -32
- 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/binding_call.rb +14 -5
- data/lib/playwright_api/browser.rb +22 -23
- data/lib/playwright_api/browser_context.rb +49 -35
- data/lib/playwright_api/browser_type.rb +24 -64
- data/lib/playwright_api/chromium_browser_context.rb +10 -8
- data/lib/playwright_api/console_message.rb +10 -6
- data/lib/playwright_api/dialog.rb +37 -6
- data/lib/playwright_api/download.rb +28 -11
- data/lib/playwright_api/element_handle.rb +107 -96
- data/lib/playwright_api/file_chooser.rb +18 -10
- data/lib/playwright_api/frame.rb +124 -117
- data/lib/playwright_api/js_handle.rb +20 -22
- data/lib/playwright_api/keyboard.rb +5 -5
- data/lib/playwright_api/page.rb +206 -148
- data/lib/playwright_api/playwright.rb +33 -45
- data/lib/playwright_api/request.rb +11 -12
- data/lib/playwright_api/response.rb +30 -16
- data/lib/playwright_api/route.rb +27 -5
- data/lib/playwright_api/selectors.rb +14 -10
- data/lib/playwright_api/web_socket.rb +10 -1
- data/lib/playwright_api/worker.rb +13 -13
- metadata +16 -7
- data/lib/playwright/input_type.rb +0 -19
- data/lib/playwright/input_types/mouse.rb +0 -4
- data/lib/playwright/input_types/touchscreen.rb +0 -4
@@ -0,0 +1,18 @@
|
|
1
|
+
module Playwright
|
2
|
+
# Each Impl class include this module.
|
3
|
+
# Used for detecting whether the object is a XXXXImpl or not.
|
4
|
+
module ApiImplementation ; end
|
5
|
+
|
6
|
+
def self.define_api_implementation(class_name, &block)
|
7
|
+
klass = Class.new
|
8
|
+
klass.include(ApiImplementation)
|
9
|
+
klass.class_eval(&block) if block
|
10
|
+
if ::Playwright.const_defined?(class_name)
|
11
|
+
raise ArgumentError.new("Playwright::#{class_name} already exist. Choose another class name.")
|
12
|
+
end
|
13
|
+
::Playwright.const_set(class_name, klass)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# load subclasses
|
18
|
+
Dir[File.join(__dir__, '*_impl.rb')].each { |f| require f }
|
data/lib/playwright/channel.rb
CHANGED
@@ -16,12 +16,19 @@ module Playwright
|
|
16
16
|
# @param method [String]
|
17
17
|
# @param params [Hash]
|
18
18
|
def send_message_to_server(method, params = {})
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
async_send_message_to_server(method, params).value!
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param method [String]
|
23
|
+
# @param params [Hash]
|
24
|
+
def async_send_message_to_server(method, params = {})
|
25
|
+
@connection.async_send_message_to_server(@guid, method, params).then do |result|
|
26
|
+
if result.is_a?(Hash)
|
27
|
+
_type, channel_owner = result.first
|
28
|
+
channel_owner
|
29
|
+
else
|
30
|
+
nil
|
31
|
+
end
|
25
32
|
end
|
26
33
|
end
|
27
34
|
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,8 +2,8 @@ module Playwright
|
|
2
2
|
define_channel_owner :AndroidDevice do
|
3
3
|
include Utils::PrepareBrowserContextOptions
|
4
4
|
|
5
|
-
def after_initialize
|
6
|
-
@input =
|
5
|
+
private def after_initialize
|
6
|
+
@input = AndroidInputImpl.new(@channel)
|
7
7
|
end
|
8
8
|
|
9
9
|
attr_reader :input
|
@@ -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)
|
@@ -2,13 +2,21 @@ 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
|
-
@channel.on('page', ->(
|
16
|
+
@channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
|
17
|
+
@channel.on('route', ->(params) {
|
18
|
+
on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
|
19
|
+
})
|
12
20
|
end
|
13
21
|
|
14
22
|
private def on_page(page)
|
@@ -17,6 +25,35 @@ module Playwright
|
|
17
25
|
emit(Events::BrowserContext::Page, page)
|
18
26
|
end
|
19
27
|
|
28
|
+
private def on_route(route, request)
|
29
|
+
# It is not desired to use PlaywrightApi.wrap directly.
|
30
|
+
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
31
|
+
# Just a workaround...
|
32
|
+
wrapped_route = PlaywrightApi.wrap(route)
|
33
|
+
wrapped_request = PlaywrightApi.wrap(request)
|
34
|
+
|
35
|
+
if @routes.none? { |handler_entry| handler_entry.handle(wrapped_route, wrapped_request) }
|
36
|
+
route.continue
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private def on_binding(binding_call)
|
41
|
+
func = @binding[binding_call.name]
|
42
|
+
if func
|
43
|
+
binding_call.call(func)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_default_navigation_timeout(timeout)
|
48
|
+
@timeout_settings.default_navigation_timeout = timeout
|
49
|
+
@channel.send_message_to_server('setDefaultNavigationTimeoutNoReply', timeout: timeout)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_default_timeout(timeout)
|
53
|
+
@timeout_settings.default_timeout = timeout
|
54
|
+
@channel.send_message_to_server('setDefaultTimeoutNoReply', timeout: timeout)
|
55
|
+
end
|
56
|
+
|
20
57
|
def pages
|
21
58
|
@pages.to_a
|
22
59
|
end
|
@@ -28,6 +65,111 @@ module Playwright
|
|
28
65
|
ChannelOwners::Page.from(resp)
|
29
66
|
end
|
30
67
|
|
68
|
+
def cookies(urls: nil)
|
69
|
+
target_urls =
|
70
|
+
if urls.nil?
|
71
|
+
[]
|
72
|
+
elsif urls.is_a?(Enumerable)
|
73
|
+
urls
|
74
|
+
else
|
75
|
+
[urls]
|
76
|
+
end
|
77
|
+
@channel.send_message_to_server('cookies', urls: urls)
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_cookies(cookies)
|
81
|
+
@channel.send_message_to_server('addCookies', cookies: cookies)
|
82
|
+
end
|
83
|
+
|
84
|
+
def clear_cookies
|
85
|
+
@channel.send_message_to_server('clearCookies')
|
86
|
+
end
|
87
|
+
|
88
|
+
def grant_permissions(permissions, origin: nil)
|
89
|
+
params = {
|
90
|
+
permissions: permissions,
|
91
|
+
origin: origin,
|
92
|
+
}.compact
|
93
|
+
@channel.send_message_to_server('grantPermissions', params)
|
94
|
+
end
|
95
|
+
|
96
|
+
def clear_permissions
|
97
|
+
@channel.send_message_to_server('clearPermissions')
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_geolocation(geolocation)
|
101
|
+
@channel.send_message_to_server('setGeolocation', geolocation: geolocation)
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_extra_http_headers(headers)
|
105
|
+
@channel.send_message_to_server('setExtraHTTPHeaders',
|
106
|
+
headers: HttpHeaders.new(headers).as_serialized)
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_offline(offline)
|
110
|
+
@channel.send_message_to_server('setOffline', offline: offline)
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_init_script(path: nil, script: nil)
|
114
|
+
source =
|
115
|
+
if path
|
116
|
+
File.read(path)
|
117
|
+
elsif script
|
118
|
+
script
|
119
|
+
else
|
120
|
+
raise ArgumentError.new('Either path or script parameter must be specified')
|
121
|
+
end
|
122
|
+
|
123
|
+
@channel.send_message_to_server('addInitScript', source: script)
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
|
127
|
+
def expose_binding(name, callback, handle: nil)
|
128
|
+
if @pages.any? { |page| page.send(:has_bindings?, name) }
|
129
|
+
raise ArgumentError.new("Function \"#{name}\" has been already registered in one of the pages")
|
130
|
+
end
|
131
|
+
if @bindings.key?(name)
|
132
|
+
raise ArgumentError.new("Function \"#{name}\" has been already registered")
|
133
|
+
end
|
134
|
+
params = {
|
135
|
+
name: name,
|
136
|
+
needsHandle: handle,
|
137
|
+
}.compact
|
138
|
+
@bindings[name] = callback
|
139
|
+
@channel.send_message_to_server('exposeBinding', params)
|
140
|
+
end
|
141
|
+
|
142
|
+
def expose_function(name, callback)
|
143
|
+
expose_binding(name, ->(_source, *args) { callback.call(*args) }, )
|
144
|
+
end
|
145
|
+
|
146
|
+
def route(url, handler)
|
147
|
+
entry = RouteHandlerEntry.new(url, handler)
|
148
|
+
@routes << entry
|
149
|
+
if @routes.count >= 1
|
150
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: true)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def unroute(url, handler: nil)
|
155
|
+
@routes.reject! do |handler_entry|
|
156
|
+
handler_entry.same_value?(url: url, handler: handler)
|
157
|
+
end
|
158
|
+
if @routes.count == 0
|
159
|
+
@channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def expect_event(event, predicate: nil, timeout: nil, &block)
|
164
|
+
wait_helper = WaitHelper.new
|
165
|
+
wait_helper.reject_on_timeout(timeout || @timeout_settings.timeout, "Timeout while waiting for event \"#{event}\"")
|
166
|
+
wait_helper.wait_for_event(self, event, predicate: predicate)
|
167
|
+
|
168
|
+
block&.call
|
169
|
+
|
170
|
+
wait_helper.promise.value!
|
171
|
+
end
|
172
|
+
|
31
173
|
private def on_close
|
32
174
|
@closed_or_closing = true
|
33
175
|
@browser&.send(:remove_context, self)
|
@@ -43,6 +185,18 @@ module Playwright
|
|
43
185
|
raise unless safe_close_error?(err)
|
44
186
|
end
|
45
187
|
|
188
|
+
def pause
|
189
|
+
@channel.send_message_to_server('pause')
|
190
|
+
end
|
191
|
+
|
192
|
+
def expect_page(predicate: nil, timeout: nil)
|
193
|
+
params = {
|
194
|
+
predicate: predicate,
|
195
|
+
timeout: timeout,
|
196
|
+
}.compact
|
197
|
+
expect_event(Events::BrowserContext::Page, params)
|
198
|
+
end
|
199
|
+
|
46
200
|
# called from Page#on_close with send(:remove_page, page), so keep private
|
47
201
|
private def remove_page(page)
|
48
202
|
@pages.delete(page)
|
@@ -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
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_channel_owner :Download do
|
3
|
+
def url
|
4
|
+
@initializer['url']
|
5
|
+
end
|
6
|
+
|
7
|
+
def suggested_filename
|
8
|
+
@initializer['suggestedFilename']
|
9
|
+
end
|
10
|
+
|
11
|
+
def delete
|
12
|
+
@channel.send_message_to_server('delete')
|
13
|
+
end
|
14
|
+
|
15
|
+
def failure
|
16
|
+
@channel.send_message_to_server('failure')
|
17
|
+
end
|
18
|
+
|
19
|
+
def path
|
20
|
+
@channel.send_message_to_server('path')
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_as(path)
|
24
|
+
@channel.send_message_to_server('saveAs', path: path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -136,8 +136,19 @@ module Playwright
|
|
136
136
|
nil
|
137
137
|
end
|
138
138
|
|
139
|
-
def select_option(
|
140
|
-
|
139
|
+
def select_option(
|
140
|
+
element: nil,
|
141
|
+
index: nil,
|
142
|
+
value: nil,
|
143
|
+
label: nil,
|
144
|
+
noWaitAfter: nil,
|
145
|
+
timeout: nil)
|
146
|
+
base_params = SelectOptionValues.new(
|
147
|
+
element: element,
|
148
|
+
index: index,
|
149
|
+
value: value,
|
150
|
+
label: label,
|
151
|
+
).as_params
|
141
152
|
params = base_params + { noWaitAfter: noWaitAfter, timeout: timeout }.compact
|
142
153
|
@channel.send_message_to_server('selectOption', params)
|
143
154
|
|
@@ -182,8 +193,8 @@ module Playwright
|
|
182
193
|
end
|
183
194
|
|
184
195
|
def set_input_files(files, noWaitAfter: nil, timeout: nil)
|
185
|
-
|
186
|
-
params =
|
196
|
+
file_payloads = InputFiles.new(files).as_params
|
197
|
+
params = { files: file_payloads, noWaitAfter: noWaitAfter, timeout: timeout }.compact
|
187
198
|
@channel.send_message_to_server('setInputFiles', params)
|
188
199
|
|
189
200
|
nil
|