playwright-ruby-client 0.0.6 → 0.0.7

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -2
  3. data/docs/api_coverage.md +354 -0
  4. data/lib/playwright.rb +2 -0
  5. data/lib/playwright/channel_owner.rb +3 -2
  6. data/lib/playwright/channel_owners/android.rb +10 -1
  7. data/lib/playwright/channel_owners/android_device.rb +93 -0
  8. data/lib/playwright/channel_owners/browser.rb +13 -13
  9. data/lib/playwright/channel_owners/element_handle.rb +232 -1
  10. data/lib/playwright/channel_owners/frame.rb +41 -3
  11. data/lib/playwright/channel_owners/js_handle.rb +51 -0
  12. data/lib/playwright/channel_owners/page.rb +48 -10
  13. data/lib/playwright/channel_owners/webkit_browser.rb +1 -1
  14. data/lib/playwright/connection.rb +9 -6
  15. data/lib/playwright/errors.rb +1 -1
  16. data/lib/playwright/input_files.rb +42 -0
  17. data/lib/playwright/input_types/keyboard.rb +1 -1
  18. data/lib/playwright/javascript/value_serializer.rb +11 -11
  19. data/lib/playwright/playwright_api.rb +8 -0
  20. data/lib/playwright/select_option_values.rb +32 -0
  21. data/lib/playwright/utils.rb +18 -0
  22. data/lib/playwright/version.rb +1 -1
  23. data/lib/playwright_api/android.rb +33 -0
  24. data/lib/playwright_api/android_device.rb +48 -0
  25. data/lib/playwright_api/binding_call.rb +3 -3
  26. data/lib/playwright_api/browser.rb +7 -6
  27. data/lib/playwright_api/browser_context.rb +6 -6
  28. data/lib/playwright_api/browser_type.rb +4 -4
  29. data/lib/playwright_api/chromium_browser_context.rb +3 -3
  30. data/lib/playwright_api/console_message.rb +3 -8
  31. data/lib/playwright_api/dialog.rb +2 -2
  32. data/lib/playwright_api/element_handle.rb +40 -39
  33. data/lib/playwright_api/frame.rb +23 -27
  34. data/lib/playwright_api/js_handle.rb +15 -9
  35. data/lib/playwright_api/keyboard.rb +6 -6
  36. data/lib/playwright_api/page.rb +35 -54
  37. data/lib/playwright_api/playwright.rb +7 -7
  38. data/lib/playwright_api/request.rb +3 -3
  39. data/lib/playwright_api/response.rb +3 -3
  40. data/lib/playwright_api/selectors.rb +3 -3
  41. data/playwright.gemspec +1 -0
  42. metadata +22 -2
@@ -1,4 +1,55 @@
1
1
  module Playwright
2
2
  define_channel_owner :JSHandle do
3
+ def after_initialize
4
+ @preview = @initializer['preview']
5
+ @channel.on('previewUpdated', method(:on_preview_updated))
6
+ end
7
+
8
+ def to_s
9
+ @preview
10
+ end
11
+
12
+ private def on_preview_updated(preview)
13
+ @preview = preview
14
+ end
15
+
16
+ def evaluate(pageFunction, arg: nil)
17
+ if JavaScript.function?(pageFunction)
18
+ JavaScript::Function.new(pageFunction, arg).evaluate(@channel)
19
+ else
20
+ JavaScript::Expression.new(pageFunction).evaluate(@channel)
21
+ end
22
+ end
23
+
24
+ def evaluate_handle(pageFunction, arg: nil)
25
+ if JavaScript.function?(pageFunction)
26
+ JavaScript::Function.new(pageFunction, arg).evaluate_handle(@channel)
27
+ else
28
+ JavaScript::Expression.new(pageFunction).evaluate_handle(@channel)
29
+ end
30
+ end
31
+
32
+ def get_properties
33
+ resp = @channel.send_message_to_server('getPropertyList')
34
+ resp.map { |prop| [prop['name'], ChannelOwner.from(prop['value'])] }.to_h
35
+ end
36
+
37
+ def get_property(name)
38
+ resp = @channel.send_message_to_server('getProperty', name: name)
39
+ ChannelOwner.from(resp)
40
+ end
41
+
42
+ def as_element
43
+ nil
44
+ end
45
+
46
+ def dispose
47
+ @channel.send_message_to_server('dispose')
48
+ end
49
+
50
+ def json_value
51
+ value = @channel.send_message_to_server('jsonValue')
52
+ JavaScript::ValueParser.new(value).parse
53
+ end
3
54
  end
4
55
  end
@@ -143,6 +143,19 @@ module Playwright
143
143
  @main_frame.goto(url, timeout: timeout, waitUntil: waitUntil, referer: referer)
144
144
  end
145
145
 
146
+ def reload(timeout: nil, waitUntil: nil)
147
+ params = {
148
+ timeout: timeout,
149
+ waitUntil: waitUntil,
150
+ }.compact
151
+ resp = @channel.send_message_to_server('reoad', params)
152
+ ChannelOwners::Response.from_nullable(resp)
153
+ end
154
+
155
+ def wait_for_load_state(state: nil, timeout: nil)
156
+ @main_frame.wait_for_load_state(state: state, timeout: timeout)
157
+ end
158
+
146
159
  def set_viewport_size(viewportSize)
147
160
  @viewport_size = viewportSize
148
161
  @channel.send_message_to_server('setViewportSize', { viewportSize: viewportSize })
@@ -167,7 +180,7 @@ module Playwright
167
180
  timeout: timeout,
168
181
  }.compact
169
182
  encoded_binary = @channel.send_message_to_server('screenshot', params)
170
- decoded_binary = Base64.decode64(encoded_binary)
183
+ decoded_binary = Base64.strict_decode64(encoded_binary)
171
184
  if path
172
185
  File.open(path, 'wb') do |f|
173
186
  f.write(decoded_binary)
@@ -217,18 +230,43 @@ module Playwright
217
230
  )
218
231
  end
219
232
 
233
+ def dblclick(
234
+ selector,
235
+ button: nil,
236
+ delay: nil,
237
+ force: nil,
238
+ modifiers: nil,
239
+ noWaitAfter: nil,
240
+ position: nil,
241
+ timeout: nil)
242
+ @main_frame.dblclick(
243
+ selector,
244
+ button: button,
245
+ delay: delay,
246
+ force: force,
247
+ modifiers: modifiers,
248
+ noWaitAfter: noWaitAfter,
249
+ position: position,
250
+ timeout: timeout,
251
+ )
252
+ end
253
+
254
+ def fill(selector, value, noWaitAfter: nil, timeout: nil)
255
+ @main_frame.fill(selector, value, noWaitAfter: noWaitAfter, timeout: timeout)
256
+ end
257
+
220
258
  def focus(selector, timeout: nil)
221
259
  @main_frame.focus(selector, timeout: timeout)
222
260
  end
223
261
 
224
- def type_text(
262
+ def type(
225
263
  selector,
226
264
  text,
227
265
  delay: nil,
228
266
  noWaitAfter: nil,
229
267
  timeout: nil)
230
268
 
231
- @main_frame.type_text(selector, text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
269
+ @main_frame.type(selector, text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
232
270
  end
233
271
 
234
272
  def press(
@@ -259,7 +297,7 @@ module Playwright
259
297
  end
260
298
  end
261
299
 
262
- def wait_for_event(event, optionsOrPredicate: nil, &block)
300
+ def expect_event(event, optionsOrPredicate: nil, &block)
263
301
  predicate, timeout =
264
302
  case optionsOrPredicate
265
303
  when Proc
@@ -289,15 +327,15 @@ module Playwright
289
327
  wait_helper.promise.value!
290
328
  end
291
329
 
292
- def wait_for_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
293
- @main_frame.wait_for_navigation(
330
+ def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
331
+ @main_frame.expect_navigation(
294
332
  timeout: timeout,
295
333
  url: url,
296
334
  waitUntil: waitUntil,
297
335
  &block)
298
336
  end
299
337
 
300
- def wait_for_request(urlOrPredicate, timeout: nil)
338
+ def expect_request(urlOrPredicate, timeout: nil)
301
339
  predicate =
302
340
  case urlOrPredicate
303
341
  when String, Regexp
@@ -309,10 +347,10 @@ module Playwright
309
347
  -> (_) { true }
310
348
  end
311
349
 
312
- wait_for_event(Events::Page::Request, optionsOrPredicate: { predicate: predicate, timeout: timeout})
350
+ expect_event(Events::Page::Request, optionsOrPredicate: { predicate: predicate, timeout: timeout})
313
351
  end
314
352
 
315
- def wait_for_response(urlOrPredicate, timeout: nil)
353
+ def expect_response(urlOrPredicate, timeout: nil)
316
354
  predicate =
317
355
  case urlOrPredicate
318
356
  when String, Regexp
@@ -324,7 +362,7 @@ module Playwright
324
362
  -> (_) { true }
325
363
  end
326
364
 
327
- wait_for_event(Events::Page::Response, optionsOrPredicate: { predicate: predicate, timeout: timeout})
365
+ expect_event(Events::Page::Response, optionsOrPredicate: { predicate: predicate, timeout: timeout})
328
366
  end
329
367
 
330
368
  # called from BrowserContext#on_page with send(:update_browser_context, page), so keep private.
@@ -2,7 +2,7 @@ require_relative './browser'
2
2
 
3
3
  module Playwright
4
4
  module ChannelOwners
5
- class WebkitBrowser < Browser
5
+ class WebKitBrowser < Browser
6
6
  end
7
7
  end
8
8
  end
@@ -55,10 +55,13 @@ module Playwright
55
55
  method: method,
56
56
  params: replace_channels_with_guids(params),
57
57
  }
58
- @transport.send_message(message)
59
- rescue Transport::AlreadyDisconnectedError => err
60
- @callbacks.delete(id)
61
- callback.reject(err)
58
+ begin
59
+ @transport.send_message(message)
60
+ rescue => err
61
+ @callbacks.delete(id)
62
+ callback.reject(err)
63
+ raise unless err.is_a?(Transport::AlreadyDisconnectedError)
64
+ end
62
65
  end
63
66
 
64
67
  callback
@@ -132,7 +135,7 @@ module Playwright
132
135
  unless object
133
136
  raise "Cannot find object to dispose: #{guid}"
134
137
  end
135
- object.dispose
138
+ object.send(:dispose!)
136
139
  return
137
140
  end
138
141
 
@@ -153,7 +156,7 @@ module Playwright
153
156
  end
154
157
 
155
158
  if payload.is_a?(Channel)
156
- { guid: payload.guid }
159
+ return { guid: payload.guid }
157
160
  end
158
161
 
159
162
  if payload.is_a?(Hash)
@@ -3,7 +3,7 @@ module Playwright
3
3
  # ref: https://github.com/microsoft/playwright-python/blob/0b4a980fed366c4c1dee9bfcdd72662d629fdc8d/playwright/_impl/_helper.py#L155
4
4
  def self.parse(error_payload)
5
5
  if error_payload['name'] == 'TimeoutError'
6
- Playwright::TimeoutError.new(
6
+ TimeoutError.new(
7
7
  message: error_payload['message'],
8
8
  stack: error_payload['stack'].split("\n"),
9
9
  )
@@ -0,0 +1,42 @@
1
+ require 'base64'
2
+ require 'mime/types'
3
+
4
+ module Playwright
5
+ class InputFiles
6
+ def initialize(files)
7
+ @params = convert(files)
8
+ end
9
+
10
+ def as_params
11
+ @params
12
+ end
13
+
14
+ private def convert(files)
15
+ return convert([files]) unless files.is_a?(Array)
16
+
17
+ files.map do |file|
18
+ case file
19
+ when String
20
+ {
21
+ name: File.basename(file),
22
+ mimeType: mime_type_for(file),
23
+ buffer: Base64.strict_encode64(File.read(file)),
24
+ }
25
+ when File
26
+ {
27
+ name: File.basename(file.path),
28
+ mimeType: mime_type_for(file.path),
29
+ buffer: Base64.strict_encode64(file.read),
30
+ }
31
+ else
32
+ raise ArgumentError.new('file must be a String or File.')
33
+ end
34
+ end
35
+ end
36
+
37
+ private def mime_type_for(filepath)
38
+ mime_types = MIME::Types.type_for(filepath)
39
+ mime_types.first || 'application/octet-stream'
40
+ end
41
+ end
42
+ end
@@ -13,7 +13,7 @@ module Playwright
13
13
  @channel.send_message_to_server('keyboardInsertText', text: text)
14
14
  end
15
15
 
16
- def type_text(text, delay: nil)
16
+ def type(text, delay: nil)
17
17
  params = {
18
18
  text: text,
19
19
  delay: delay,
@@ -15,9 +15,9 @@ module Playwright
15
15
  # ref: https://github.com/microsoft/playwright-python/blob/25a99d53e00e35365cf5113b9525272628c0e65f/playwright/_impl/_js_handle.py#L99
16
16
  private def serialize_value(value)
17
17
  case value
18
- when JSHandle
18
+ when ChannelOwners::JSHandle
19
19
  index = @handles.count
20
- @handles << v
20
+ @handles << value.channel
21
21
  { h: index }
22
22
  when nil
23
23
  { v: 'undefined' }
@@ -28,23 +28,23 @@ module Playwright
28
28
  when -Float::INFINITY
29
29
  { v: '-Infinity' }
30
30
  when true, false
31
- { b: v }
31
+ { b: value }
32
32
  when Numeric
33
- { n: v }
33
+ { n: value }
34
34
  when String
35
- { s: v }
35
+ { s: value }
36
36
  when Time
37
37
  require 'time'
38
- { d: v.utc.iso8601 }
38
+ { d: value.utc.iso8601 }
39
39
  when Regexp
40
40
  flags = []
41
- flags << 'ms' if (v.options & Regexp::MULTILINE) != 0
42
- flags << 'i' if (v.options & Regexp::IGNORECASE) != 0
43
- { r: { p: v.source, f: flags.join('') } }
41
+ flags << 'ms' if (value.options & Regexp::MULTILINE) != 0
42
+ flags << 'i' if (value.options & Regexp::IGNORECASE) != 0
43
+ { r: { p: value.source, f: flags.join('') } }
44
44
  when Array
45
- { a: v.map { |value| serialize_value(value) } }
45
+ { a: value.map { |v| serialize_value(v) } }
46
46
  when Hash
47
- { o: v.map { |key, value| [key, serialize_value(value)] }.to_h }
47
+ { o: value.map { |key, v| [key, serialize_value(v)] }.to_h }
48
48
  else
49
49
  raise ArgumentError.new("Unexpected value: #{value}")
50
50
  end
@@ -83,5 +83,13 @@ module Playwright
83
83
  object
84
84
  end
85
85
  end
86
+
87
+ private def unwrap_impl(object)
88
+ if object.is_a?(PlaywrightApi)
89
+ object.instance_variable_get(:@impl)
90
+ else
91
+ object
92
+ end
93
+ end
86
94
  end
87
95
  end
@@ -0,0 +1,32 @@
1
+ module Playwright
2
+ class SelectOptionValues
3
+ def initialize(values)
4
+ @params = convert(values)
5
+ end
6
+
7
+ # @return [Hash]
8
+ def as_params
9
+ @params
10
+ end
11
+
12
+ private def convert(values)
13
+ return {} unless values
14
+ return convert([values]) unless values.is_a?('Array')
15
+ return {} if values.empty?
16
+ values.each_with_index do |value, index|
17
+ unless values
18
+ raise ArgumentError.new("options[#{index}]: expected object, got null")
19
+ end
20
+ end
21
+
22
+ case values.first
23
+ when ElementHandle
24
+ { elements: values.map(&:channel) }
25
+ when String
26
+ { options: values.map { |value| { value: value } } }
27
+ else
28
+ { options: values }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,23 @@
1
1
  module Playwright
2
2
  module Utils
3
+ module PrepareBrowserContextOptions
4
+ # @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
5
+ private def prepare_browser_context_options(params)
6
+ if params[:viewport] == 0
7
+ params.delete(:viewport)
8
+ params[:noDefaultViewport] = true
9
+ end
10
+ if params[:extraHTTPHeaders]
11
+ # TODO
12
+ end
13
+ if params[:storageState].is_a?(String)
14
+ params[:storageState] = JSON.parse(File.read(params[:storageState]))
15
+ end
16
+
17
+ params
18
+ end
19
+ end
20
+
3
21
  module Errors
4
22
  module SafeCloseError
5
23
  # @param err [Exception]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '0.0.6'
4
+ VERSION = '0.0.7'
5
5
  end
@@ -0,0 +1,33 @@
1
+ module Playwright
2
+ # @nodoc
3
+ class Android < PlaywrightApi
4
+
5
+ # @nodoc
6
+ def after_initialize
7
+ wrap_impl(@impl.after_initialize)
8
+ end
9
+
10
+ # @nodoc
11
+ def devices
12
+ wrap_impl(@impl.devices)
13
+ end
14
+
15
+ # -- inherited from EventEmitter --
16
+ # @nodoc
17
+ def on(event, callback)
18
+ wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
19
+ end
20
+
21
+ # -- inherited from EventEmitter --
22
+ # @nodoc
23
+ def off(event, callback)
24
+ wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
25
+ end
26
+
27
+ # -- inherited from EventEmitter --
28
+ # @nodoc
29
+ def once(event, callback)
30
+ wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
31
+ end
32
+ end
33
+ end