playwright-ruby-client 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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