playwright-ruby-client 0.2.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -5
  3. data/docs/api_coverage.md +116 -74
  4. data/lib/playwright.rb +48 -9
  5. data/lib/playwright/channel.rb +12 -2
  6. data/lib/playwright/channel_owners/artifact.rb +30 -0
  7. data/lib/playwright/channel_owners/binding_call.rb +3 -0
  8. data/lib/playwright/channel_owners/browser.rb +21 -0
  9. data/lib/playwright/channel_owners/browser_context.rb +154 -3
  10. data/lib/playwright/channel_owners/browser_type.rb +28 -0
  11. data/lib/playwright/channel_owners/dialog.rb +28 -0
  12. data/lib/playwright/channel_owners/element_handle.rb +1 -1
  13. data/lib/playwright/channel_owners/frame.rb +25 -2
  14. data/lib/playwright/channel_owners/js_handle.rb +2 -2
  15. data/lib/playwright/channel_owners/page.rb +141 -25
  16. data/lib/playwright/channel_owners/playwright.rb +24 -27
  17. data/lib/playwright/channel_owners/request.rb +26 -2
  18. data/lib/playwright/channel_owners/response.rb +60 -0
  19. data/lib/playwright/channel_owners/route.rb +78 -0
  20. data/lib/playwright/channel_owners/selectors.rb +19 -1
  21. data/lib/playwright/channel_owners/stream.rb +15 -0
  22. data/lib/playwright/connection.rb +11 -32
  23. data/lib/playwright/download.rb +27 -0
  24. data/lib/playwright/errors.rb +6 -0
  25. data/lib/playwright/events.rb +2 -5
  26. data/lib/playwright/keyboard_impl.rb +1 -1
  27. data/lib/playwright/mouse_impl.rb +41 -0
  28. data/lib/playwright/route_handler_entry.rb +28 -0
  29. data/lib/playwright/transport.rb +27 -6
  30. data/lib/playwright/url_matcher.rb +1 -1
  31. data/lib/playwright/utils.rb +9 -0
  32. data/lib/playwright/version.rb +1 -1
  33. data/lib/playwright/video.rb +51 -0
  34. data/lib/playwright/wait_helper.rb +2 -2
  35. data/lib/playwright_api/accessibility.rb +39 -1
  36. data/lib/playwright_api/android.rb +74 -2
  37. data/lib/playwright_api/android_device.rb +141 -23
  38. data/lib/playwright_api/android_input.rb +17 -13
  39. data/lib/playwright_api/android_socket.rb +16 -0
  40. data/lib/playwright_api/android_web_view.rb +21 -0
  41. data/lib/playwright_api/browser.rb +77 -2
  42. data/lib/playwright_api/browser_context.rb +182 -29
  43. data/lib/playwright_api/browser_type.rb +40 -9
  44. data/lib/playwright_api/dialog.rb +54 -7
  45. data/lib/playwright_api/element_handle.rb +105 -31
  46. data/lib/playwright_api/file_chooser.rb +6 -1
  47. data/lib/playwright_api/frame.rb +229 -36
  48. data/lib/playwright_api/js_handle.rb +23 -0
  49. data/lib/playwright_api/keyboard.rb +48 -1
  50. data/lib/playwright_api/mouse.rb +26 -5
  51. data/lib/playwright_api/page.rb +491 -81
  52. data/lib/playwright_api/playwright.rb +21 -4
  53. data/lib/playwright_api/request.rb +30 -2
  54. data/lib/playwright_api/response.rb +21 -11
  55. data/lib/playwright_api/route.rb +51 -5
  56. data/lib/playwright_api/selectors.rb +27 -1
  57. data/lib/playwright_api/touchscreen.rb +1 -1
  58. data/lib/playwright_api/worker.rb +25 -1
  59. data/playwright.gemspec +4 -2
  60. metadata +42 -14
  61. data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
  62. data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
  63. data/lib/playwright/channel_owners/download.rb +0 -27
  64. data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
  65. data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
  66. data/lib/playwright_api/binding_call.rb +0 -27
  67. data/lib/playwright_api/chromium_browser_context.rb +0 -59
  68. data/lib/playwright_api/download.rb +0 -95
  69. data/lib/playwright_api/video.rb +0 -24
@@ -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
@@ -0,0 +1,28 @@
1
+ module Playwright
2
+ class RouteHandlerEntry
3
+ # @param url [String]
4
+ # @param handler [Proc]
5
+ def initialize(url, handler)
6
+ @url_value = url
7
+ @url_matcher = UrlMatcher.new(url)
8
+ @handler = handler
9
+ end
10
+
11
+ def handle(route, request)
12
+ if @url_matcher.match?(request.url)
13
+ @handler.call(route, request)
14
+ true
15
+ else
16
+ false
17
+ end
18
+ end
19
+
20
+ def same_value?(url:, handler: nil)
21
+ if handler
22
+ @url_value == url && @handler == handler
23
+ else
24
+ @url_value == url
25
+ end
26
+ end
27
+ end
28
+ end
@@ -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
- @stdin.write([msg.size].pack('V')) # unsigned 32bit, little endian
28
- @stdin.write(msg)
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 run
42
- @stdin, @stdout, @stderr, @thread = Open3.popen3(@driver_executable_path, 'run-driver')
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
@@ -8,7 +8,7 @@ module Playwright
8
8
  def match?(target_url)
9
9
  case @url
10
10
  when String
11
- @url == target_url
11
+ @url == target_url || File.fnmatch?(@url, target_url)
12
12
  when Regexp
13
13
  @url.match?(target_url)
14
14
  else
@@ -3,6 +3,7 @@ module Playwright
3
3
  module PrepareBrowserContextOptions
4
4
  # @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
5
5
  private def prepare_browser_context_options(params)
6
+ params[:sdkLanguage] = 'ruby'
6
7
  if params[:noViewport] == 0
7
8
  params.delete(:noViewport)
8
9
  params[:noDefaultViewport] = true
@@ -10,6 +11,14 @@ module Playwright
10
11
  if params[:extraHTTPHeaders]
11
12
  params[:extraHTTPHeaders] = ::Playwright::HttpHeaders.new(params[:extraHTTPHeaders]).as_serialized
12
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
13
22
  if params[:storageState].is_a?(String)
14
23
  params[:storageState] = JSON.parse(File.read(params[:storageState]))
15
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '0.2.0'
4
+ VERSION = '0.5.2'
5
5
  end
@@ -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
@@ -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 Webkit have a concept of "accessibility tree", which is then translated into
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"))
@@ -1,12 +1,84 @@
1
1
  module Playwright
2
- # @nodoc
2
+ # Playwright has **experimental** support for Android automation. You can access android namespace via:
3
+ #
4
+ #
5
+ # ```js
6
+ # const { _android: android } = require('playwright');
7
+ # ```
8
+ #
9
+ # An example of the Android automation script would be:
10
+ #
11
+ #
12
+ # ```js
13
+ # const { _android: android } = require('playwright');
14
+ #
15
+ # (async () => {
16
+ # // Connect to the device.
17
+ # const [device] = await android.devices();
18
+ # console.log(`Model: ${device.model()}`);
19
+ # console.log(`Serial: ${device.serial()}`);
20
+ # // Take screenshot of the whole device.
21
+ # await device.screenshot({ path: 'device.png' });
22
+ #
23
+ # {
24
+ # // --------------------- WebView -----------------------
25
+ #
26
+ # // Launch an application with WebView.
27
+ # await device.shell('am force-stop org.chromium.webview_shell');
28
+ # await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
29
+ # // Get the WebView.
30
+ # const webview = await device.webView({ pkg: 'org.chromium.webview_shell' });
31
+ #
32
+ # // Fill the input box.
33
+ # await device.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'github.com/microsoft/playwright');
34
+ # await device.press({ res: 'org.chromium.webview_shell:id/url_field' }, 'Enter');
35
+ #
36
+ # // Work with WebView's page as usual.
37
+ # const page = await webview.page();
38
+ # await page.waitForNavigation({ url: /.*microsoft\/playwright.*/ });
39
+ # console.log(await page.title());
40
+ # }
41
+ #
42
+ # {
43
+ # // --------------------- Browser -----------------------
44
+ #
45
+ # // Launch Chrome browser.
46
+ # await device.shell('am force-stop com.android.chrome');
47
+ # const context = await device.launchBrowser();
48
+ #
49
+ # // Use BrowserContext as usual.
50
+ # const page = await context.newPage();
51
+ # await page.goto('https://webkit.org/');
52
+ # console.log(await page.evaluate(() => window.location.href));
53
+ # await page.screenshot({ path: 'page.png' });
54
+ #
55
+ # await context.close();
56
+ # }
57
+ #
58
+ # // Close the device.
59
+ # await device.close();
60
+ # })();
61
+ # ```
62
+ #
63
+ # Note that since you don't need Playwright to install web browsers when testing Android, you can omit browser download
64
+ # via setting the following environment variable when installing Playwright:
65
+ #
66
+ # ```sh js
67
+ # $ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm i -D playwright
68
+ # ```
3
69
  class Android < PlaywrightApi
4
70
 
5
- # @nodoc
71
+ # Returns the list of detected Android devices.
6
72
  def devices
7
73
  wrap_impl(@impl.devices)
8
74
  end
9
75
 
76
+ # This setting will change the default maximum time for all the methods accepting `timeout` option.
77
+ def set_default_timeout(timeout)
78
+ raise NotImplementedError.new('set_default_timeout is not implemented yet.')
79
+ end
80
+ alias_method :default_timeout=, :set_default_timeout
81
+
10
82
  # -- inherited from EventEmitter --
11
83
  # @nodoc
12
84
  def once(event, callback)
@@ -1,55 +1,173 @@
1
1
  module Playwright
2
- # @nodoc
2
+ # `AndroidDevice` represents a connected device, either real hardware or emulated. Devices can be obtained using
3
+ # [`method: Android.devices`].
3
4
  class AndroidDevice < PlaywrightApi
4
5
 
5
- # @nodoc
6
- def tree
7
- wrap_impl(@impl.tree)
6
+ def input # property
7
+ wrap_impl(@impl.input)
8
8
  end
9
9
 
10
- # @nodoc
10
+ # Disconnects from the device.
11
11
  def close
12
12
  wrap_impl(@impl.close)
13
13
  end
14
14
 
15
- # @nodoc
16
- def tap_on(selector, duration: nil, timeout: nil)
17
- wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
15
+ # Drags the widget defined by `selector` towards `dest` point.
16
+ def drag(selector, dest, speed: nil)
17
+ raise NotImplementedError.new('drag is not implemented yet.')
18
18
  end
19
19
 
20
- # @nodoc
20
+ # Fills the specific `selector` input box with `text`.
21
+ def fill(selector, text)
22
+ raise NotImplementedError.new('fill is not implemented yet.')
23
+ end
24
+
25
+ # Flings the widget defined by `selector` in the specified `direction`.
26
+ def fling(selector, direction, speed: nil)
27
+ raise NotImplementedError.new('fling is not implemented yet.')
28
+ end
29
+
30
+ # Returns information about a widget defined by `selector`.
31
+ def info(selector)
32
+ wrap_impl(@impl.info(unwrap_impl(selector)))
33
+ end
34
+
35
+ # Installs an apk on the device.
36
+ def install_apk(file, args: nil)
37
+ raise NotImplementedError.new('install_apk is not implemented yet.')
38
+ end
39
+
40
+ # Launches Chrome browser on the device, and returns its persistent context.
41
+ def launch_browser(
42
+ acceptDownloads: nil,
43
+ bypassCSP: nil,
44
+ colorScheme: nil,
45
+ command: nil,
46
+ deviceScaleFactor: nil,
47
+ extraHTTPHeaders: nil,
48
+ geolocation: nil,
49
+ hasTouch: nil,
50
+ httpCredentials: nil,
51
+ ignoreHTTPSErrors: nil,
52
+ isMobile: nil,
53
+ javaScriptEnabled: nil,
54
+ locale: nil,
55
+ noViewport: nil,
56
+ offline: nil,
57
+ permissions: nil,
58
+ record_har_omit_content: nil,
59
+ record_har_path: nil,
60
+ record_video_dir: nil,
61
+ record_video_size: nil,
62
+ screen: nil,
63
+ timezoneId: nil,
64
+ userAgent: nil,
65
+ viewport: nil,
66
+ &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)))
68
+ end
69
+
70
+ # Performs a long tap on the widget defined by `selector`.
71
+ def long_tap(selector)
72
+ raise NotImplementedError.new('long_tap is not implemented yet.')
73
+ end
74
+
75
+ # Device model.
76
+ def model
77
+ wrap_impl(@impl.model)
78
+ end
79
+
80
+ # Launches a process in the shell on the device and returns a socket to communicate with the launched process.
81
+ def open(command)
82
+ raise NotImplementedError.new('open is not implemented yet.')
83
+ end
84
+
85
+ # Pinches the widget defined by `selector` in the closing direction.
86
+ def pinch_close(selector, percent, speed: nil)
87
+ raise NotImplementedError.new('pinch_close is not implemented yet.')
88
+ end
89
+
90
+ # Pinches the widget defined by `selector` in the open direction.
91
+ def pinch_open(selector, percent, speed: nil)
92
+ raise NotImplementedError.new('pinch_open is not implemented yet.')
93
+ end
94
+
95
+ # Presses the specific `key` in the widget defined by `selector`.
96
+ def press(selector, key)
97
+ raise NotImplementedError.new('press is not implemented yet.')
98
+ end
99
+
100
+ # Copies a file to the device.
101
+ def push(file, path, mode: nil)
102
+ raise NotImplementedError.new('push is not implemented yet.')
103
+ end
104
+
105
+ # Returns the buffer with the captured screenshot of the device.
21
106
  def screenshot(path: nil)
22
107
  wrap_impl(@impl.screenshot(path: unwrap_impl(path)))
23
108
  end
24
109
 
25
- # @nodoc
110
+ # Scrolls the widget defined by `selector` in the specified `direction`.
111
+ def scroll(selector, direction, percent, speed: nil)
112
+ raise NotImplementedError.new('scroll is not implemented yet.')
113
+ end
114
+
115
+ # Device serial number.
116
+ def serial
117
+ wrap_impl(@impl.serial)
118
+ end
119
+
120
+ # This setting will change the default maximum time for all the methods accepting `timeout` option.
121
+ def set_default_timeout(timeout)
122
+ raise NotImplementedError.new('set_default_timeout is not implemented yet.')
123
+ end
124
+ alias_method :default_timeout=, :set_default_timeout
125
+
126
+ # Executes a shell command on the device and returns its output.
26
127
  def shell(command)
27
128
  wrap_impl(@impl.shell(unwrap_impl(command)))
28
129
  end
29
130
 
30
- # @nodoc
31
- def input
32
- wrap_impl(@impl.input)
131
+ # Swipes the widget defined by `selector` in the specified `direction`.
132
+ def swipe(selector, direction, percent, speed: nil)
133
+ raise NotImplementedError.new('swipe is not implemented yet.')
33
134
  end
34
135
 
35
- # @nodoc
36
- def launch_browser(pkg: nil, acceptDownloads: nil, bypassCSP: nil, colorScheme: nil, deviceScaleFactor: nil, extraHTTPHeaders: nil, geolocation: nil, hasTouch: nil, httpCredentials: nil, ignoreHTTPSErrors: nil, isMobile: nil, javaScriptEnabled: nil, locale: nil, noViewport: nil, offline: nil, permissions: nil, proxy: nil, record_har_omit_content: nil, record_har_path: nil, record_video_dir: nil, record_video_size: nil, storageState: nil, timezoneId: nil, userAgent: nil, viewport: nil, &block)
37
- wrap_impl(@impl.launch_browser(pkg: unwrap_impl(pkg), acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), 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), proxy: unwrap_impl(proxy), 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), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
136
+ # Taps on the widget defined by `selector`.
137
+ def tap_point(selector, duration: nil)
138
+ raise NotImplementedError.new('tap_point is not implemented yet.')
38
139
  end
39
140
 
40
- # @nodoc
41
- def info(selector)
42
- wrap_impl(@impl.info(unwrap_impl(selector)))
141
+ # Waits for the specific `selector` to either appear or disappear, depending on the `state`.
142
+ def wait(selector, state: nil)
143
+ raise NotImplementedError.new('wait is not implemented yet.')
144
+ end
145
+
146
+ # Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
147
+ # value.
148
+ def wait_for_event(event, optionsOrPredicate: nil)
149
+ raise NotImplementedError.new('wait_for_event is not implemented yet.')
150
+ end
151
+
152
+ # This method waits until `AndroidWebView` matching the `selector` is opened and returns it. If there is already an open
153
+ # `AndroidWebView` matching the `selector`, returns immediately.
154
+ def web_view(selector)
155
+ raise NotImplementedError.new('web_view is not implemented yet.')
156
+ end
157
+
158
+ # Currently open WebViews.
159
+ def web_views
160
+ raise NotImplementedError.new('web_views is not implemented yet.')
43
161
  end
44
162
 
45
163
  # @nodoc
46
- def serial
47
- wrap_impl(@impl.serial)
164
+ def tap_on(selector, duration: nil, timeout: nil)
165
+ wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
48
166
  end
49
167
 
50
168
  # @nodoc
51
- def model
52
- wrap_impl(@impl.model)
169
+ def tree
170
+ wrap_impl(@impl.tree)
53
171
  end
54
172
 
55
173
  # -- inherited from EventEmitter --