playwright-ruby-client 0.3.0 → 0.5.2
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/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
|