playwright-ruby-client 0.3.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -5
- data/docs/api_coverage.md +14 -25
- 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 +1 -1
- 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 +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/route_handler_entry.rb +1 -9
- data/lib/playwright/transport.rb +27 -6
- 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.rb +47 -9
- 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 +163 -15
- 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 +456 -48
- data/lib/playwright_api/playwright.rb +26 -9
- data/lib/playwright_api/request.rb +34 -6
- data/lib/playwright_api/response.rb +8 -8
- 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
@@ -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',
|
@@ -3,5 +3,46 @@ module Playwright
|
|
3
3
|
def initialize(channel)
|
4
4
|
@channel = channel
|
5
5
|
end
|
6
|
+
|
7
|
+
def move(x, y, steps: nil)
|
8
|
+
params = { x: x, y: y, steps: steps }.compact
|
9
|
+
@channel.send_message_to_server('mouseMove', params)
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def down(button: nil, clickCount: nil)
|
14
|
+
params = { button: button, clickCount: clickCount }.compact
|
15
|
+
@channel.send_message_to_server('mouseDown', params)
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def up(button: nil, clickCount: nil)
|
20
|
+
params = { button: button, clickCount: clickCount }.compact
|
21
|
+
@channel.send_message_to_server('mouseUp', params)
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def click(
|
26
|
+
x,
|
27
|
+
y,
|
28
|
+
button: nil,
|
29
|
+
clickCount: nil,
|
30
|
+
delay: nil)
|
31
|
+
|
32
|
+
params = {
|
33
|
+
x: x,
|
34
|
+
y: y,
|
35
|
+
button: button,
|
36
|
+
clickCount: clickCount,
|
37
|
+
delay: delay,
|
38
|
+
}.compact
|
39
|
+
@channel.send_message_to_server('mouseClick', params)
|
40
|
+
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def dblclick(x, y, button: nil, delay: nil)
|
45
|
+
click(x, y, button: button, clickCount: 2, delay: delay)
|
46
|
+
end
|
6
47
|
end
|
7
48
|
end
|
@@ -9,7 +9,7 @@ module Playwright
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def handle(route, request)
|
12
|
-
if
|
12
|
+
if @url_matcher.match?(request.url)
|
13
13
|
@handler.call(route, request)
|
14
14
|
true
|
15
15
|
else
|
@@ -24,13 +24,5 @@ module Playwright
|
|
24
24
|
@url_value == url
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
28
|
-
private def url_match?(request_url)
|
29
|
-
if @url_value.is_a?(Regexp)
|
30
|
-
@url_matcher.match?(request_url)
|
31
|
-
else
|
32
|
-
@url_matcher.match?(request_url) || File.fnmatch?(@url_value, request_url)
|
33
|
-
end
|
34
|
-
end
|
35
27
|
end
|
36
28
|
end
|
data/lib/playwright/transport.rb
CHANGED
@@ -12,20 +12,27 @@ module Playwright
|
|
12
12
|
def initialize(playwright_cli_executable_path:)
|
13
13
|
@driver_executable_path = playwright_cli_executable_path
|
14
14
|
@debug = ENV['DEBUG'].to_s == 'true' || ENV['DEBUG'].to_s == '1'
|
15
|
+
@mutex = Mutex.new
|
15
16
|
end
|
16
17
|
|
17
18
|
def on_message_received(&block)
|
18
19
|
@on_message = block
|
19
20
|
end
|
20
21
|
|
22
|
+
def on_driver_crashed(&block)
|
23
|
+
@on_driver_crashed = block
|
24
|
+
end
|
25
|
+
|
21
26
|
class AlreadyDisconnectedError < StandardError ; end
|
22
27
|
|
23
28
|
# @param message [Hash]
|
24
29
|
def send_message(message)
|
25
30
|
debug_send_message(message) if @debug
|
26
31
|
msg = JSON.dump(message)
|
27
|
-
@
|
28
|
-
|
32
|
+
@mutex.synchronize {
|
33
|
+
@stdin.write([msg.size].pack('V')) # unsigned 32bit, little endian
|
34
|
+
@stdin.write(msg)
|
35
|
+
}
|
29
36
|
rescue Errno::EPIPE
|
30
37
|
raise AlreadyDisconnectedError.new('send_message failed')
|
31
38
|
end
|
@@ -33,18 +40,17 @@ module Playwright
|
|
33
40
|
# Terminate playwright-cli driver.
|
34
41
|
def stop
|
35
42
|
[@stdin, @stdout, @stderr].each { |io| io.close unless io.closed? }
|
43
|
+
@thread&.terminate
|
36
44
|
end
|
37
45
|
|
38
46
|
# Start `playwright-cli run-driver`
|
39
47
|
#
|
40
48
|
# @note This method blocks until playwright-cli exited. Consider using Thread or Future.
|
41
|
-
def
|
42
|
-
@stdin, @stdout, @stderr, @thread = Open3.popen3(@driver_executable_path
|
49
|
+
def async_run
|
50
|
+
@stdin, @stdout, @stderr, @thread = Open3.popen3("#{@driver_executable_path} run-driver")
|
43
51
|
|
44
52
|
Thread.new { handle_stdout }
|
45
53
|
Thread.new { handle_stderr }
|
46
|
-
|
47
|
-
@thread.join
|
48
54
|
end
|
49
55
|
|
50
56
|
private
|
@@ -69,6 +75,21 @@ module Playwright
|
|
69
75
|
|
70
76
|
def handle_stderr
|
71
77
|
while err = @stderr.read
|
78
|
+
# sometimed driver crashes with the error below.
|
79
|
+
# --------
|
80
|
+
# undefined:1
|
81
|
+
# �
|
82
|
+
# ^
|
83
|
+
|
84
|
+
# SyntaxError: Unexpected token � in JSON at position 0
|
85
|
+
# at JSON.parse (<anonymous>)
|
86
|
+
# at Transport.transport.onmessage (/home/runner/work/playwright-ruby-client/playwright-ruby-client/node_modules/playwright/lib/cli/driver.js:42:73)
|
87
|
+
# at Immediate.<anonymous> (/home/runner/work/playwright-ruby-client/playwright-ruby-client/node_modules/playwright/lib/protocol/transport.js:74:26)
|
88
|
+
# at processImmediate (internal/timers.js:461:21)
|
89
|
+
if err.include?('undefined:1')
|
90
|
+
@on_driver_crashed&.call
|
91
|
+
break
|
92
|
+
end
|
72
93
|
$stderr.write(err)
|
73
94
|
end
|
74
95
|
rescue IOError
|
data/lib/playwright/utils.rb
CHANGED
@@ -11,6 +11,14 @@ module Playwright
|
|
11
11
|
if params[:extraHTTPHeaders]
|
12
12
|
params[:extraHTTPHeaders] = ::Playwright::HttpHeaders.new(params[:extraHTTPHeaders]).as_serialized
|
13
13
|
end
|
14
|
+
if params[:record_video_dir]
|
15
|
+
params[:recordVideo] = {
|
16
|
+
dir: params.delete(:record_video_dir)
|
17
|
+
}
|
18
|
+
if params[:record_video_size]
|
19
|
+
params[:recordVideo][:size] = params.delete(:record_video_size)
|
20
|
+
end
|
21
|
+
end
|
14
22
|
if params[:storageState].is_a?(String)
|
15
23
|
params[:storageState] = JSON.parse(File.read(params[:storageState]))
|
16
24
|
end
|
data/lib/playwright/version.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Playwright
|
2
|
+
class Video
|
3
|
+
def initialize(page)
|
4
|
+
@page = page
|
5
|
+
@artifact = Concurrent::Promises.resolvable_future
|
6
|
+
if @page.closed?
|
7
|
+
on_page_closed
|
8
|
+
else
|
9
|
+
page.once('close', -> { on_page_closed })
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private def on_page_closed
|
14
|
+
unless @artifact.resolved?
|
15
|
+
@artifact.reject('Page closed')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# called only from Page#on_video via send(:set_artifact, artifact)
|
20
|
+
private def set_artifact(artifact)
|
21
|
+
@artifact.fulfill(artifact)
|
22
|
+
end
|
23
|
+
|
24
|
+
def path
|
25
|
+
wait_for_artifact_and do |artifact|
|
26
|
+
artifact.absolute_path
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def save_as(path)
|
31
|
+
wait_for_artifact_and do |artifact|
|
32
|
+
artifact.save_as(path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete
|
37
|
+
wait_for_artifact_and do |artifact|
|
38
|
+
artifact.delete
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private def wait_for_artifact_and(&block)
|
43
|
+
artifact = @artifact.value!
|
44
|
+
unless artifact
|
45
|
+
raise 'Page did not produce any video frames'
|
46
|
+
end
|
47
|
+
|
48
|
+
block.call(artifact)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -22,9 +22,9 @@ module Playwright
|
|
22
22
|
def reject_on_timeout(timeout_ms, message)
|
23
23
|
return if timeout_ms <= 0
|
24
24
|
|
25
|
-
Concurrent::Promises.schedule(timeout_ms / 1000.0)
|
25
|
+
Concurrent::Promises.schedule(timeout_ms / 1000.0) do
|
26
26
|
reject(TimeoutError.new(message: message))
|
27
|
-
|
27
|
+
end
|
28
28
|
|
29
29
|
self
|
30
30
|
end
|
data/lib/playwright.rb
CHANGED
@@ -17,6 +17,7 @@ require 'playwright/utils'
|
|
17
17
|
require 'playwright/api_implementation'
|
18
18
|
require 'playwright/channel'
|
19
19
|
require 'playwright/channel_owner'
|
20
|
+
require 'playwright/download'
|
20
21
|
require 'playwright/http_headers'
|
21
22
|
require 'playwright/input_files'
|
22
23
|
require 'playwright/connection'
|
@@ -26,6 +27,7 @@ require 'playwright/timeout_settings'
|
|
26
27
|
require 'playwright/transport'
|
27
28
|
require 'playwright/url_matcher'
|
28
29
|
require 'playwright/version'
|
30
|
+
require 'playwright/video'
|
29
31
|
require 'playwright/wait_helper'
|
30
32
|
|
31
33
|
require 'playwright/playwright_api'
|
@@ -33,18 +35,54 @@ require 'playwright/playwright_api'
|
|
33
35
|
Dir[File.join(__dir__, 'playwright_api', '*.rb')].each { |f| require f }
|
34
36
|
|
35
37
|
module Playwright
|
36
|
-
|
37
|
-
|
38
|
+
class Execution
|
39
|
+
def initialize(connection, playwright)
|
40
|
+
@connection = connection
|
41
|
+
@playwright = playwright
|
42
|
+
end
|
43
|
+
|
44
|
+
def stop
|
45
|
+
@connection.stop
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_reader :playwright
|
49
|
+
end
|
38
50
|
|
51
|
+
# Recommended to call this method with block.
|
52
|
+
#
|
53
|
+
# Playwright.create(...) do |playwright|
|
54
|
+
# browser = playwright.chromium.launch
|
55
|
+
# ...
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# When we use this method without block, an instance of Puppeteer::Execution is returned
|
59
|
+
# and we *must* call execution.stop on the end.
|
60
|
+
# The instance of playwright is available by calling execution.playwright
|
61
|
+
module_function def create(playwright_cli_executable_path:, &block)
|
39
62
|
connection = Connection.new(playwright_cli_executable_path: playwright_cli_executable_path)
|
63
|
+
connection.async_run
|
64
|
+
|
65
|
+
execution =
|
66
|
+
begin
|
67
|
+
playwright = connection.wait_for_object_with_known_name('Playwright')
|
68
|
+
Execution.new(connection, PlaywrightApi.wrap(playwright))
|
69
|
+
rescue
|
70
|
+
connection.stop
|
71
|
+
raise
|
72
|
+
end
|
40
73
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
74
|
+
if block
|
75
|
+
begin
|
76
|
+
block.call(execution.playwright)
|
77
|
+
ensure
|
78
|
+
execution.stop
|
79
|
+
end
|
80
|
+
else
|
81
|
+
execution
|
48
82
|
end
|
49
83
|
end
|
84
|
+
|
85
|
+
module_function def instance
|
86
|
+
@playwright_instance
|
87
|
+
end
|
50
88
|
end
|
@@ -6,7 +6,7 @@ module Playwright
|
|
6
6
|
# Accessibility is a very platform-specific thing. On different platforms, there are different screen readers that might
|
7
7
|
# have wildly different output.
|
8
8
|
#
|
9
|
-
# Rendering engines of Chromium, Firefox and
|
9
|
+
# Rendering engines of Chromium, Firefox and WebKit have a concept of "accessibility tree", which is then translated into
|
10
10
|
# different platform-specific APIs. Accessibility namespace gives access to this Accessibility Tree.
|
11
11
|
#
|
12
12
|
# Most of the accessibility tree gets filtered out when converting from internal browser AX Tree to Platform-specific
|
@@ -28,6 +28,11 @@ module Playwright
|
|
28
28
|
# console.log(snapshot);
|
29
29
|
# ```
|
30
30
|
#
|
31
|
+
# ```java
|
32
|
+
# String snapshot = page.accessibility().snapshot();
|
33
|
+
# System.out.println(snapshot);
|
34
|
+
# ```
|
35
|
+
#
|
31
36
|
# ```python async
|
32
37
|
# snapshot = await page.accessibility.snapshot()
|
33
38
|
# print(snapshot)
|
@@ -38,6 +43,11 @@ module Playwright
|
|
38
43
|
# print(snapshot)
|
39
44
|
# ```
|
40
45
|
#
|
46
|
+
# ```csharp
|
47
|
+
# var accessibilitySnapshot = await Page.Accessibility.SnapshotAsync();
|
48
|
+
# Console.WriteLine(accessibilitySnapshot);
|
49
|
+
# ```
|
50
|
+
#
|
41
51
|
# An example of logging the focused node's name:
|
42
52
|
#
|
43
53
|
#
|
@@ -57,6 +67,34 @@ module Playwright
|
|
57
67
|
# }
|
58
68
|
# ```
|
59
69
|
#
|
70
|
+
# ```csharp
|
71
|
+
# Func<AccessibilitySnapshotResult, AccessibilitySnapshotResult> findFocusedNode = root =>
|
72
|
+
# {
|
73
|
+
# var nodes = new Stack<AccessibilitySnapshotResult>(new[] { root });
|
74
|
+
# while (nodes.Count > 0)
|
75
|
+
# {
|
76
|
+
# var node = nodes.Pop();
|
77
|
+
# if (node.Focused) return node;
|
78
|
+
# foreach (var innerNode in node.Children)
|
79
|
+
# {
|
80
|
+
# nodes.Push(innerNode);
|
81
|
+
# }
|
82
|
+
# }
|
83
|
+
#
|
84
|
+
# return null;
|
85
|
+
# };
|
86
|
+
#
|
87
|
+
# var accessibilitySnapshot = await Page.Accessibility.SnapshotAsync();
|
88
|
+
# var focusedNode = findFocusedNode(accessibilitySnapshot);
|
89
|
+
# if(focusedNode != null)
|
90
|
+
# Console.WriteLine(focusedNode.Name);
|
91
|
+
# ```
|
92
|
+
#
|
93
|
+
# ```java
|
94
|
+
# // FIXME
|
95
|
+
# String snapshot = page.accessibility().snapshot();
|
96
|
+
# ```
|
97
|
+
#
|
60
98
|
# ```python async
|
61
99
|
# def find_focused_node(node):
|
62
100
|
# if (node.get("focused"))
|
@@ -3,18 +3,18 @@ module Playwright
|
|
3
3
|
#
|
4
4
|
#
|
5
5
|
# ```js
|
6
|
-
# const { _android } = require('playwright');
|
6
|
+
# const { _android: android } = require('playwright');
|
7
7
|
# ```
|
8
8
|
#
|
9
9
|
# An example of the Android automation script would be:
|
10
10
|
#
|
11
11
|
#
|
12
12
|
# ```js
|
13
|
-
# const { _android } = require('playwright');
|
13
|
+
# const { _android: android } = require('playwright');
|
14
14
|
#
|
15
15
|
# (async () => {
|
16
16
|
# // Connect to the device.
|
17
|
-
# const [device] = await
|
17
|
+
# const [device] = await android.devices();
|
18
18
|
# console.log(`Model: ${device.model()}`);
|
19
19
|
# console.log(`Serial: ${device.serial()}`);
|
20
20
|
# // Take screenshot of the whole device.
|
@@ -35,7 +35,7 @@ module Playwright
|
|
35
35
|
#
|
36
36
|
# // Work with WebView's page as usual.
|
37
37
|
# const page = await webview.page();
|
38
|
-
# await page.
|
38
|
+
# await page.waitForNavigation({ url: /.*microsoft\/playwright.*/ });
|
39
39
|
# console.log(await page.title());
|
40
40
|
# }
|
41
41
|
#
|
@@ -79,12 +79,6 @@ module Playwright
|
|
79
79
|
end
|
80
80
|
alias_method :default_timeout=, :set_default_timeout
|
81
81
|
|
82
|
-
# -- inherited from EventEmitter --
|
83
|
-
# @nodoc
|
84
|
-
def off(event, callback)
|
85
|
-
event_emitter_proxy.off(event, callback)
|
86
|
-
end
|
87
|
-
|
88
82
|
# -- inherited from EventEmitter --
|
89
83
|
# @nodoc
|
90
84
|
def once(event, callback)
|
@@ -97,6 +91,12 @@ module Playwright
|
|
97
91
|
event_emitter_proxy.on(event, callback)
|
98
92
|
end
|
99
93
|
|
94
|
+
# -- inherited from EventEmitter --
|
95
|
+
# @nodoc
|
96
|
+
def off(event, callback)
|
97
|
+
event_emitter_proxy.off(event, callback)
|
98
|
+
end
|
99
|
+
|
100
100
|
private def event_emitter_proxy
|
101
101
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
102
102
|
end
|
@@ -59,11 +59,12 @@ module Playwright
|
|
59
59
|
record_har_path: nil,
|
60
60
|
record_video_dir: nil,
|
61
61
|
record_video_size: nil,
|
62
|
+
screen: nil,
|
62
63
|
timezoneId: nil,
|
63
64
|
userAgent: nil,
|
64
65
|
viewport: nil,
|
65
66
|
&block)
|
66
|
-
wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), command: unwrap_impl(command), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
|
67
|
+
wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), command: unwrap_impl(command), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), screen: unwrap_impl(screen), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
|
67
68
|
end
|
68
69
|
|
69
70
|
# Performs a long tap on the widget defined by `selector`.
|
@@ -159,20 +160,14 @@ module Playwright
|
|
159
160
|
raise NotImplementedError.new('web_views is not implemented yet.')
|
160
161
|
end
|
161
162
|
|
162
|
-
# @nodoc
|
163
|
-
def tree
|
164
|
-
wrap_impl(@impl.tree)
|
165
|
-
end
|
166
|
-
|
167
163
|
# @nodoc
|
168
164
|
def tap_on(selector, duration: nil, timeout: nil)
|
169
165
|
wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
|
170
166
|
end
|
171
167
|
|
172
|
-
# -- inherited from EventEmitter --
|
173
168
|
# @nodoc
|
174
|
-
def
|
175
|
-
|
169
|
+
def tree
|
170
|
+
wrap_impl(@impl.tree)
|
176
171
|
end
|
177
172
|
|
178
173
|
# -- inherited from EventEmitter --
|
@@ -187,6 +182,12 @@ module Playwright
|
|
187
182
|
event_emitter_proxy.on(event, callback)
|
188
183
|
end
|
189
184
|
|
185
|
+
# -- inherited from EventEmitter --
|
186
|
+
# @nodoc
|
187
|
+
def off(event, callback)
|
188
|
+
event_emitter_proxy.off(event, callback)
|
189
|
+
end
|
190
|
+
|
190
191
|
private def event_emitter_proxy
|
191
192
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
192
193
|
end
|