playwright-ruby-client 0.7.1 → 1.14.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -0
  3. data/documentation/docs/api/accessibility.md +52 -1
  4. data/documentation/docs/api/browser.md +8 -2
  5. data/documentation/docs/api/browser_context.md +28 -0
  6. data/documentation/docs/api/browser_type.md +1 -0
  7. data/documentation/docs/api/download.md +97 -0
  8. data/documentation/docs/api/element_handle.md +38 -4
  9. data/documentation/docs/api/experimental/android_device.md +1 -0
  10. data/documentation/docs/api/frame.md +89 -17
  11. data/documentation/docs/api/keyboard.md +11 -20
  12. data/documentation/docs/api/locator.md +650 -0
  13. data/documentation/docs/api/page.md +135 -19
  14. data/documentation/docs/api/response.md +16 -0
  15. data/documentation/docs/api/touchscreen.md +8 -0
  16. data/documentation/docs/api/worker.md +37 -0
  17. data/documentation/docs/article/guides/inspector.md +31 -0
  18. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +91 -0
  19. data/documentation/docs/article/guides/semi_automation.md +5 -1
  20. data/documentation/docs/include/api_coverage.md +77 -14
  21. data/lib/playwright.rb +36 -4
  22. data/lib/playwright/accessibility_impl.rb +50 -0
  23. data/lib/playwright/channel_owners/artifact.rb +4 -0
  24. data/lib/playwright/channel_owners/browser_context.rb +77 -3
  25. data/lib/playwright/channel_owners/element_handle.rb +11 -4
  26. data/lib/playwright/channel_owners/frame.rb +107 -34
  27. data/lib/playwright/channel_owners/page.rb +163 -55
  28. data/lib/playwright/channel_owners/response.rb +8 -0
  29. data/lib/playwright/channel_owners/worker.rb +23 -0
  30. data/lib/playwright/connection.rb +2 -4
  31. data/lib/playwright/{download.rb → download_impl.rb} +5 -1
  32. data/lib/playwright/javascript/expression.rb +5 -4
  33. data/lib/playwright/locator_impl.rb +314 -0
  34. data/lib/playwright/route_handler_entry.rb +3 -2
  35. data/lib/playwright/timeout_settings.rb +4 -4
  36. data/lib/playwright/touchscreen_impl.rb +7 -0
  37. data/lib/playwright/transport.rb +0 -1
  38. data/lib/playwright/url_matcher.rb +12 -2
  39. data/lib/playwright/version.rb +2 -2
  40. data/lib/playwright/web_socket_client.rb +164 -0
  41. data/lib/playwright/web_socket_transport.rb +104 -0
  42. data/lib/playwright_api/accessibility.rb +1 -1
  43. data/lib/playwright_api/android_device.rb +6 -5
  44. data/lib/playwright_api/browser.rb +10 -4
  45. data/lib/playwright_api/browser_context.rb +12 -7
  46. data/lib/playwright_api/browser_type.rb +2 -1
  47. data/lib/playwright_api/cdp_session.rb +6 -6
  48. data/lib/playwright_api/download.rb +70 -0
  49. data/lib/playwright_api/element_handle.rb +38 -18
  50. data/lib/playwright_api/frame.rb +95 -44
  51. data/lib/playwright_api/locator.rb +509 -0
  52. data/lib/playwright_api/page.rb +102 -49
  53. data/lib/playwright_api/response.rb +10 -0
  54. data/lib/playwright_api/touchscreen.rb +1 -1
  55. data/lib/playwright_api/worker.rb +13 -3
  56. metadata +17 -7
@@ -8,7 +8,6 @@ module Playwright
8
8
  # ref: https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_transport.py
9
9
  class Transport
10
10
  # @param playwright_cli_executable_path [String] path to playwright-cli.
11
- # @param debug [Boolean]
12
11
  def initialize(playwright_cli_executable_path:)
13
12
  @driver_executable_path = playwright_cli_executable_path
14
13
  @debug = ENV['DEBUG'].to_s == 'true' || ENV['DEBUG'].to_s == '1'
@@ -1,19 +1,29 @@
1
1
  module Playwright
2
2
  class UrlMatcher
3
3
  # @param url [String|Regexp]
4
- def initialize(url)
4
+ # @param base_url [String|nil]
5
+ def initialize(url, base_url:)
5
6
  @url = url
7
+ @base_url = base_url
6
8
  end
7
9
 
8
10
  def match?(target_url)
9
11
  case @url
10
12
  when String
11
- @url == target_url || File.fnmatch?(@url, target_url)
13
+ joined_url == target_url || File.fnmatch?(@url, target_url)
12
14
  when Regexp
13
15
  @url.match?(target_url)
14
16
  else
15
17
  false
16
18
  end
17
19
  end
20
+
21
+ private def joined_url
22
+ if @base_url && !@url.start_with?('*')
23
+ URI.join(@base_url, @url).to_s
24
+ else
25
+ @url
26
+ end
27
+ end
18
28
  end
19
29
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '0.7.1'
5
- COMPATIBLE_PLAYWRIGHT_VERSION = '1.12.0'
4
+ VERSION = '1.14.beta1'
5
+ COMPATIBLE_PLAYWRIGHT_VERSION = '1.14.0'
6
6
  end
@@ -0,0 +1,164 @@
1
+ require 'openssl'
2
+ require 'socket'
3
+
4
+ begin
5
+ require 'websocket/driver'
6
+ rescue LoadError
7
+ raise "websocket-driver is required. Add `gem 'websocket-driver'` to your Gemfile"
8
+ end
9
+
10
+ # ref: https://github.com/rails/rails/blob/master/actioncable/lib/action_cable/connection/client_socket.rb
11
+ # ref: https://github.com/cavalle/chrome_remote/blob/master/lib/chrome_remote/web_socket_client.rb
12
+ module Playwright
13
+ class WebSocketClient
14
+ class SecureSocketFactory
15
+ def initialize(host, port)
16
+ @host = host
17
+ @port = port || 443
18
+ end
19
+
20
+ def create
21
+ tcp_socket = TCPSocket.new(@host, @port)
22
+ OpenSSL::SSL::SSLSocket.new(tcp_socket).tap(&:connect)
23
+ end
24
+ end
25
+
26
+ class DriverImpl # providing #url, #write(string)
27
+ def initialize(url)
28
+ @url = url
29
+
30
+ endpoint = URI.parse(url)
31
+ @socket =
32
+ if endpoint.scheme == 'wss'
33
+ SecureSocketFactory.new(endpoint.host, endpoint.port).create
34
+ else
35
+ TCPSocket.new(endpoint.host, endpoint.port)
36
+ end
37
+ end
38
+
39
+ attr_reader :url
40
+
41
+ def write(data)
42
+ @socket.write(data)
43
+ rescue Errno::EPIPE
44
+ raise EOFError.new('already closed')
45
+ rescue Errno::ECONNRESET
46
+ raise EOFError.new('closed by remote')
47
+ end
48
+
49
+ def readpartial(maxlen = 1024)
50
+ @socket.readpartial(maxlen)
51
+ rescue Errno::ECONNRESET
52
+ raise EOFError.new('closed by remote')
53
+ end
54
+
55
+ def disconnect
56
+ @socket.close
57
+ end
58
+ end
59
+
60
+ STATE_CONNECTING = 0
61
+ STATE_OPENED = 1
62
+ STATE_CLOSING = 2
63
+ STATE_CLOSED = 3
64
+
65
+ def initialize(url:, max_payload_size:)
66
+ @impl = DriverImpl.new(url)
67
+ @driver = ::WebSocket::Driver.client(@impl, max_length: max_payload_size)
68
+
69
+ setup
70
+ end
71
+
72
+ class TransportError < StandardError; end
73
+
74
+ private def setup
75
+ @ready_state = STATE_CONNECTING
76
+ @driver.on(:open) do
77
+ @ready_state = STATE_OPENED
78
+ handle_on_open
79
+ end
80
+ @driver.on(:close) do |event|
81
+ @ready_state = STATE_CLOSED
82
+ handle_on_close(reason: event.reason, code: event.code)
83
+ end
84
+ @driver.on(:error) do |event|
85
+ if !handle_on_error(error_message: event.message)
86
+ raise TransportError.new(event.message)
87
+ end
88
+ end
89
+ @driver.on(:message) do |event|
90
+ handle_on_message(event.data)
91
+ end
92
+ end
93
+
94
+ private def wait_for_data
95
+ @driver.parse(@impl.readpartial)
96
+ end
97
+
98
+ def start
99
+ @driver.start
100
+
101
+ Thread.new do
102
+ wait_for_data until @ready_state >= STATE_CLOSING
103
+ rescue EOFError
104
+ # Google Chrome was gone.
105
+ # We have nothing todo. Just finish polling.
106
+ if @ready_state < STATE_CLOSING
107
+ handle_on_close(reason: 'Going Away', code: 1001)
108
+ end
109
+ end
110
+ end
111
+
112
+ # @param message [String]
113
+ def send_text(message)
114
+ return if @ready_state >= STATE_CLOSING
115
+ @driver.text(message)
116
+ end
117
+
118
+ def close(code: 1000, reason: "")
119
+ return if @ready_state >= STATE_CLOSING
120
+ @ready_state = STATE_CLOSING
121
+ @driver.close(reason, code)
122
+ end
123
+
124
+ def on_open(&block)
125
+ @on_open = block
126
+ end
127
+
128
+ # @param block [Proc(reason: String, code: Numeric)]
129
+ def on_close(&block)
130
+ @on_close = block
131
+ end
132
+
133
+ # @param block [Proc(error_message: String)]
134
+ def on_error(&block)
135
+ @on_error = block
136
+ end
137
+
138
+ def on_message(&block)
139
+ @on_message = block
140
+ end
141
+
142
+ private def handle_on_open
143
+ @on_open&.call
144
+ end
145
+
146
+ private def handle_on_close(reason:, code:)
147
+ @on_close&.call(reason, code)
148
+ @impl.disconnect
149
+ end
150
+
151
+ private def handle_on_error(error_message:)
152
+ return false if @on_error.nil?
153
+
154
+ @on_error.call(error_message)
155
+ true
156
+ end
157
+
158
+ private def handle_on_message(data)
159
+ return if @ready_state != STATE_OPENED
160
+
161
+ @on_message&.call(data)
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Playwright
6
+ # ref: https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_transport.py
7
+ class WebSocketTransport
8
+ # @param ws_endpoint [String] EndpointURL of WebSocket
9
+ def initialize(ws_endpoint:)
10
+ @ws_endpoint = ws_endpoint
11
+ @debug = ENV['DEBUG'].to_s == 'true' || ENV['DEBUG'].to_s == '1'
12
+ end
13
+
14
+ def on_message_received(&block)
15
+ @on_message = block
16
+ end
17
+
18
+ def on_driver_crashed(&block)
19
+ @on_driver_crashed = block
20
+ end
21
+
22
+ class AlreadyDisconnectedError < StandardError ; end
23
+
24
+ # @param message [Hash]
25
+ def send_message(message)
26
+ debug_send_message(message) if @debug
27
+ msg = JSON.dump(message)
28
+
29
+ @ws.send_text(msg)
30
+ rescue Errno::EPIPE, IOError
31
+ raise AlreadyDisconnectedError.new('send_message failed')
32
+ end
33
+
34
+ # Terminate playwright-cli driver.
35
+ def stop
36
+ return unless @ws
37
+
38
+ future = Concurrent::Promises.resolvable_future
39
+
40
+ @ws.on_close do
41
+ future.fulfill(nil)
42
+ end
43
+
44
+ begin
45
+ @ws.close
46
+ rescue EOFError => err
47
+ # ignore EOLError. The connection is already closed.
48
+ future.fulfill(err)
49
+ end
50
+
51
+ # Wait for closed actually.
52
+ future.value!
53
+ end
54
+
55
+ # Start `playwright-cli run-driver`
56
+ #
57
+ # @note This method blocks until playwright-cli exited. Consider using Thread or Future.
58
+ def async_run
59
+ ws = WebSocketClient.new(
60
+ url: @ws_endpoint,
61
+ max_payload_size: 256 * 1024 * 1024, # 256MB
62
+ )
63
+ promise = Concurrent::Promises.resolvable_future
64
+ ws.on_open do
65
+ promise.fulfill(ws)
66
+ end
67
+ ws.on_error do |error_message|
68
+ promise.reject(WebSocketClient::TransportError.new(error_message))
69
+ end
70
+
71
+ # Some messages can be sent just after start, before setting @ws.on_message
72
+ # So set this handler before ws.start.
73
+ ws.on_message do |data|
74
+ handle_on_message(data)
75
+ end
76
+
77
+ ws.start
78
+ @ws = promise.value!
79
+ @ws.on_error do |error|
80
+ puts "[WebSocketTransport] error: #{error}"
81
+ @on_driver_crashed&.call
82
+ end
83
+ rescue Errno::ECONNREFUSED => err
84
+ raise WebSocketClient::TransportError.new(err)
85
+ end
86
+
87
+ private
88
+
89
+ def handle_on_message(data)
90
+ obj = JSON.parse(data)
91
+
92
+ debug_recv_message(obj) if @debug
93
+ @on_message&.call(obj)
94
+ end
95
+
96
+ def debug_send_message(message)
97
+ puts "\x1b[33mSEND>\x1b[0m#{message}"
98
+ end
99
+
100
+ def debug_recv_message(message)
101
+ puts "\x1b[33mRECV>\x1b[0m#{message}"
102
+ end
103
+ end
104
+ end
@@ -44,7 +44,7 @@ module Playwright
44
44
  # print(node["name"])
45
45
  # ```
46
46
  def snapshot(interestingOnly: nil, root: nil)
47
- raise NotImplementedError.new('snapshot is not implemented yet.')
47
+ wrap_impl(@impl.snapshot(interestingOnly: unwrap_impl(interestingOnly), root: unwrap_impl(root)))
48
48
  end
49
49
  end
50
50
  end
@@ -40,6 +40,7 @@ module Playwright
40
40
  # Launches Chrome browser on the device, and returns its persistent context.
41
41
  def launch_browser(
42
42
  acceptDownloads: nil,
43
+ baseURL: nil,
43
44
  bypassCSP: nil,
44
45
  colorScheme: nil,
45
46
  command: nil,
@@ -65,7 +66,7 @@ module Playwright
65
66
  userAgent: nil,
66
67
  viewport: nil,
67
68
  &block)
68
- 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), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
69
+ wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), 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), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
69
70
  end
70
71
 
71
72
  # Performs a long tap on the widget defined by `selector`.
@@ -162,13 +163,13 @@ module Playwright
162
163
  end
163
164
 
164
165
  # @nodoc
165
- def tree
166
- wrap_impl(@impl.tree)
166
+ def tap_on(selector, duration: nil, timeout: nil)
167
+ wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
167
168
  end
168
169
 
169
170
  # @nodoc
170
- def tap_on(selector, duration: nil, timeout: nil)
171
- wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
171
+ def tree
172
+ wrap_impl(@impl.tree)
172
173
  end
173
174
 
174
175
  # -- inherited from EventEmitter --
@@ -65,6 +65,7 @@ module Playwright
65
65
  # ```
66
66
  def new_context(
67
67
  acceptDownloads: nil,
68
+ baseURL: nil,
68
69
  bypassCSP: nil,
69
70
  colorScheme: nil,
70
71
  deviceScaleFactor: nil,
@@ -91,7 +92,7 @@ module Playwright
91
92
  userAgent: nil,
92
93
  viewport: nil,
93
94
  &block)
94
- wrap_impl(@impl.new_context(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), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
95
+ wrap_impl(@impl.new_context(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), 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), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
95
96
  end
96
97
 
97
98
  # Creates a new page in a new browser context. Closing this page will close the context as well.
@@ -101,6 +102,7 @@ module Playwright
101
102
  # [`method: BrowserContext.newPage`] to control their exact life times.
102
103
  def new_page(
103
104
  acceptDownloads: nil,
105
+ baseURL: nil,
104
106
  bypassCSP: nil,
105
107
  colorScheme: nil,
106
108
  deviceScaleFactor: nil,
@@ -127,10 +129,12 @@ module Playwright
127
129
  userAgent: nil,
128
130
  viewport: nil,
129
131
  &block)
130
- wrap_impl(@impl.new_page(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), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
132
+ wrap_impl(@impl.new_page(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), 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), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
131
133
  end
132
134
 
133
- # > NOTE: Tracing is only supported on Chromium-based browsers.
135
+ # > NOTE: This API controls [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool)
136
+ # which is a low-level chromium-specific debugging tool. API to control [Playwright Tracing](../trace-viewer) could be
137
+ # found [here](./class-tracing).
134
138
  #
135
139
  # You can use [`method: Browser.startTracing`] and [`method: Browser.stopTracing`] to create a trace file that can be
136
140
  # opened in Chrome DevTools performance panel.
@@ -144,7 +148,9 @@ module Playwright
144
148
  wrap_impl(@impl.start_tracing(page: unwrap_impl(page), categories: unwrap_impl(categories), path: unwrap_impl(path), screenshots: unwrap_impl(screenshots)))
145
149
  end
146
150
 
147
- # > NOTE: Tracing is only supported on Chromium-based browsers.
151
+ # > NOTE: This API controls [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool)
152
+ # which is a low-level chromium-specific debugging tool. API to control [Playwright Tracing](../trace-viewer) could be
153
+ # found [here](./class-tracing).
148
154
  #
149
155
  # Returns the buffer with trace data.
150
156
  def stop_tracing
@@ -59,7 +59,7 @@ module Playwright
59
59
  #
60
60
  # All existing background pages in the context.
61
61
  def background_pages
62
- raise NotImplementedError.new('background_pages is not implemented yet.')
62
+ wrap_impl(@impl.background_pages)
63
63
  end
64
64
 
65
65
  # Returns the browser instance of the context. If it was launched as a persistent context null gets returned.
@@ -268,7 +268,7 @@ module Playwright
268
268
  #
269
269
  # All existing service workers in the context.
270
270
  def service_workers
271
- raise NotImplementedError.new('service_workers is not implemented yet.')
271
+ wrap_impl(@impl.service_workers)
272
272
  end
273
273
 
274
274
  # This setting will change the default maximum navigation time for the following methods and related shortcuts:
@@ -325,7 +325,7 @@ module Playwright
325
325
 
326
326
  # Returns storage state for this browser context, contains current cookies and local storage snapshot.
327
327
  def storage_state(path: nil)
328
- raise NotImplementedError.new('storage_state is not implemented yet.')
328
+ wrap_impl(@impl.storage_state(path: unwrap_impl(path)))
329
329
  end
330
330
 
331
331
  # Removes a route created with [`method: BrowserContext.route`]. When `handler` is not specified, removes all routes for
@@ -362,6 +362,11 @@ module Playwright
362
362
  raise NotImplementedError.new('wait_for_event is not implemented yet.')
363
363
  end
364
364
 
365
+ # @nodoc
366
+ def enable_debug_console!
367
+ wrap_impl(@impl.enable_debug_console!)
368
+ end
369
+
365
370
  # @nodoc
366
371
  def browser=(req)
367
372
  wrap_impl(@impl.browser=(unwrap_impl(req)))
@@ -373,13 +378,13 @@ module Playwright
373
378
  end
374
379
 
375
380
  # @nodoc
376
- def options=(req)
377
- wrap_impl(@impl.options=(unwrap_impl(req)))
381
+ def pause
382
+ wrap_impl(@impl.pause)
378
383
  end
379
384
 
380
385
  # @nodoc
381
- def pause
382
- wrap_impl(@impl.pause)
386
+ def options=(req)
387
+ wrap_impl(@impl.options=(unwrap_impl(req)))
383
388
  end
384
389
 
385
390
  # -- inherited from EventEmitter --