playwright-ruby-client 0.6.2 → 0.7.0

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/browser.md +2 -1
  3. data/documentation/docs/api/browser_context.md +1 -1
  4. data/documentation/docs/api/browser_type.md +54 -1
  5. data/documentation/docs/api/experimental/android.md +3 -2
  6. data/documentation/docs/api/page.md +8 -0
  7. data/documentation/docs/api/route.md +20 -21
  8. data/documentation/docs/api/tracing.md +8 -15
  9. data/documentation/docs/api/web_socket.md +38 -1
  10. data/documentation/docs/article/guides/launch_browser.md +2 -0
  11. data/documentation/docs/article/guides/rails_integration.md +156 -2
  12. data/documentation/docs/article/guides/recording_video.md +79 -0
  13. data/documentation/docs/article/guides/semi_automation.md +67 -0
  14. data/documentation/docs/include/api_coverage.md +7 -8
  15. data/documentation/package.json +1 -1
  16. data/documentation/yarn.lock +478 -498
  17. data/lib/playwright/channel_owners/browser.rb +15 -27
  18. data/lib/playwright/channel_owners/browser_context.rb +13 -5
  19. data/lib/playwright/channel_owners/browser_type.rb +23 -8
  20. data/lib/playwright/channel_owners/page.rb +6 -1
  21. data/lib/playwright/channel_owners/web_socket.rb +87 -0
  22. data/lib/playwright/tracing_impl.rb +9 -9
  23. data/lib/playwright/version.rb +1 -1
  24. data/lib/playwright_api/android.rb +9 -8
  25. data/lib/playwright_api/android_device.rb +6 -6
  26. data/lib/playwright_api/browser.rb +9 -8
  27. data/lib/playwright_api/browser_context.rb +8 -8
  28. data/lib/playwright_api/browser_type.rb +12 -11
  29. data/lib/playwright_api/console_message.rb +6 -6
  30. data/lib/playwright_api/dialog.rb +6 -6
  31. data/lib/playwright_api/element_handle.rb +6 -6
  32. data/lib/playwright_api/frame.rb +6 -6
  33. data/lib/playwright_api/js_handle.rb +6 -6
  34. data/lib/playwright_api/page.rb +14 -14
  35. data/lib/playwright_api/playwright.rb +6 -6
  36. data/lib/playwright_api/request.rb +6 -6
  37. data/lib/playwright_api/response.rb +6 -6
  38. data/lib/playwright_api/route.rb +6 -6
  39. data/lib/playwright_api/selectors.rb +6 -6
  40. data/lib/playwright_api/tracing.rb +6 -12
  41. data/lib/playwright_api/web_socket.rb +28 -6
  42. data/lib/playwright_api/worker.rb +6 -6
  43. data/playwright.gemspec +2 -1
  44. metadata +33 -16
@@ -7,7 +7,7 @@ module Playwright
7
7
  private def after_initialize
8
8
  @connected = true
9
9
  @closed_or_closing = false
10
- @remote = true
10
+ @remote = false
11
11
 
12
12
  @contexts = Set.new
13
13
  @channel.on('close', method(:on_close))
@@ -30,36 +30,32 @@ module Playwright
30
30
  @contexts << context
31
31
  context.browser = self
32
32
  context.options = params
33
+ return context unless block
33
34
 
34
- if block
35
- begin
36
- block.call(context)
37
- ensure
38
- context.close
39
- end
40
- else
41
- context
35
+ begin
36
+ block.call(context)
37
+ ensure
38
+ context.close
42
39
  end
43
40
  end
44
41
 
45
- def new_page(**options)
42
+ def new_page(**options, &block)
46
43
  context = new_context(**options)
47
44
  page = context.new_page
48
45
  page.owned_context = context
49
46
  context.owner_page = page
50
- page
47
+
48
+ return page unless block
49
+
50
+ begin
51
+ block.call(page)
52
+ ensure
53
+ page.close
54
+ end
51
55
  end
52
56
 
53
57
  def close
54
58
  return if @closed_or_closing
55
- if @remote
56
- @contexts.each do |context|
57
- context.pages.each do |page|
58
- page.send(:on_close)
59
- end
60
- context.send(:on_close)
61
- end
62
- end
63
59
  @closed_or_closing = true
64
60
  @channel.send_message_to_server('close')
65
61
  nil
@@ -89,14 +85,6 @@ module Playwright
89
85
 
90
86
  private def on_close(_ = {})
91
87
  @connected = false
92
- if @remote
93
- @contexts.each do |context|
94
- context.pages.each do |page|
95
- page.send(:on_close)
96
- end
97
- context.send(:on_close)
98
- end
99
- end
100
88
  emit(Events::Browser::Disconnected, self)
101
89
  @closed_or_closing = true
102
90
  end
@@ -46,6 +46,8 @@ module Playwright
46
46
  ChannelOwners::Request.from_nullable(params['page']),
47
47
  )
48
48
  })
49
+
50
+ @closed_promise = Concurrent::Promises.resolvable_future
49
51
  end
50
52
 
51
53
  private def on_page(page)
@@ -111,10 +113,17 @@ module Playwright
111
113
  end
112
114
 
113
115
  # @returns [Playwright::Page]
114
- def new_page
116
+ def new_page(&block)
115
117
  raise 'Please use browser.new_context' if @owner_page
116
118
  resp = @channel.send_message_to_server('newPage')
117
- ChannelOwners::Page.from(resp)
119
+ page = ChannelOwners::Page.from(resp)
120
+ return page unless block
121
+
122
+ begin
123
+ block.call(page)
124
+ ensure
125
+ page.close
126
+ end
118
127
  end
119
128
 
120
129
  def cookies(urls: nil)
@@ -223,15 +232,14 @@ module Playwright
223
232
  end
224
233
 
225
234
  private def on_close
226
- @closed_or_closing = true
227
235
  @browser&.send(:remove_context, self)
228
236
  emit(Events::BrowserContext::Close)
237
+ @closed_promise.fulfill(true)
229
238
  end
230
239
 
231
240
  def close
232
- return if @closed_or_closing
233
- @closed_or_closing = true
234
241
  @channel.send_message_to_server('close')
242
+ @closed_promise.value!
235
243
  nil
236
244
  rescue => err
237
245
  raise unless safe_close_error?(err)
@@ -1,5 +1,7 @@
1
1
  module Playwright
2
2
  define_channel_owner :BrowserType do
3
+ include Utils::PrepareBrowserContextOptions
4
+
3
5
  def name
4
6
  @initializer['name']
5
7
  end
@@ -11,15 +13,28 @@ module Playwright
11
13
  def launch(options, &block)
12
14
  resp = @channel.send_message_to_server('launch', options.compact)
13
15
  browser = ChannelOwners::Browser.from(resp)
16
+ return browser unless block
14
17
 
15
- if block
16
- begin
17
- block.call(browser)
18
- ensure
19
- browser.close
20
- end
21
- else
22
- browser
18
+ begin
19
+ block.call(browser)
20
+ ensure
21
+ browser.close
22
+ end
23
+ end
24
+
25
+ def launch_persistent_context(userDataDir, **options, &block)
26
+ params = options.dup
27
+ prepare_browser_context_options(params)
28
+ params['userDataDir'] = userDataDir
29
+
30
+ resp = @channel.send_message_to_server('launchPersistentContext', params.compact)
31
+ context = ChannelOwners::Browser.from(resp)
32
+ return context unless block
33
+
34
+ begin
35
+ block.call(context)
36
+ ensure
37
+ context.close
23
38
  end
24
39
  end
25
40
 
@@ -65,7 +65,8 @@ module Playwright
65
65
  emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
66
66
  })
67
67
  @channel.on('worker', ->(params) {
68
- on_worker(ChannelOwners::Worker.from(params['worker']))
68
+ worker = ChannelOwners::Worker.from(params['worker'])
69
+ # on_worker(worker)
69
70
  })
70
71
  end
71
72
 
@@ -773,6 +774,10 @@ module Playwright
773
774
  expect_event(Events::Page::Response, predicate: predicate, timeout: timeout, &block)
774
775
  end
775
776
 
777
+ def expect_websocket(predicate: nil, timeout: nil, &block)
778
+ expect_event(Events::Page::WebSocket, predicate: predicate, timeout: timeout, &block)
779
+ end
780
+
776
781
  # called from Frame with send(:timeout_settings)
777
782
  private def timeout_settings
778
783
  @timeout_settings
@@ -0,0 +1,87 @@
1
+ require 'base64'
2
+
3
+ module Playwright
4
+ define_channel_owner :WebSocket do
5
+ private def after_initialize
6
+ @closed = false
7
+
8
+ @channel.on('frameSent', -> (params) {
9
+ on_frame_sent(params['opcode'], params['data'])
10
+ })
11
+ @channel.on('frameReceived', -> (params) {
12
+ on_frame_received(params['opcode'], params['data'])
13
+ })
14
+ @channel.on('socketError', -> (params) {
15
+ emit(Events::WebSocket::Error, params['error'])
16
+ })
17
+ @channel.on('close', -> (_) { on_close })
18
+ end
19
+
20
+ def url
21
+ @initializer['url']
22
+ end
23
+
24
+ class SocketClosedError < StandardError
25
+ def initialize
26
+ super('Socket closed')
27
+ end
28
+ end
29
+
30
+ class SocketError < StandardError
31
+ def initialize
32
+ super('Socket error')
33
+ end
34
+ end
35
+
36
+ class PageClosedError < StandardError
37
+ def initialize
38
+ super('Page closed')
39
+ end
40
+ end
41
+
42
+ def expect_event(event, predicate: nil, timeout: nil, &block)
43
+ wait_helper = WaitHelper.new
44
+ wait_helper.reject_on_timeout(timeout || @parent.send(:timeout_settings).timeout, "Timeout while waiting for event \"#{event}\"")
45
+
46
+ unless event == Events::WebSocket::Close
47
+ wait_helper.reject_on_event(self, Events::WebSocket::Close, SocketClosedError.new)
48
+ end
49
+
50
+ unless event == Events::WebSocket::Error
51
+ wait_helper.reject_on_event(self, Events::WebSocket::Error, SocketError.new)
52
+ end
53
+
54
+ wait_helper.reject_on_event(@parent, 'close', PageClosedError.new)
55
+ wait_helper.wait_for_event(self, event, predicate: predicate)
56
+ block&.call
57
+
58
+ wait_helper.promise.value!
59
+ end
60
+ alias_method :wait_for_event, :expect_event
61
+
62
+ private def on_frame_sent(opcode, data)
63
+ if opcode == 2
64
+ emit(Events::WebSocket::FrameSent, Base64.strict_decode64(data))
65
+ else
66
+ emit(Events::WebSocket::FrameSent, data)
67
+ end
68
+ end
69
+
70
+ private def on_frame_received(opcode, data)
71
+ if opcode == 2
72
+ emit(Events::WebSocket::FrameReceived, Base64.strict_decode64(data))
73
+ else
74
+ emit(Events::WebSocket::FrameReceived, data)
75
+ end
76
+ end
77
+
78
+ def closed?
79
+ @closed
80
+ end
81
+
82
+ private def on_close
83
+ @closed = true
84
+ emit(Events::WebSocket::Close)
85
+ end
86
+ end
87
+ end
@@ -15,17 +15,17 @@ module Playwright
15
15
  end
16
16
 
17
17
  # Stop tracing.
18
- def stop
18
+ def stop(path: nil)
19
19
  @channel.send_message_to_server('tracingStop')
20
- end
21
20
 
22
- def export(path)
23
- resp = @channel.send_message_to_server('tracingExport')
24
- artifact = ChannelOwners::Artifact.from(resp)
25
- # if self._context._browser:
26
- # artifact._is_remote = self._context._browser._is_remote
27
- artifact.save_as(path)
28
- artifact.delete
21
+ if path
22
+ resp = @channel.send_message_to_server('tracingExport')
23
+ artifact = ChannelOwners::Artifact.from(resp)
24
+ # if self._context._browser:
25
+ # artifact._is_remote = self._context._browser._is_remote
26
+ artifact.save_as(path)
27
+ artifact.delete
28
+ end
29
29
  end
30
30
  end
31
31
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '0.6.2'
4
+ VERSION = '0.7.0'
5
5
  COMPATIBLE_PLAYWRIGHT_VERSION = '1.12.0'
6
6
  end
@@ -1,12 +1,13 @@
1
1
  module Playwright
2
- # Playwright has **experimental** support for Android automation. You can access android namespace via:
2
+ # Playwright has **experimental** support for Android automation. See [here](./mobile.md) for more information. You can
3
+ # access android namespace via:
3
4
  #
4
5
  # An example of the Android automation script would be:
5
6
  #
6
7
  # Note that since you don't need Playwright to install web browsers when testing Android, you can omit browser download
7
8
  # via setting the following environment variable when installing Playwright:
8
9
  #
9
- # ```sh js
10
+ # ```bash js
10
11
  # PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm i -D playwright
11
12
  # ```
12
13
  class Android < PlaywrightApi
@@ -22,12 +23,6 @@ module Playwright
22
23
  end
23
24
  alias_method :default_timeout=, :set_default_timeout
24
25
 
25
- # -- inherited from EventEmitter --
26
- # @nodoc
27
- def once(event, callback)
28
- event_emitter_proxy.once(event, callback)
29
- end
30
-
31
26
  # -- inherited from EventEmitter --
32
27
  # @nodoc
33
28
  def on(event, callback)
@@ -40,6 +35,12 @@ module Playwright
40
35
  event_emitter_proxy.off(event, callback)
41
36
  end
42
37
 
38
+ # -- inherited from EventEmitter --
39
+ # @nodoc
40
+ def once(event, callback)
41
+ event_emitter_proxy.once(event, callback)
42
+ end
43
+
43
44
  private def event_emitter_proxy
44
45
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
45
46
  end
@@ -171,12 +171,6 @@ module Playwright
171
171
  wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
172
172
  end
173
173
 
174
- # -- inherited from EventEmitter --
175
- # @nodoc
176
- def once(event, callback)
177
- event_emitter_proxy.once(event, callback)
178
- end
179
-
180
174
  # -- inherited from EventEmitter --
181
175
  # @nodoc
182
176
  def on(event, callback)
@@ -189,6 +183,12 @@ module Playwright
189
183
  event_emitter_proxy.off(event, callback)
190
184
  end
191
185
 
186
+ # -- inherited from EventEmitter --
187
+ # @nodoc
188
+ def once(event, callback)
189
+ event_emitter_proxy.once(event, callback)
190
+ end
191
+
192
192
  private def event_emitter_proxy
193
193
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
194
194
  end
@@ -125,8 +125,9 @@ module Playwright
125
125
  storageState: nil,
126
126
  timezoneId: nil,
127
127
  userAgent: nil,
128
- viewport: nil)
129
- 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)))
128
+ viewport: nil,
129
+ &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)))
130
131
  end
131
132
 
132
133
  # > NOTE: Tracing is only supported on Chromium-based browsers.
@@ -155,12 +156,6 @@ module Playwright
155
156
  wrap_impl(@impl.version)
156
157
  end
157
158
 
158
- # -- inherited from EventEmitter --
159
- # @nodoc
160
- def once(event, callback)
161
- event_emitter_proxy.once(event, callback)
162
- end
163
-
164
159
  # -- inherited from EventEmitter --
165
160
  # @nodoc
166
161
  def on(event, callback)
@@ -173,6 +168,12 @@ module Playwright
173
168
  event_emitter_proxy.off(event, callback)
174
169
  end
175
170
 
171
+ # -- inherited from EventEmitter --
172
+ # @nodoc
173
+ def once(event, callback)
174
+ event_emitter_proxy.once(event, callback)
175
+ end
176
+
176
177
  private def event_emitter_proxy
177
178
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
178
179
  end
@@ -208,8 +208,8 @@ module Playwright
208
208
  end
209
209
 
210
210
  # Creates a new page in the browser context.
211
- def new_page
212
- wrap_impl(@impl.new_page)
211
+ def new_page(&block)
212
+ wrap_impl(@impl.new_page(&wrap_block_call(block)))
213
213
  end
214
214
 
215
215
  # Returns all open pages in the context.
@@ -382,12 +382,6 @@ module Playwright
382
382
  wrap_impl(@impl.pause)
383
383
  end
384
384
 
385
- # -- inherited from EventEmitter --
386
- # @nodoc
387
- def once(event, callback)
388
- event_emitter_proxy.once(event, callback)
389
- end
390
-
391
385
  # -- inherited from EventEmitter --
392
386
  # @nodoc
393
387
  def on(event, callback)
@@ -400,6 +394,12 @@ module Playwright
400
394
  event_emitter_proxy.off(event, callback)
401
395
  end
402
396
 
397
+ # -- inherited from EventEmitter --
398
+ # @nodoc
399
+ def once(event, callback)
400
+ event_emitter_proxy.once(event, callback)
401
+ end
402
+
403
403
  private def event_emitter_proxy
404
404
  @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
405
405
  end