playwright-ruby-client 0.0.7 → 0.2.1

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