playwright-ruby-client 0.0.7 → 0.2.1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -3
  3. data/docs/api_coverage.md +89 -84
  4. data/lib/playwright.rb +4 -2
  5. data/lib/playwright/android_input_impl.rb +23 -0
  6. data/lib/playwright/api_implementation.rb +18 -0
  7. data/lib/playwright/channel.rb +7 -0
  8. data/lib/playwright/channel_owner.rb +3 -5
  9. data/lib/playwright/channel_owners/android.rb +1 -1
  10. data/lib/playwright/channel_owners/android_device.rb +83 -13
  11. data/lib/playwright/channel_owners/browser.rb +1 -1
  12. data/lib/playwright/channel_owners/browser_context.rb +10 -2
  13. data/lib/playwright/channel_owners/download.rb +27 -0
  14. data/lib/playwright/channel_owners/element_handle.rb +15 -4
  15. data/lib/playwright/channel_owners/frame.rb +228 -19
  16. data/lib/playwright/channel_owners/js_handle.rb +1 -1
  17. data/lib/playwright/channel_owners/page.rb +350 -27
  18. data/lib/playwright/channel_owners/request.rb +9 -1
  19. data/lib/playwright/errors.rb +1 -1
  20. data/lib/playwright/event_emitter.rb +8 -1
  21. data/lib/playwright/event_emitter_proxy.rb +49 -0
  22. data/lib/playwright/file_chooser_impl.rb +23 -0
  23. data/lib/playwright/http_headers.rb +20 -0
  24. data/lib/playwright/input_files.rb +1 -1
  25. data/lib/playwright/javascript/expression.rb +15 -0
  26. data/lib/playwright/javascript/function.rb +15 -0
  27. data/lib/playwright/javascript/value_parser.rb +1 -1
  28. data/lib/playwright/javascript/value_serializer.rb +1 -1
  29. data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +5 -1
  30. data/lib/playwright/mouse_impl.rb +7 -0
  31. data/lib/playwright/playwright_api.rb +59 -20
  32. data/lib/playwright/select_option_values.rb +14 -4
  33. data/lib/playwright/timeout_settings.rb +1 -1
  34. data/lib/playwright/touchscreen_impl.rb +7 -0
  35. data/lib/playwright/utils.rb +3 -3
  36. data/lib/playwright/version.rb +1 -1
  37. data/lib/playwright/wait_helper.rb +1 -1
  38. data/lib/playwright_api/android.rb +9 -10
  39. data/lib/playwright_api/android_device.rb +43 -14
  40. data/lib/playwright_api/android_input.rb +25 -0
  41. data/lib/playwright_api/binding_call.rb +10 -6
  42. data/lib/playwright_api/browser.rb +20 -21
  43. data/lib/playwright_api/browser_context.rb +29 -20
  44. data/lib/playwright_api/browser_type.rb +16 -56
  45. data/lib/playwright_api/chromium_browser_context.rb +10 -8
  46. data/lib/playwright_api/console_message.rb +10 -6
  47. data/lib/playwright_api/dialog.rb +5 -1
  48. data/lib/playwright_api/download.rb +28 -11
  49. data/lib/playwright_api/element_handle.rb +107 -96
  50. data/lib/playwright_api/file_chooser.rb +17 -9
  51. data/lib/playwright_api/frame.rb +136 -132
  52. data/lib/playwright_api/js_handle.rb +18 -20
  53. data/lib/playwright_api/keyboard.rb +5 -5
  54. data/lib/playwright_api/page.rb +204 -149
  55. data/lib/playwright_api/playwright.rb +32 -44
  56. data/lib/playwright_api/request.rb +7 -8
  57. data/lib/playwright_api/response.rb +10 -6
  58. data/lib/playwright_api/selectors.rb +13 -9
  59. data/lib/playwright_api/web_socket.rb +10 -1
  60. data/lib/playwright_api/worker.rb +13 -13
  61. metadata +12 -6
  62. data/lib/playwright/input_type.rb +0 -19
  63. data/lib/playwright/input_types/mouse.rb +0 -4
  64. data/lib/playwright/input_types/touchscreen.rb +0 -4
@@ -59,16 +59,14 @@ module Playwright
59
59
  "#<#{@guid}>"
60
60
  end
61
61
 
62
- private
63
-
64
- def after_initialize
62
+ private def after_initialize
65
63
  end
66
64
 
67
- def update_object_from_child(guid, child)
65
+ private def update_object_from_child(guid, child)
68
66
  @objects[guid] = child
69
67
  end
70
68
 
71
- def delete_object_from_child(guid)
69
+ private def delete_object_from_child(guid)
72
70
  @objects.delete(guid)
73
71
  end
74
72
  end
@@ -1,6 +1,6 @@
1
1
  module Playwright
2
2
  define_channel_owner :Android do
3
- def after_initialize
3
+ private def after_initialize
4
4
  @timeout_settings = TimeoutSettings.new
5
5
  end
6
6
 
@@ -2,6 +2,12 @@ module Playwright
2
2
  define_channel_owner :AndroidDevice do
3
3
  include Utils::PrepareBrowserContextOptions
4
4
 
5
+ private def after_initialize
6
+ @input = AndroidInputImpl.new(@channel)
7
+ end
8
+
9
+ attr_reader :input
10
+
5
11
  def serial
6
12
  @initializer['serial']
7
13
  end
@@ -10,9 +16,68 @@ module Playwright
10
16
  @initializer['model']
11
17
  end
12
18
 
13
- def shell(command)
14
- resp = @channel.send_message_to_server('shell', command: command)
15
- Base64.strict_decode64(resp)
19
+ private def to_regex(value)
20
+ case value
21
+ when nil
22
+ nil
23
+ when Regexp
24
+ value
25
+ else
26
+ Regexp.new("^#{value}$")
27
+ end
28
+ end
29
+
30
+ private def to_selector_channel(selector)
31
+ {
32
+ checkable: selector[:checkable],
33
+ checked: selector[:checked],
34
+ clazz: to_regex(selector[:clazz]),
35
+ pkg: to_regex(selector[:pkg]),
36
+ desc: to_regex(selector[:desc]),
37
+ res: to_regex(selector[:res]),
38
+ text: to_regex(selector[:text]),
39
+ clickable: selector[:clickable],
40
+ depth: selector[:depth],
41
+ enabled: selector[:enabled],
42
+ focusable: selector[:focusable],
43
+ focused: selector[:focused],
44
+ hasChild: selector[:hasChild] ? { selector: to_selector_channel(selector[:hasChild][:selector]) } : nil,
45
+ hasDescendant: selector[:hasDescendant] ? {
46
+ selector: to_selector_channel(selector[:hasDescendant][:selector]),
47
+ maxDepth: selector[:hasDescendant][:maxDepth],
48
+ } : nil,
49
+ longClickable: selector[:longClickable],
50
+ scrollable: selector[:scrollable],
51
+ selected: selector[:selected],
52
+ }.compact
53
+ end
54
+
55
+ def tap_on(selector, duration: nil, timeout: nil)
56
+ params = {
57
+ selector: to_selector_channel(selector),
58
+ duration: duration,
59
+ timeout: timeout,
60
+ }.compact
61
+ @channel.send_message_to_server('tap', params)
62
+ end
63
+
64
+ def info(selector)
65
+ @channel.send_message_to_server('info', selector: to_selector_channel(selector))
66
+ end
67
+
68
+ def tree
69
+ @channel.send_message_to_server('tree')
70
+ end
71
+
72
+ def screenshot(path: nil)
73
+ encoded_binary = @channel.send_message_to_server('screenshot')
74
+ decoded_binary = Base64.strict_decode64(encoded_binary)
75
+ if path
76
+ File.open(path, 'wb') do |f|
77
+ f.write(decoded_binary)
78
+ end
79
+ end
80
+ decoded_binary
16
81
  end
17
82
 
18
83
  def close
@@ -20,6 +85,11 @@ module Playwright
20
85
  emit(Events::AndroidDevice::Close)
21
86
  end
22
87
 
88
+ def shell(command)
89
+ resp = @channel.send_message_to_server('shell', command: command)
90
+ Base64.strict_decode64(resp)
91
+ end
92
+
23
93
  def launch_browser(
24
94
  pkg: nil,
25
95
  acceptDownloads: nil,
@@ -34,17 +104,17 @@ module Playwright
34
104
  isMobile: nil,
35
105
  javaScriptEnabled: nil,
36
106
  locale: nil,
37
- logger: nil,
107
+ noViewport: nil,
38
108
  offline: nil,
39
109
  permissions: nil,
40
110
  proxy: nil,
41
- recordHar: nil,
42
- recordVideo: nil,
111
+ record_har_omit_content: nil,
112
+ record_har_path: nil,
113
+ record_video_dir: nil,
114
+ record_video_size: nil,
43
115
  storageState: nil,
44
116
  timezoneId: nil,
45
117
  userAgent: nil,
46
- videoSize: nil,
47
- videosPath: nil,
48
118
  viewport: nil,
49
119
  &block)
50
120
  params = {
@@ -61,17 +131,17 @@ module Playwright
61
131
  isMobile: isMobile,
62
132
  javaScriptEnabled: javaScriptEnabled,
63
133
  locale: locale,
64
- logger: logger,
134
+ noViewport: noViewport,
65
135
  offline: offline,
66
136
  permissions: permissions,
67
137
  proxy: proxy,
68
- recordHar: recordHar,
69
- recordVideo: recordVideo,
138
+ record_har_omit_content: record_har_omit_content,
139
+ record_har_path: record_har_path,
140
+ record_video_dir: record_video_dir,
141
+ record_video_size: record_video_size,
70
142
  storageState: storageState,
71
143
  timezoneId: timezoneId,
72
144
  userAgent: userAgent,
73
- videoSize: videoSize,
74
- videosPath: videosPath,
75
145
  viewport: viewport,
76
146
  }.compact
77
147
  prepare_browser_context_options(params)
@@ -4,7 +4,7 @@ module Playwright
4
4
  include Utils::Errors::SafeCloseError
5
5
  include Utils::PrepareBrowserContextOptions
6
6
 
7
- def after_initialize
7
+ private def after_initialize
8
8
  @contexts = Set.new
9
9
  @channel.on('close', method(:on_close))
10
10
  end
@@ -4,11 +4,14 @@ module Playwright
4
4
  include Utils::Errors::SafeCloseError
5
5
  attr_writer :browser, :owner_page, :options
6
6
 
7
- def after_initialize
7
+ private def after_initialize
8
8
  @pages = Set.new
9
9
 
10
10
  @channel.once('close', ->(_) { on_close })
11
- @channel.on('page', ->(hash) { on_page(ChannelOwners::Page.from(hash['page']) )})
11
+ @channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
12
+ @channel.on('route', ->(params) {
13
+ on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
14
+ })
12
15
  end
13
16
 
14
17
  private def on_page(page)
@@ -17,6 +20,11 @@ module Playwright
17
20
  emit(Events::BrowserContext::Page, page)
18
21
  end
19
22
 
23
+ private def on_route(route, request)
24
+ # @routes.each ...
25
+ route.continue_
26
+ end
27
+
20
28
  def pages
21
29
  @pages.to_a
22
30
  end
@@ -0,0 +1,27 @@
1
+ module Playwright
2
+ define_channel_owner :Download do
3
+ def url
4
+ @initializer['url']
5
+ end
6
+
7
+ def suggested_filename
8
+ @initializer['suggestedFilename']
9
+ end
10
+
11
+ def delete
12
+ @channel.send_message_to_server('delete')
13
+ end
14
+
15
+ def failure
16
+ @channel.send_message_to_server('failure')
17
+ end
18
+
19
+ def path
20
+ @channel.send_message_to_server('path')
21
+ end
22
+
23
+ def save_as(path)
24
+ @channel.send_message_to_server('saveAs', path: path)
25
+ end
26
+ end
27
+ end
@@ -136,8 +136,19 @@ module Playwright
136
136
  nil
137
137
  end
138
138
 
139
- def select_option(values, noWaitAfter: nil, timeout: nil)
140
- base_params = SelectOptionValues.new(values).as_params
139
+ def select_option(
140
+ element: nil,
141
+ index: nil,
142
+ value: nil,
143
+ label: nil,
144
+ noWaitAfter: nil,
145
+ timeout: nil)
146
+ base_params = SelectOptionValues.new(
147
+ element: element,
148
+ index: index,
149
+ value: value,
150
+ label: label,
151
+ ).as_params
141
152
  params = base_params + { noWaitAfter: noWaitAfter, timeout: timeout }.compact
142
153
  @channel.send_message_to_server('selectOption', params)
143
154
 
@@ -182,8 +193,8 @@ module Playwright
182
193
  end
183
194
 
184
195
  def set_input_files(files, noWaitAfter: nil, timeout: nil)
185
- base_params = InputFiles.new(values).as_params
186
- params = base_params + { noWaitAfter: noWaitAfter, timeout: timeout }.compact
196
+ file_payloads = InputFiles.new(files).as_params
197
+ params = { files: file_payloads, noWaitAfter: noWaitAfter, timeout: timeout }.compact
187
198
  @channel.send_message_to_server('setInputFiles', params)
188
199
 
189
200
  nil
@@ -1,7 +1,7 @@
1
1
  module Playwright
2
2
  # @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_frame.py
3
3
  define_channel_owner :Frame do
4
- def after_initialize
4
+ private def after_initialize
5
5
  if @initializer['parentFrame']
6
6
  @parent_frame = ChannelOwners::Frame.from(@initializer['parentFrame'])
7
7
  @parent_frame.send(:append_child_frame_from_child, self)
@@ -144,6 +144,55 @@ module Playwright
144
144
  end
145
145
  end
146
146
 
147
+ def wait_for_selector(selector, state: nil, timeout: nil)
148
+ params = { selector: selector, state: state, timeout: timeout }.compact
149
+ resp = @channel.send_message_to_server('waitForSelector', params)
150
+
151
+ ChannelOwners::ElementHandle.from_nullable(resp)
152
+ end
153
+
154
+ def checked?(selector, timeout: nil)
155
+ params = { selector: selector, timeout: timeout }.compact
156
+ @channel.send_message_to_server('isChecked', params)
157
+ end
158
+
159
+ def disabled?(selector, timeout: nil)
160
+ params = { selector: selector, timeout: timeout }.compact
161
+ @channel.send_message_to_server('isDisabled', params)
162
+ end
163
+
164
+ def editable?(selector, timeout: nil)
165
+ params = { selector: selector, timeout: timeout }.compact
166
+ @channel.send_message_to_server('isEditable', params)
167
+ end
168
+
169
+ def enabled?(selector, timeout: nil)
170
+ params = { selector: selector, timeout: timeout }.compact
171
+ @channel.send_message_to_server('isEnabled', params)
172
+ end
173
+
174
+ def hidden?(selector, timeout: nil)
175
+ params = { selector: selector, timeout: timeout }.compact
176
+ @channel.send_message_to_server('isHidden', params)
177
+ end
178
+
179
+ def visible?(selector, timeout: nil)
180
+ params = { selector: selector, timeout: timeout }.compact
181
+ @channel.send_message_to_server('isVisible', params)
182
+ end
183
+
184
+ def dispatch_event(selector, type, eventInit: nil, timeout: nil)
185
+ params = {
186
+ selector: selector,
187
+ type: type,
188
+ eventInit: JavaScript::ValueSerializer.new(eventInit).serialize,
189
+ timeout: timeout,
190
+ }.compact
191
+ @channel.send_message_to_server('dispatchEvent', params)
192
+
193
+ nil
194
+ end
195
+
147
196
  def eval_on_selector(selector, pageFunction, arg: nil)
148
197
  if JavaScript.function?(pageFunction)
149
198
  JavaScript::Function.new(pageFunction, arg).eval_on_selector(@channel, selector)
@@ -176,6 +225,47 @@ module Playwright
176
225
  nil
177
226
  end
178
227
 
228
+ def name
229
+ @name || ''
230
+ end
231
+
232
+ def url
233
+ @url || ''
234
+ end
235
+
236
+ def child_frames
237
+ @child_frames.to_a
238
+ end
239
+
240
+ def detached?
241
+ @detached
242
+ end
243
+
244
+ def add_script_tag(content: nil, path: nil, type: nil, url: nil)
245
+ params = {
246
+ content: content,
247
+ type: type,
248
+ url: url,
249
+ }.compact
250
+ if path
251
+ params[:content] = "#{File.read(path)}\n//# sourceURL=#{path}"
252
+ end
253
+ resp = @channel.send_message_to_server('addScriptTag', params)
254
+ ChannelOwners::ElementHandle.from(resp)
255
+ end
256
+
257
+ def add_style_tag(content: nil, path: nil, url: nil)
258
+ params = {
259
+ content: content,
260
+ url: url,
261
+ }.compact
262
+ if path
263
+ params[:content] = "#{File.read(path)}\n/*# sourceURL=#{path}*/"
264
+ end
265
+ resp = @channel.send_message_to_server('addStyleTag', params)
266
+ ChannelOwners::ElementHandle.from(resp)
267
+ end
268
+
179
269
  def click(
180
270
  selector,
181
271
  button: nil,
@@ -228,6 +318,26 @@ module Playwright
228
318
  nil
229
319
  end
230
320
 
321
+ def tap_point(
322
+ selector,
323
+ force: nil,
324
+ modifiers: nil,
325
+ noWaitAfter: nil,
326
+ position: nil,
327
+ timeout: nil)
328
+ params = {
329
+ selector: selector,
330
+ force: force,
331
+ modifiers: modifiers,
332
+ noWaitAfter: noWaitAfter,
333
+ position: position,
334
+ timeout: timeout,
335
+ }.compact
336
+ @channel.send_message_to_server('tap', params)
337
+
338
+ nil
339
+ end
340
+
231
341
  def fill(selector, value, noWaitAfter: nil, timeout: nil)
232
342
  params = {
233
343
  selector: selector,
@@ -246,12 +356,82 @@ module Playwright
246
356
  nil
247
357
  end
248
358
 
359
+ def text_content(selector, timeout: nil)
360
+ params = { selector: selector, timeout: timeout }.compact
361
+ @channel.send_message_to_server('textContent', params)
362
+ end
363
+
364
+ def inner_text(selector, timeout: nil)
365
+ params = { selector: selector, timeout: timeout }.compact
366
+ @channel.send_message_to_server('innerText', params)
367
+ end
368
+
369
+ def inner_html(selector, timeout: nil)
370
+ params = { selector: selector, timeout: timeout }.compact
371
+ @channel.send_message_to_server('innerHTML', params)
372
+ end
373
+
374
+ def get_attribute(selector, name, timeout: nil)
375
+ params = {
376
+ selector: selector,
377
+ name: name,
378
+ timeout: timeout,
379
+ }.compact
380
+ @channel.send_message_to_server('getAttribute', params)
381
+ end
382
+
383
+ def hover(
384
+ selector,
385
+ force: nil,
386
+ modifiers: nil,
387
+ position: nil,
388
+ timeout: nil)
389
+ params = {
390
+ selector: selector,
391
+ force: force,
392
+ modifiers: modifiers,
393
+ position: position,
394
+ timeout: timeout,
395
+ }.compact
396
+ @channel.send_message_to_server('hover', params)
397
+
398
+ nil
399
+ end
400
+
401
+ def select_option(
402
+ selector,
403
+ element: nil,
404
+ index: nil,
405
+ value: nil,
406
+ label: nil,
407
+ noWaitAfter: nil,
408
+ timeout: nil)
409
+ base_params = SelectOptionValues.new(
410
+ element: element,
411
+ index: index,
412
+ value: value,
413
+ label: label,
414
+ ).as_params
415
+ params = base_params + { selector: selector, noWaitAfter: noWaitAfter, timeout: timeout }.compact
416
+ @channel.send_message_to_server('selectOption', params)
417
+
418
+ nil
419
+ end
420
+
421
+ def set_input_files(selector, files, noWaitAfter: nil, timeout: nil)
422
+ file_payloads = InputFiles.new(files).as_params
423
+ params = { files: file_payloads, selector: selector, noWaitAfter: noWaitAfter, timeout: timeout }.compact
424
+ @channel.send_message_to_server('setInputFiles', params)
425
+
426
+ nil
427
+ end
428
+
249
429
  def type(
250
- selector,
251
- text,
252
- delay: nil,
253
- noWaitAfter: nil,
254
- timeout: nil)
430
+ selector,
431
+ text,
432
+ delay: nil,
433
+ noWaitAfter: nil,
434
+ timeout: nil)
255
435
 
256
436
  params = {
257
437
  selector: selector,
@@ -260,16 +440,17 @@ module Playwright
260
440
  noWaitAfter: noWaitAfter,
261
441
  timeout: timeout,
262
442
  }.compact
263
-
264
443
  @channel.send_message_to_server('type', params)
444
+
445
+ nil
265
446
  end
266
447
 
267
448
  def press(
268
- selector,
269
- key,
270
- delay: nil,
271
- noWaitAfter: nil,
272
- timeout: nil)
449
+ selector,
450
+ key,
451
+ delay: nil,
452
+ noWaitAfter: nil,
453
+ timeout: nil)
273
454
 
274
455
  params = {
275
456
  selector: selector,
@@ -278,20 +459,48 @@ module Playwright
278
459
  noWaitAfter: noWaitAfter,
279
460
  timeout: timeout,
280
461
  }.compact
281
-
282
462
  @channel.send_message_to_server('press', params)
463
+
464
+ nil
283
465
  end
284
466
 
285
- def name
286
- @name || ''
467
+ def check(selector, force: nil, noWaitAfter: nil, timeout: nil)
468
+ params = {
469
+ selector: selector,
470
+ force: force,
471
+ noWaitAfter: noWaitAfter,
472
+ timeout: timeout,
473
+ }.compact
474
+ @channel.send_message_to_server('check', params)
475
+
476
+ nil
287
477
  end
288
478
 
289
- def url
290
- @url || ''
479
+ def uncheck(selector, force: nil, noWaitAfter: nil, timeout: nil)
480
+ params = {
481
+ selector: selector,
482
+ force: force,
483
+ noWaitAfter: noWaitAfter,
484
+ timeout: timeout,
485
+ }.compact
486
+ @channel.send_message_to_server('uncheck', params)
487
+
488
+ nil
291
489
  end
292
490
 
293
- def child_frames
294
- @child_frames.to_a
491
+ def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
492
+ if polling.is_a?(String) && polling != 'raf'
493
+ raise ArgumentError.new("Unknown polling option: #{polling}")
494
+ end
495
+
496
+ function_or_expression =
497
+ if JavaScript.function?(pageFunction)
498
+ JavaScript::Function.new(pageFunction, arg)
499
+ else
500
+ JavaScript::Expression.new(pageFunction)
501
+ end
502
+
503
+ function_or_expression.wait_for_function(@channel, polling: polling, timeout: timeout)
295
504
  end
296
505
 
297
506
  def title