playwright-ruby-client 0.3.0 → 0.5.6
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 +14 -25
- data/lib/playwright.rb +47 -9
- data/lib/playwright/channel.rb +19 -9
- data/lib/playwright/channel_owners/artifact.rb +30 -0
- data/lib/playwright/channel_owners/browser.rb +21 -0
- data/lib/playwright/channel_owners/browser_context.rb +5 -0
- data/lib/playwright/channel_owners/browser_type.rb +28 -0
- data/lib/playwright/channel_owners/element_handle.rb +7 -7
- data/lib/playwright/channel_owners/frame.rb +26 -5
- data/lib/playwright/channel_owners/js_handle.rb +2 -2
- data/lib/playwright/channel_owners/page.rb +78 -15
- data/lib/playwright/channel_owners/playwright.rb +22 -29
- 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 +5 -3
- data/lib/playwright/route_handler_entry.rb +1 -9
- data/lib/playwright/select_option_values.rb +31 -22
- data/lib/playwright/transport.rb +29 -7
- data/lib/playwright/url_matcher.rb +1 -1
- data/lib/playwright/utils.rb +8 -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 +10 -10
- data/lib/playwright_api/android_device.rb +10 -9
- data/lib/playwright_api/browser.rb +83 -8
- data/lib/playwright_api/browser_context.rb +157 -9
- data/lib/playwright_api/browser_type.rb +35 -4
- data/lib/playwright_api/console_message.rb +6 -6
- data/lib/playwright_api/dialog.rb +28 -8
- data/lib/playwright_api/element_handle.rb +111 -37
- data/lib/playwright_api/file_chooser.rb +5 -0
- data/lib/playwright_api/frame.rb +228 -37
- data/lib/playwright_api/js_handle.rb +26 -3
- data/lib/playwright_api/keyboard.rb +48 -1
- data/lib/playwright_api/mouse.rb +26 -5
- data/lib/playwright_api/page.rb +454 -46
- data/lib/playwright_api/playwright.rb +26 -9
- data/lib/playwright_api/request.rb +34 -6
- data/lib/playwright_api/response.rb +6 -6
- data/lib/playwright_api/route.rb +30 -6
- data/lib/playwright_api/selectors.rb +32 -6
- data/lib/playwright_api/touchscreen.rb +1 -1
- data/lib/playwright_api/worker.rb +25 -1
- data/playwright.gemspec +4 -2
- metadata +37 -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 -32
- 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
@@ -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
|
@@ -412,10 +421,8 @@ module Playwright
|
|
412
421
|
value: value,
|
413
422
|
label: label,
|
414
423
|
).as_params
|
415
|
-
params = base_params
|
424
|
+
params = base_params.merge({ selector: selector, noWaitAfter: noWaitAfter, timeout: timeout }.compact)
|
416
425
|
@channel.send_message_to_server('selectOption', params)
|
417
|
-
|
418
|
-
nil
|
419
426
|
end
|
420
427
|
|
421
428
|
def set_input_files(selector, files, noWaitAfter: nil, timeout: nil)
|
@@ -464,11 +471,18 @@ module Playwright
|
|
464
471
|
nil
|
465
472
|
end
|
466
473
|
|
467
|
-
def check(
|
474
|
+
def check(
|
475
|
+
selector,
|
476
|
+
force: nil,
|
477
|
+
noWaitAfter: nil,
|
478
|
+
position: nil,
|
479
|
+
timeout: nil)
|
480
|
+
|
468
481
|
params = {
|
469
482
|
selector: selector,
|
470
483
|
force: force,
|
471
484
|
noWaitAfter: noWaitAfter,
|
485
|
+
position: position,
|
472
486
|
timeout: timeout,
|
473
487
|
}.compact
|
474
488
|
@channel.send_message_to_server('check', params)
|
@@ -476,11 +490,18 @@ module Playwright
|
|
476
490
|
nil
|
477
491
|
end
|
478
492
|
|
479
|
-
def uncheck(
|
493
|
+
def uncheck(
|
494
|
+
selector,
|
495
|
+
force: nil,
|
496
|
+
noWaitAfter: nil,
|
497
|
+
position: nil,
|
498
|
+
timeout: nil)
|
499
|
+
|
480
500
|
params = {
|
481
501
|
selector: selector,
|
482
502
|
force: force,
|
483
503
|
noWaitAfter: noWaitAfter,
|
504
|
+
position: position,
|
484
505
|
timeout: timeout,
|
485
506
|
}.compact
|
486
507
|
@channel.send_message_to_server('uncheck', params)
|
@@ -28,6 +28,7 @@ module Playwright
|
|
28
28
|
@main_frame.send(:update_page_from_page, self)
|
29
29
|
@frames = Set.new
|
30
30
|
@frames << @main_frame
|
31
|
+
@opener = ChannelOwners::Page.from_nullable(@initializer['opener'])
|
31
32
|
|
32
33
|
@channel.once('close', ->(_) { on_close })
|
33
34
|
@channel.on('console', ->(params) {
|
@@ -37,9 +38,7 @@ module Playwright
|
|
37
38
|
@channel.on('crash', ->(_) { emit(Events::Page::Crash) })
|
38
39
|
@channel.on('dialog', method(:on_dialog))
|
39
40
|
@channel.on('domcontentloaded', ->(_) { emit(Events::Page::DOMContentLoaded) })
|
40
|
-
@channel.on('download',
|
41
|
-
emit(Events::Page::Download, ChannelOwners::Download.from(params['download']))
|
42
|
-
})
|
41
|
+
@channel.on('download', method(:on_download))
|
43
42
|
@channel.on('fileChooser', ->(params) {
|
44
43
|
chooser = FileChooserImpl.new(
|
45
44
|
page: self,
|
@@ -57,9 +56,6 @@ module Playwright
|
|
57
56
|
@channel.on('pageError', ->(params) {
|
58
57
|
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
59
58
|
})
|
60
|
-
@channel.on('popup', ->(params) {
|
61
|
-
emit(Events::Page::Popup, ChannelOwners::Page.from(params['page']))
|
62
|
-
})
|
63
59
|
@channel.on('request', ->(params) {
|
64
60
|
emit(Events::Page::Request, ChannelOwners::Request.from(params['request']))
|
65
61
|
})
|
@@ -82,9 +78,7 @@ module Playwright
|
|
82
78
|
@channel.on('route', ->(params) {
|
83
79
|
on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
|
84
80
|
})
|
85
|
-
@channel.on('video',
|
86
|
-
video.send(:update_relative_path, params['relativePath'])
|
87
|
-
})
|
81
|
+
@channel.on('video', method(:on_video))
|
88
82
|
@channel.on('webSocket', ->(params) {
|
89
83
|
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
90
84
|
})
|
@@ -149,6 +143,20 @@ module Playwright
|
|
149
143
|
end
|
150
144
|
end
|
151
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
|
+
|
152
160
|
# @override
|
153
161
|
def on(event, callback)
|
154
162
|
if event == Events::Page::FileChooser && listener_count(event) == 0
|
@@ -178,8 +186,17 @@ module Playwright
|
|
178
186
|
end
|
179
187
|
|
180
188
|
def opener
|
181
|
-
|
182
|
-
|
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
|
183
200
|
end
|
184
201
|
|
185
202
|
def frame(name: nil, url: nil)
|
@@ -326,6 +343,10 @@ module Playwright
|
|
326
343
|
@main_frame.wait_for_load_state(state: state, timeout: timeout)
|
327
344
|
end
|
328
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
|
+
|
329
350
|
def go_back(timeout: nil, waitUntil: nil)
|
330
351
|
params = { timeout: timeout, waitUntil: waitUntil }.compact
|
331
352
|
resp = @channel.send_message_to_server('goBack', params)
|
@@ -578,12 +599,24 @@ module Playwright
|
|
578
599
|
@main_frame.press(selector, key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
|
579
600
|
end
|
580
601
|
|
581
|
-
def check(
|
582
|
-
|
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)
|
583
610
|
end
|
584
611
|
|
585
|
-
def uncheck(
|
586
|
-
|
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)
|
587
620
|
end
|
588
621
|
|
589
622
|
def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
|
@@ -629,6 +662,36 @@ module Playwright
|
|
629
662
|
decoded_binary
|
630
663
|
end
|
631
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
|
+
|
632
695
|
class CrashedError < StandardError
|
633
696
|
def initialize
|
634
697
|
super('Page crashed')
|
@@ -24,38 +24,31 @@ module Playwright
|
|
24
24
|
@selectors ||= ::Playwright::ChannelOwners::Selectors.from(@initializer['selectors'])
|
25
25
|
end
|
26
26
|
|
27
|
-
class DeviceDescriptor
|
28
|
-
class Viewport
|
29
|
-
def initialize(hash)
|
30
|
-
@width = hash['width']
|
31
|
-
@heirhgt = hash['height']
|
32
|
-
end
|
33
|
-
attr_reader :width, :height
|
34
|
-
end
|
35
|
-
|
36
|
-
def initialize(hash)
|
37
|
-
@user_agent = hash["userAgent"]
|
38
|
-
@viewport = Viewport.new(hash["viewport"])
|
39
|
-
@device_scale_factor = hash["deviceScaleFactor"]
|
40
|
-
@is_mobile = hash["isMobile"]
|
41
|
-
@has_touch = hash["hasTouch"]
|
42
|
-
end
|
43
|
-
|
44
|
-
attr_reader :user_agent, :viewport, :device_scale_factor
|
45
|
-
|
46
|
-
def mobile?
|
47
|
-
@is_mobile
|
48
|
-
end
|
49
|
-
|
50
|
-
def has_touch?
|
51
|
-
@has_touch
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
27
|
def devices
|
56
28
|
@devices ||= @initializer['deviceDescriptors'].map do |item|
|
57
|
-
[item['name'],
|
29
|
+
[item['name'], parse_device_descriptor(item['descriptor'])]
|
58
30
|
end.to_h
|
59
31
|
end
|
32
|
+
|
33
|
+
private def parse_device_descriptor(descriptor)
|
34
|
+
# This return value can be passed into Browser#new_context as it is.
|
35
|
+
# ex:
|
36
|
+
# ```
|
37
|
+
# iPhone = playwright.devices['iPhone 6']
|
38
|
+
# context = browser.new_context(**iPhone)
|
39
|
+
# page = context.new_page
|
40
|
+
#
|
41
|
+
# ```
|
42
|
+
{
|
43
|
+
userAgent: descriptor['userAgent'],
|
44
|
+
viewport: {
|
45
|
+
width: descriptor['viewport']['width'],
|
46
|
+
height: descriptor['viewport']['height'],
|
47
|
+
},
|
48
|
+
deviceScaleFactor: descriptor['deviceScaleFactor'],
|
49
|
+
isMobile: descriptor['isMobile'],
|
50
|
+
hasTouch: descriptor['hasTouch'],
|
51
|
+
}
|
52
|
+
end
|
60
53
|
end
|
61
54
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Playwright
|
4
|
+
define_channel_owner :Stream do
|
5
|
+
def save_as(path)
|
6
|
+
File.open(path, 'wb') do |f|
|
7
|
+
loop do
|
8
|
+
binary = @channel.send_message_to_server('read')
|
9
|
+
break if !binary || binary.length == 0
|
10
|
+
f.write(Base64.strict_decode64(binary))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -12,6 +12,12 @@ module Playwright
|
|
12
12
|
@transport.on_message_received do |message|
|
13
13
|
dispatch(message)
|
14
14
|
end
|
15
|
+
@transport.on_driver_crashed do
|
16
|
+
@callbacks.each_value do |callback|
|
17
|
+
callback.reject(::Playwright::DriverCrashedError.new)
|
18
|
+
end
|
19
|
+
raise ::Playwright::DriverCrashedError.new
|
20
|
+
end
|
15
21
|
|
16
22
|
@objects = {} # Hash[ guid => ChannelOwner ]
|
17
23
|
@waiting_for_object = {} # Hash[ guid => Promise<ChannelOwner> ]
|
@@ -19,26 +25,22 @@ module Playwright
|
|
19
25
|
@root_object = RootChannelOwner.new(self)
|
20
26
|
end
|
21
27
|
|
22
|
-
def
|
23
|
-
@transport.
|
28
|
+
def async_run
|
29
|
+
@transport.async_run
|
24
30
|
end
|
25
31
|
|
26
32
|
def stop
|
27
33
|
@transport.stop
|
28
34
|
end
|
29
35
|
|
30
|
-
def
|
36
|
+
def wait_for_object_with_known_name(guid)
|
31
37
|
if @objects[guid]
|
32
38
|
return @objects[guid]
|
33
39
|
end
|
34
40
|
|
35
41
|
callback = Concurrent::Promises.resolvable_future
|
36
42
|
@waiting_for_object[guid] = callback
|
37
|
-
callback
|
38
|
-
end
|
39
|
-
|
40
|
-
def wait_for_object_with_known_name(guid)
|
41
|
-
async_wait_for_object_with_known_name.value!
|
43
|
+
callback.value!
|
42
44
|
end
|
43
45
|
|
44
46
|
def async_send_message_to_server(guid, method, params)
|
@@ -195,32 +197,9 @@ module Playwright
|
|
195
197
|
end
|
196
198
|
initializer = replace_guids_with_channels(initializer)
|
197
199
|
|
198
|
-
class_name = case type
|
199
|
-
when 'Browser'
|
200
|
-
case initializer['name']
|
201
|
-
when 'chromium'
|
202
|
-
'ChromiumBrowser'
|
203
|
-
when 'webkit'
|
204
|
-
'WebKitBrowser'
|
205
|
-
when 'firefox'
|
206
|
-
'FirefoxBrowser'
|
207
|
-
else
|
208
|
-
'Browser'
|
209
|
-
end
|
210
|
-
when 'BrowserContext'
|
211
|
-
browser_name = initializer['browserName']
|
212
|
-
if browser_name == 'chromium'
|
213
|
-
'ChromiumBrowserContext'
|
214
|
-
else
|
215
|
-
'BrowserContext'
|
216
|
-
end
|
217
|
-
else
|
218
|
-
type
|
219
|
-
end
|
220
|
-
|
221
200
|
result =
|
222
201
|
begin
|
223
|
-
ChannelOwners.const_get(
|
202
|
+
ChannelOwners.const_get(type).new(
|
224
203
|
parent,
|
225
204
|
type,
|
226
205
|
guid,
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Playwright
|
2
|
+
class Download
|
3
|
+
def initialize(url:, suggested_filename:, artifact:)
|
4
|
+
@url = url
|
5
|
+
@suggested_filename = suggested_filename
|
6
|
+
@artifact = artifact
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :url, :suggested_filename
|
10
|
+
|
11
|
+
def delete
|
12
|
+
@artifact.delete
|
13
|
+
end
|
14
|
+
|
15
|
+
def failure
|
16
|
+
@artifact.failure
|
17
|
+
end
|
18
|
+
|
19
|
+
def path
|
20
|
+
@artifact.path_after_finished
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_as(path)
|
24
|
+
@artifact.save_as(path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/playwright/errors.rb
CHANGED
@@ -27,6 +27,12 @@ module Playwright
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
class DriverCrashedError < StandardError
|
31
|
+
def initialize
|
32
|
+
super("[BUG] Playwright driver is crashed!")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
30
36
|
class TimeoutError < Error
|
31
37
|
def initialize(message:, stack: [])
|
32
38
|
super(name: 'TimeoutError', message: message, stack: stack)
|
data/lib/playwright/events.rb
CHANGED
@@ -24,8 +24,10 @@ end
|
|
24
24
|
},
|
25
25
|
|
26
26
|
BrowserContext: {
|
27
|
+
BackgroundPage: 'backgroundpage',
|
27
28
|
Close: 'close',
|
28
29
|
Page: 'page',
|
30
|
+
ServiceWorker: 'serviceworker',
|
29
31
|
},
|
30
32
|
|
31
33
|
BrowserServer: {
|
@@ -67,11 +69,6 @@ end
|
|
67
69
|
Close: 'close',
|
68
70
|
},
|
69
71
|
|
70
|
-
ChromiumBrowserContext: {
|
71
|
-
BackgroundPage: 'backgroundpage',
|
72
|
-
ServiceWorker: 'serviceworker',
|
73
|
-
},
|
74
|
-
|
75
72
|
ElectronApplication: {
|
76
73
|
Close: 'close',
|
77
74
|
Window: 'window',
|