playwright-ruby-client 0.0.6 → 0.2.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 +117 -5
- data/docs/api_coverage.md +359 -0
- data/lib/playwright.rb +6 -2
- data/lib/playwright/android_input_impl.rb +23 -0
- data/lib/playwright/api_implementation.rb +18 -0
- data/lib/playwright/channel.rb +7 -0
- data/lib/playwright/channel_owner.rb +6 -7
- data/lib/playwright/channel_owners/android.rb +10 -1
- data/lib/playwright/channel_owners/android_device.rb +163 -0
- data/lib/playwright/channel_owners/browser.rb +14 -14
- data/lib/playwright/channel_owners/browser_context.rb +10 -2
- data/lib/playwright/channel_owners/download.rb +27 -0
- data/lib/playwright/channel_owners/element_handle.rb +243 -1
- data/lib/playwright/channel_owners/frame.rb +269 -22
- data/lib/playwright/channel_owners/js_handle.rb +51 -0
- data/lib/playwright/channel_owners/page.rb +379 -34
- data/lib/playwright/channel_owners/request.rb +9 -1
- data/lib/playwright/channel_owners/webkit_browser.rb +1 -1
- data/lib/playwright/connection.rb +9 -6
- data/lib/playwright/errors.rb +2 -2
- 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 +42 -0
- data/lib/playwright/javascript/expression.rb +15 -0
- data/lib/playwright/javascript/function.rb +15 -0
- data/lib/playwright/javascript/value_parser.rb +1 -1
- data/lib/playwright/javascript/value_serializer.rb +11 -11
- data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +6 -2
- data/lib/playwright/mouse_impl.rb +7 -0
- data/lib/playwright/playwright_api.rb +66 -19
- data/lib/playwright/select_option_values.rb +42 -0
- data/lib/playwright/timeout_settings.rb +1 -1
- data/lib/playwright/touchscreen_impl.rb +7 -0
- data/lib/playwright/utils.rb +18 -0
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright/wait_helper.rb +1 -1
- data/lib/playwright_api/android.rb +32 -0
- data/lib/playwright_api/android_device.rb +77 -0
- data/lib/playwright_api/android_input.rb +25 -0
- data/lib/playwright_api/binding_call.rb +10 -6
- data/lib/playwright_api/browser.rb +22 -22
- data/lib/playwright_api/browser_context.rb +31 -22
- data/lib/playwright_api/browser_type.rb +16 -56
- data/lib/playwright_api/chromium_browser_context.rb +10 -8
- data/lib/playwright_api/console_message.rb +9 -10
- data/lib/playwright_api/dialog.rb +7 -3
- data/lib/playwright_api/download.rb +28 -11
- data/lib/playwright_api/element_handle.rb +139 -127
- data/lib/playwright_api/file_chooser.rb +17 -9
- data/lib/playwright_api/frame.rb +148 -148
- data/lib/playwright_api/js_handle.rb +26 -22
- data/lib/playwright_api/keyboard.rb +6 -6
- data/lib/playwright_api/page.rb +215 -179
- data/lib/playwright_api/playwright.rb +34 -46
- data/lib/playwright_api/request.rb +7 -8
- data/lib/playwright_api/response.rb +10 -6
- data/lib/playwright_api/selectors.rb +13 -9
- data/lib/playwright_api/web_socket.rb +10 -1
- data/lib/playwright_api/worker.rb +13 -13
- data/playwright.gemspec +1 -0
- metadata +32 -6
- 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
data/lib/playwright.rb
CHANGED
@@ -10,13 +10,17 @@ require 'concurrent'
|
|
10
10
|
require 'playwright/errors'
|
11
11
|
require 'playwright/events'
|
12
12
|
require 'playwright/event_emitter'
|
13
|
+
require 'playwright/event_emitter_proxy'
|
13
14
|
require 'playwright/javascript'
|
14
15
|
require 'playwright/utils'
|
15
16
|
|
17
|
+
require 'playwright/api_implementation'
|
16
18
|
require 'playwright/channel'
|
17
19
|
require 'playwright/channel_owner'
|
18
|
-
require 'playwright/
|
20
|
+
require 'playwright/http_headers'
|
21
|
+
require 'playwright/input_files'
|
19
22
|
require 'playwright/connection'
|
23
|
+
require 'playwright/select_option_values'
|
20
24
|
require 'playwright/timeout_settings'
|
21
25
|
require 'playwright/transport'
|
22
26
|
require 'playwright/url_matcher'
|
@@ -35,7 +39,7 @@ module Playwright
|
|
35
39
|
|
36
40
|
playwright_promise = connection.async_wait_for_object_with_known_name('Playwright')
|
37
41
|
Thread.new { connection.run }
|
38
|
-
playwright = PlaywrightApi.
|
42
|
+
playwright = PlaywrightApi.wrap(playwright_promise.value!)
|
39
43
|
begin
|
40
44
|
block.call(playwright)
|
41
45
|
ensure
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_api_implementation :AndroidInputImpl do
|
3
|
+
def initialize(channel)
|
4
|
+
@channel = channel
|
5
|
+
end
|
6
|
+
|
7
|
+
def type(text)
|
8
|
+
@channel.send_message_to_server('inputType', text: text)
|
9
|
+
end
|
10
|
+
|
11
|
+
def press(key)
|
12
|
+
@channel.send_message_to_server('inputPress', key: key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tap_point(point)
|
16
|
+
@channel.send_message_to_server('inputTap', point: point)
|
17
|
+
end
|
18
|
+
|
19
|
+
def drag(from, to, steps)
|
20
|
+
@channel.send_message_to_server('inputDrag', from: from, to: to, steps: steps)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -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
@@ -39,13 +39,14 @@ module Playwright
|
|
39
39
|
|
40
40
|
attr_reader :channel
|
41
41
|
|
42
|
-
|
42
|
+
# used only from Connection. Not intended for public use. So keep private.
|
43
|
+
private def dispose!
|
43
44
|
# Clean up from parent and connection.
|
44
45
|
@parent&.send(:delete_object_from_child, @guid)
|
45
46
|
@connection.send(:delete_object_from_channel_owner, @guid)
|
46
47
|
|
47
48
|
# Dispose all children.
|
48
|
-
@objects.each_value(
|
49
|
+
@objects.each_value { |object| object.send(:dispose!) }
|
49
50
|
@objects.clear
|
50
51
|
end
|
51
52
|
|
@@ -58,16 +59,14 @@ module Playwright
|
|
58
59
|
"#<#{@guid}>"
|
59
60
|
end
|
60
61
|
|
61
|
-
private
|
62
|
-
|
63
|
-
def after_initialize
|
62
|
+
private def after_initialize
|
64
63
|
end
|
65
64
|
|
66
|
-
def update_object_from_child(guid, child)
|
65
|
+
private def update_object_from_child(guid, child)
|
67
66
|
@objects[guid] = child
|
68
67
|
end
|
69
68
|
|
70
|
-
def delete_object_from_child(guid)
|
69
|
+
private def delete_object_from_child(guid)
|
71
70
|
@objects.delete(guid)
|
72
71
|
end
|
73
72
|
end
|
@@ -1,3 +1,12 @@
|
|
1
1
|
module Playwright
|
2
|
-
define_channel_owner :Android
|
2
|
+
define_channel_owner :Android do
|
3
|
+
private def after_initialize
|
4
|
+
@timeout_settings = TimeoutSettings.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def devices
|
8
|
+
resp = @channel.send_message_to_server('devices')
|
9
|
+
resp.map { |device| ChannelOwners::AndroidDevice.from(device) }
|
10
|
+
end
|
11
|
+
end
|
3
12
|
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_channel_owner :AndroidDevice do
|
3
|
+
include Utils::PrepareBrowserContextOptions
|
4
|
+
|
5
|
+
private def after_initialize
|
6
|
+
@input = AndroidInputImpl.new(@channel)
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :input
|
10
|
+
|
11
|
+
def serial
|
12
|
+
@initializer['serial']
|
13
|
+
end
|
14
|
+
|
15
|
+
def model
|
16
|
+
@initializer['model']
|
17
|
+
end
|
18
|
+
|
19
|
+
private def to_regex(value)
|
20
|
+
case value
|
21
|
+
when nil
|
22
|
+
nil
|
23
|
+
when Regexp
|
24
|
+
value
|
25
|
+
else
|
26
|
+
Regexp.new("^#{value}$")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private def to_selector_channel(selector)
|
31
|
+
{
|
32
|
+
checkable: selector[:checkable],
|
33
|
+
checked: selector[:checked],
|
34
|
+
clazz: to_regex(selector[:clazz]),
|
35
|
+
pkg: to_regex(selector[:pkg]),
|
36
|
+
desc: to_regex(selector[:desc]),
|
37
|
+
res: to_regex(selector[:res]),
|
38
|
+
text: to_regex(selector[:text]),
|
39
|
+
clickable: selector[:clickable],
|
40
|
+
depth: selector[:depth],
|
41
|
+
enabled: selector[:enabled],
|
42
|
+
focusable: selector[:focusable],
|
43
|
+
focused: selector[:focused],
|
44
|
+
hasChild: selector[:hasChild] ? { selector: to_selector_channel(selector[:hasChild][:selector]) } : nil,
|
45
|
+
hasDescendant: selector[:hasDescendant] ? {
|
46
|
+
selector: to_selector_channel(selector[:hasDescendant][:selector]),
|
47
|
+
maxDepth: selector[:hasDescendant][:maxDepth],
|
48
|
+
} : nil,
|
49
|
+
longClickable: selector[:longClickable],
|
50
|
+
scrollable: selector[:scrollable],
|
51
|
+
selected: selector[:selected],
|
52
|
+
}.compact
|
53
|
+
end
|
54
|
+
|
55
|
+
def tap_on(selector, duration: nil, timeout: nil)
|
56
|
+
params = {
|
57
|
+
selector: to_selector_channel(selector),
|
58
|
+
duration: duration,
|
59
|
+
timeout: timeout,
|
60
|
+
}.compact
|
61
|
+
@channel.send_message_to_server('tap', params)
|
62
|
+
end
|
63
|
+
|
64
|
+
def info(selector)
|
65
|
+
@channel.send_message_to_server('info', selector: to_selector_channel(selector))
|
66
|
+
end
|
67
|
+
|
68
|
+
def tree
|
69
|
+
@channel.send_message_to_server('tree')
|
70
|
+
end
|
71
|
+
|
72
|
+
def screenshot(path: nil)
|
73
|
+
encoded_binary = @channel.send_message_to_server('screenshot')
|
74
|
+
decoded_binary = Base64.strict_decode64(encoded_binary)
|
75
|
+
if path
|
76
|
+
File.open(path, 'wb') do |f|
|
77
|
+
f.write(decoded_binary)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
decoded_binary
|
81
|
+
end
|
82
|
+
|
83
|
+
def close
|
84
|
+
@channel.send_message_to_server('close')
|
85
|
+
emit(Events::AndroidDevice::Close)
|
86
|
+
end
|
87
|
+
|
88
|
+
def shell(command)
|
89
|
+
resp = @channel.send_message_to_server('shell', command: command)
|
90
|
+
Base64.strict_decode64(resp)
|
91
|
+
end
|
92
|
+
|
93
|
+
def launch_browser(
|
94
|
+
pkg: nil,
|
95
|
+
acceptDownloads: nil,
|
96
|
+
bypassCSP: nil,
|
97
|
+
colorScheme: nil,
|
98
|
+
deviceScaleFactor: nil,
|
99
|
+
extraHTTPHeaders: nil,
|
100
|
+
geolocation: nil,
|
101
|
+
hasTouch: nil,
|
102
|
+
httpCredentials: nil,
|
103
|
+
ignoreHTTPSErrors: nil,
|
104
|
+
isMobile: nil,
|
105
|
+
javaScriptEnabled: nil,
|
106
|
+
locale: nil,
|
107
|
+
noViewport: nil,
|
108
|
+
offline: nil,
|
109
|
+
permissions: nil,
|
110
|
+
proxy: nil,
|
111
|
+
record_har_omit_content: nil,
|
112
|
+
record_har_path: nil,
|
113
|
+
record_video_dir: nil,
|
114
|
+
record_video_size: nil,
|
115
|
+
storageState: nil,
|
116
|
+
timezoneId: nil,
|
117
|
+
userAgent: nil,
|
118
|
+
viewport: nil,
|
119
|
+
&block)
|
120
|
+
params = {
|
121
|
+
pkg: pkg,
|
122
|
+
acceptDownloads: acceptDownloads,
|
123
|
+
bypassCSP: bypassCSP,
|
124
|
+
colorScheme: colorScheme,
|
125
|
+
deviceScaleFactor: deviceScaleFactor,
|
126
|
+
extraHTTPHeaders: extraHTTPHeaders,
|
127
|
+
geolocation: geolocation,
|
128
|
+
hasTouch: hasTouch,
|
129
|
+
httpCredentials: httpCredentials,
|
130
|
+
ignoreHTTPSErrors: ignoreHTTPSErrors,
|
131
|
+
isMobile: isMobile,
|
132
|
+
javaScriptEnabled: javaScriptEnabled,
|
133
|
+
locale: locale,
|
134
|
+
noViewport: noViewport,
|
135
|
+
offline: offline,
|
136
|
+
permissions: permissions,
|
137
|
+
proxy: proxy,
|
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,
|
142
|
+
storageState: storageState,
|
143
|
+
timezoneId: timezoneId,
|
144
|
+
userAgent: userAgent,
|
145
|
+
viewport: viewport,
|
146
|
+
}.compact
|
147
|
+
prepare_browser_context_options(params)
|
148
|
+
|
149
|
+
resp = @channel.send_message_to_server('launchBrowser', params)
|
150
|
+
context = ChannelOwners::BrowserContext.from(resp)
|
151
|
+
|
152
|
+
if block
|
153
|
+
begin
|
154
|
+
block.call(context)
|
155
|
+
ensure
|
156
|
+
context.close
|
157
|
+
end
|
158
|
+
else
|
159
|
+
context
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -2,8 +2,9 @@ module Playwright
|
|
2
2
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser.py
|
3
3
|
define_channel_owner :Browser do
|
4
4
|
include Utils::Errors::SafeCloseError
|
5
|
+
include Utils::PrepareBrowserContextOptions
|
5
6
|
|
6
|
-
def after_initialize
|
7
|
+
private def after_initialize
|
7
8
|
@contexts = Set.new
|
8
9
|
@channel.on('close', method(:on_close))
|
9
10
|
end
|
@@ -16,26 +17,25 @@ module Playwright
|
|
16
17
|
@connected
|
17
18
|
end
|
18
19
|
|
19
|
-
def new_context(**options)
|
20
|
+
def new_context(**options, &block)
|
20
21
|
params = options.dup
|
21
|
-
|
22
|
-
if params[:viewport] == 0
|
23
|
-
params.delete(:viewport)
|
24
|
-
params[:noDefaultViewport] = true
|
25
|
-
end
|
26
|
-
if params[:extraHTTPHeaders]
|
27
|
-
# TODO
|
28
|
-
end
|
29
|
-
if params[:storageState].is_a?(String)
|
30
|
-
params[:storageState] = JSON.parse(File.read(params[:storageState]))
|
31
|
-
end
|
22
|
+
prepare_browser_context_options(params)
|
32
23
|
|
33
24
|
resp = @channel.send_message_to_server('newContext', params.compact)
|
34
25
|
context = ChannelOwners::BrowserContext.from(resp)
|
35
26
|
@contexts << context
|
36
27
|
context.browser = self
|
37
28
|
context.options = params
|
38
|
-
|
29
|
+
|
30
|
+
if block
|
31
|
+
begin
|
32
|
+
block.call(context)
|
33
|
+
ensure
|
34
|
+
context.close
|
35
|
+
end
|
36
|
+
else
|
37
|
+
context
|
38
|
+
end
|
39
39
|
end
|
40
40
|
|
41
41
|
def new_page(**options)
|
@@ -4,11 +4,14 @@ module Playwright
|
|
4
4
|
include Utils::Errors::SafeCloseError
|
5
5
|
attr_writer :browser, :owner_page, :options
|
6
6
|
|
7
|
-
def after_initialize
|
7
|
+
private def after_initialize
|
8
8
|
@pages = Set.new
|
9
9
|
|
10
10
|
@channel.once('close', ->(_) { on_close })
|
11
|
-
@channel.on('page', ->(
|
11
|
+
@channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
|
12
|
+
@channel.on('route', ->(params) {
|
13
|
+
on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
|
14
|
+
})
|
12
15
|
end
|
13
16
|
|
14
17
|
private def on_page(page)
|
@@ -17,6 +20,11 @@ module Playwright
|
|
17
20
|
emit(Events::BrowserContext::Page, page)
|
18
21
|
end
|
19
22
|
|
23
|
+
private def on_route(route, request)
|
24
|
+
# @routes.each ...
|
25
|
+
route.continue_
|
26
|
+
end
|
27
|
+
|
20
28
|
def pages
|
21
29
|
@pages.to_a
|
22
30
|
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
|
@@ -3,6 +3,91 @@ require_relative './js_handle'
|
|
3
3
|
module Playwright
|
4
4
|
module ChannelOwners
|
5
5
|
class ElementHandle < JSHandle
|
6
|
+
def as_element
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
def owner_frame
|
11
|
+
resp = @channel.send_message_to_server('ownerFrame')
|
12
|
+
ChannelOwners::Frame.from_nullable(resp)
|
13
|
+
end
|
14
|
+
|
15
|
+
def content_frame
|
16
|
+
resp = @channel.send_message_to_server('contentFrame')
|
17
|
+
ChannelOwners::Frame.from_nullable(resp)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_attribute(name)
|
21
|
+
@channel.send_message_to_server('getAttribute', name: name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def text_content
|
25
|
+
@channel.send_message_to_server('textContent')
|
26
|
+
end
|
27
|
+
|
28
|
+
def inner_text
|
29
|
+
@channel.send_message_to_server('innerText')
|
30
|
+
end
|
31
|
+
|
32
|
+
def inner_html
|
33
|
+
@channel.send_message_to_server('innerHTML')
|
34
|
+
end
|
35
|
+
|
36
|
+
def checked?
|
37
|
+
@channel.send_message_to_server('isChecked')
|
38
|
+
end
|
39
|
+
|
40
|
+
def disabled?
|
41
|
+
@channel.send_message_to_server('isDisabled')
|
42
|
+
end
|
43
|
+
|
44
|
+
def editable?
|
45
|
+
@channel.send_message_to_server('isEditable')
|
46
|
+
end
|
47
|
+
|
48
|
+
def enabled?
|
49
|
+
@channel.send_message_to_server('isEnabled')
|
50
|
+
end
|
51
|
+
|
52
|
+
def hidden?
|
53
|
+
@channel.send_message_to_server('isHidden')
|
54
|
+
end
|
55
|
+
|
56
|
+
def visible?
|
57
|
+
@channel.send_message_to_server('isVisible')
|
58
|
+
end
|
59
|
+
|
60
|
+
def dispatch_event(type, eventInit: nil)
|
61
|
+
params = {
|
62
|
+
type: type,
|
63
|
+
eventInit: JavaScript::ValueSerializer.new(eventInit).serialize,
|
64
|
+
}.compact
|
65
|
+
@channel.send_message_to_server('dispatchEvent', params)
|
66
|
+
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def scroll_into_view_if_needed(timeout: nil)
|
71
|
+
params = {
|
72
|
+
timeout: timeout,
|
73
|
+
}.compact
|
74
|
+
@channel.send_message_to_server('scrollIntoViewIfNeeded', params)
|
75
|
+
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def hover(force: nil, modifiers: nil, position: nil, timeout: nil)
|
80
|
+
params = {
|
81
|
+
force: force,
|
82
|
+
modifiers: modifiers,
|
83
|
+
position: position,
|
84
|
+
timeout: timeout,
|
85
|
+
}
|
86
|
+
@channel.send_message_to_server('hover', params)
|
87
|
+
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
6
91
|
def click(
|
7
92
|
button: nil,
|
8
93
|
clickCount: nil,
|
@@ -28,7 +113,100 @@ module Playwright
|
|
28
113
|
nil
|
29
114
|
end
|
30
115
|
|
31
|
-
def
|
116
|
+
def dblclick(
|
117
|
+
button: nil,
|
118
|
+
delay: nil,
|
119
|
+
force: nil,
|
120
|
+
modifiers: nil,
|
121
|
+
noWaitAfter: nil,
|
122
|
+
position: nil,
|
123
|
+
timeout: nil)
|
124
|
+
|
125
|
+
params = {
|
126
|
+
button: button,
|
127
|
+
delay: delay,
|
128
|
+
force: force,
|
129
|
+
modifiers: modifiers,
|
130
|
+
noWaitAfter: noWaitAfter,
|
131
|
+
position: position,
|
132
|
+
timeout: timeout,
|
133
|
+
}.compact
|
134
|
+
@channel.send_message_to_server('dblclick', params)
|
135
|
+
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
|
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
|
152
|
+
params = base_params + { noWaitAfter: noWaitAfter, timeout: timeout }.compact
|
153
|
+
@channel.send_message_to_server('selectOption', params)
|
154
|
+
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def tap_point(
|
159
|
+
force: nil,
|
160
|
+
modifiers: nil,
|
161
|
+
noWaitAfter: nil,
|
162
|
+
position: nil,
|
163
|
+
timeout: nil)
|
164
|
+
|
165
|
+
params = {
|
166
|
+
force: force,
|
167
|
+
modifiers: modifiers,
|
168
|
+
noWaitAfter: noWaitAfter,
|
169
|
+
position: position,
|
170
|
+
timeout: timeout,
|
171
|
+
}.compact
|
172
|
+
@channel.send_message_to_server('tap', params)
|
173
|
+
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
def fill(value, noWaitAfter: nil, timeout: nil)
|
178
|
+
params = {
|
179
|
+
value: value,
|
180
|
+
noWaitAfter: noWaitAfter,
|
181
|
+
timeout: timeout,
|
182
|
+
}
|
183
|
+
@channel.send_message_to_server('fill', params)
|
184
|
+
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
|
188
|
+
def select_text(timeout: nil)
|
189
|
+
params = { timeout: timeout }.compact
|
190
|
+
@channel.send_message_to_server('selectText', params)
|
191
|
+
|
192
|
+
nil
|
193
|
+
end
|
194
|
+
|
195
|
+
def set_input_files(files, noWaitAfter: nil, timeout: nil)
|
196
|
+
file_payloads = InputFiles.new(files).as_params
|
197
|
+
params = { files: file_payloads, noWaitAfter: noWaitAfter, timeout: timeout }.compact
|
198
|
+
@channel.send_message_to_server('setInputFiles', params)
|
199
|
+
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
|
203
|
+
def focus
|
204
|
+
@channel.send_message_to_server('focus')
|
205
|
+
|
206
|
+
nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def type(text, delay: nil, noWaitAfter: nil, timeout: nil)
|
32
210
|
params = {
|
33
211
|
text: text,
|
34
212
|
delay: delay,
|
@@ -52,6 +230,56 @@ module Playwright
|
|
52
230
|
nil
|
53
231
|
end
|
54
232
|
|
233
|
+
def check(force: nil, noWaitAfter: nil, timeout: nil)
|
234
|
+
params = {
|
235
|
+
force: force,
|
236
|
+
noWaitAfter: noWaitAfter,
|
237
|
+
timeout: timeout,
|
238
|
+
}.compact
|
239
|
+
@channel.send_message_to_server('check', params)
|
240
|
+
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
|
244
|
+
def uncheck(force: nil, noWaitAfter: nil, timeout: nil)
|
245
|
+
params = {
|
246
|
+
force: force,
|
247
|
+
noWaitAfter: noWaitAfter,
|
248
|
+
timeout: timeout,
|
249
|
+
}.compact
|
250
|
+
@channel.send_message_to_server('uncheck', params)
|
251
|
+
|
252
|
+
nil
|
253
|
+
end
|
254
|
+
|
255
|
+
def bounding_box
|
256
|
+
@channel.send_message_to_server('boundingBox')
|
257
|
+
end
|
258
|
+
|
259
|
+
def screenshot(
|
260
|
+
omitBackground: nil,
|
261
|
+
path: nil,
|
262
|
+
quality: nil,
|
263
|
+
timeout: nil,
|
264
|
+
type: nil)
|
265
|
+
|
266
|
+
params = {
|
267
|
+
omitBackground: omitBackground,
|
268
|
+
path: path,
|
269
|
+
quality: quality,
|
270
|
+
timeout: timeout,
|
271
|
+
type: type,
|
272
|
+
}.compact
|
273
|
+
encoded_binary = @channel.send_message_to_server('screenshot', params)
|
274
|
+
decoded_binary = Base64.strict_decode64(encoded_binary)
|
275
|
+
if path
|
276
|
+
File.open(path, 'wb') do |f|
|
277
|
+
f.write(decoded_binary)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
decoded_binary
|
281
|
+
end
|
282
|
+
|
55
283
|
def query_selector(selector)
|
56
284
|
resp = @channel.send_message_to_server('querySelector', selector: selector)
|
57
285
|
ChannelOwners::ElementHandle.from_nullable(resp)
|
@@ -78,6 +306,20 @@ module Playwright
|
|
78
306
|
JavaScript::Expression.new(pageFunction).eval_on_selector_all(@channel, selector)
|
79
307
|
end
|
80
308
|
end
|
309
|
+
|
310
|
+
def wait_for_element_state(state, timeout: nil)
|
311
|
+
params = { state: state, timeout: timeout }.compact
|
312
|
+
@channel.send_message_to_server('waitForElementState', params)
|
313
|
+
|
314
|
+
nil
|
315
|
+
end
|
316
|
+
|
317
|
+
def wait_for_selector(selector, state: nil, timeout: nil)
|
318
|
+
params = { selector: selector, state: state, timeout: timeout }.compact
|
319
|
+
resp = @channel.send_message_to_server('waitForSelector', params)
|
320
|
+
|
321
|
+
ChannelOwners::ElementHandle.from_nullable(resp)
|
322
|
+
end
|
81
323
|
end
|
82
324
|
end
|
83
325
|
end
|