playwright-ruby-client 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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
data/lib/playwright.rb CHANGED
@@ -15,8 +15,10 @@ require 'playwright/utils'
15
15
 
16
16
  require 'playwright/channel'
17
17
  require 'playwright/channel_owner'
18
+ require 'playwright/input_files'
18
19
  require 'playwright/input_type'
19
20
  require 'playwright/connection'
21
+ require 'playwright/select_option_values'
20
22
  require 'playwright/timeout_settings'
21
23
  require 'playwright/transport'
22
24
  require 'playwright/url_matcher'
@@ -39,13 +39,14 @@ module Playwright
39
39
 
40
40
  attr_reader :channel
41
41
 
42
- def dispose
42
+ # used only from Connection. Not intended for public use. So keep private.
43
+ private def dispose!
43
44
  # Clean up from parent and connection.
44
45
  @parent&.send(:delete_object_from_child, @guid)
45
46
  @connection.send(:delete_object_from_channel_owner, @guid)
46
47
 
47
48
  # Dispose all children.
48
- @objects.each_value(&:dispose)
49
+ @objects.each_value { |object| object.send(:dispose!) }
49
50
  @objects.clear
50
51
  end
51
52
 
@@ -1,3 +1,12 @@
1
1
  module Playwright
2
- define_channel_owner :Android
2
+ define_channel_owner :Android do
3
+ def after_initialize
4
+ @timeout_settings = TimeoutSettings.new
5
+ end
6
+
7
+ def devices
8
+ resp = @channel.send_message_to_server('devices')
9
+ resp.map { |device| ChannelOwners::AndroidDevice.from(device) }
10
+ end
11
+ end
3
12
  end
@@ -0,0 +1,93 @@
1
+ module Playwright
2
+ define_channel_owner :AndroidDevice do
3
+ include Utils::PrepareBrowserContextOptions
4
+
5
+ def serial
6
+ @initializer['serial']
7
+ end
8
+
9
+ def model
10
+ @initializer['model']
11
+ end
12
+
13
+ def shell(command)
14
+ resp = @channel.send_message_to_server('shell', command: command)
15
+ Base64.strict_decode64(resp)
16
+ end
17
+
18
+ def close
19
+ @channel.send_message_to_server('close')
20
+ emit(Events::AndroidDevice::Close)
21
+ end
22
+
23
+ def launch_browser(
24
+ pkg: nil,
25
+ acceptDownloads: nil,
26
+ bypassCSP: nil,
27
+ colorScheme: nil,
28
+ deviceScaleFactor: nil,
29
+ extraHTTPHeaders: nil,
30
+ geolocation: nil,
31
+ hasTouch: nil,
32
+ httpCredentials: nil,
33
+ ignoreHTTPSErrors: nil,
34
+ isMobile: nil,
35
+ javaScriptEnabled: nil,
36
+ locale: nil,
37
+ logger: nil,
38
+ offline: nil,
39
+ permissions: nil,
40
+ proxy: nil,
41
+ recordHar: nil,
42
+ recordVideo: nil,
43
+ storageState: nil,
44
+ timezoneId: nil,
45
+ userAgent: nil,
46
+ videoSize: nil,
47
+ videosPath: nil,
48
+ viewport: nil,
49
+ &block)
50
+ params = {
51
+ pkg: pkg,
52
+ acceptDownloads: acceptDownloads,
53
+ bypassCSP: bypassCSP,
54
+ colorScheme: colorScheme,
55
+ deviceScaleFactor: deviceScaleFactor,
56
+ extraHTTPHeaders: extraHTTPHeaders,
57
+ geolocation: geolocation,
58
+ hasTouch: hasTouch,
59
+ httpCredentials: httpCredentials,
60
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
61
+ isMobile: isMobile,
62
+ javaScriptEnabled: javaScriptEnabled,
63
+ locale: locale,
64
+ logger: logger,
65
+ offline: offline,
66
+ permissions: permissions,
67
+ proxy: proxy,
68
+ recordHar: recordHar,
69
+ recordVideo: recordVideo,
70
+ storageState: storageState,
71
+ timezoneId: timezoneId,
72
+ userAgent: userAgent,
73
+ videoSize: videoSize,
74
+ videosPath: videosPath,
75
+ viewport: viewport,
76
+ }.compact
77
+ prepare_browser_context_options(params)
78
+
79
+ resp = @channel.send_message_to_server('launchBrowser', params)
80
+ context = ChannelOwners::BrowserContext.from(resp)
81
+
82
+ if block
83
+ begin
84
+ block.call(context)
85
+ ensure
86
+ context.close
87
+ end
88
+ else
89
+ context
90
+ end
91
+ end
92
+ end
93
+ end
@@ -2,6 +2,7 @@ module Playwright
2
2
  # @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser.py
3
3
  define_channel_owner :Browser do
4
4
  include Utils::Errors::SafeCloseError
5
+ include Utils::PrepareBrowserContextOptions
5
6
 
6
7
  def after_initialize
7
8
  @contexts = Set.new
@@ -16,26 +17,25 @@ module Playwright
16
17
  @connected
17
18
  end
18
19
 
19
- def new_context(**options)
20
+ def new_context(**options, &block)
20
21
  params = options.dup
21
- # @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
22
- if params[:viewport] == 0
23
- params.delete(:viewport)
24
- params[:noDefaultViewport] = true
25
- end
26
- if params[:extraHTTPHeaders]
27
- # TODO
28
- end
29
- if params[:storageState].is_a?(String)
30
- params[:storageState] = JSON.parse(File.read(params[:storageState]))
31
- end
22
+ prepare_browser_context_options(params)
32
23
 
33
24
  resp = @channel.send_message_to_server('newContext', params.compact)
34
25
  context = ChannelOwners::BrowserContext.from(resp)
35
26
  @contexts << context
36
27
  context.browser = self
37
28
  context.options = params
38
- context
29
+
30
+ if block
31
+ begin
32
+ block.call(context)
33
+ ensure
34
+ context.close
35
+ end
36
+ else
37
+ context
38
+ end
39
39
  end
40
40
 
41
41
  def new_page(**options)
@@ -3,6 +3,91 @@ require_relative './js_handle'
3
3
  module Playwright
4
4
  module ChannelOwners
5
5
  class ElementHandle < JSHandle
6
+ def as_element
7
+ self
8
+ end
9
+
10
+ def owner_frame
11
+ resp = @channel.send_message_to_server('ownerFrame')
12
+ ChannelOwners::Frame.from_nullable(resp)
13
+ end
14
+
15
+ def content_frame
16
+ resp = @channel.send_message_to_server('contentFrame')
17
+ ChannelOwners::Frame.from_nullable(resp)
18
+ end
19
+
20
+ def get_attribute(name)
21
+ @channel.send_message_to_server('getAttribute', name: name)
22
+ end
23
+
24
+ def text_content
25
+ @channel.send_message_to_server('textContent')
26
+ end
27
+
28
+ def inner_text
29
+ @channel.send_message_to_server('innerText')
30
+ end
31
+
32
+ def inner_html
33
+ @channel.send_message_to_server('innerHTML')
34
+ end
35
+
36
+ def checked?
37
+ @channel.send_message_to_server('isChecked')
38
+ end
39
+
40
+ def disabled?
41
+ @channel.send_message_to_server('isDisabled')
42
+ end
43
+
44
+ def editable?
45
+ @channel.send_message_to_server('isEditable')
46
+ end
47
+
48
+ def enabled?
49
+ @channel.send_message_to_server('isEnabled')
50
+ end
51
+
52
+ def hidden?
53
+ @channel.send_message_to_server('isHidden')
54
+ end
55
+
56
+ def visible?
57
+ @channel.send_message_to_server('isVisible')
58
+ end
59
+
60
+ def dispatch_event(type, eventInit: nil)
61
+ params = {
62
+ type: type,
63
+ eventInit: JavaScript::ValueSerializer.new(eventInit).serialize,
64
+ }.compact
65
+ @channel.send_message_to_server('dispatchEvent', params)
66
+
67
+ nil
68
+ end
69
+
70
+ def scroll_into_view_if_needed(timeout: nil)
71
+ params = {
72
+ timeout: timeout,
73
+ }.compact
74
+ @channel.send_message_to_server('scrollIntoViewIfNeeded', params)
75
+
76
+ nil
77
+ end
78
+
79
+ def hover(force: nil, modifiers: nil, position: nil, timeout: nil)
80
+ params = {
81
+ force: force,
82
+ modifiers: modifiers,
83
+ position: position,
84
+ timeout: timeout,
85
+ }
86
+ @channel.send_message_to_server('hover', params)
87
+
88
+ nil
89
+ end
90
+
6
91
  def click(
7
92
  button: nil,
8
93
  clickCount: nil,
@@ -28,7 +113,89 @@ module Playwright
28
113
  nil
29
114
  end
30
115
 
31
- def type_text(text, delay: nil, noWaitAfter: nil, timeout: nil)
116
+ def dblclick(
117
+ button: nil,
118
+ delay: nil,
119
+ force: nil,
120
+ modifiers: nil,
121
+ noWaitAfter: nil,
122
+ position: nil,
123
+ timeout: nil)
124
+
125
+ params = {
126
+ button: button,
127
+ delay: delay,
128
+ force: force,
129
+ modifiers: modifiers,
130
+ noWaitAfter: noWaitAfter,
131
+ position: position,
132
+ timeout: timeout,
133
+ }.compact
134
+ @channel.send_message_to_server('dblclick', params)
135
+
136
+ nil
137
+ end
138
+
139
+ def select_option(values, noWaitAfter: nil, timeout: nil)
140
+ base_params = SelectOptionValues.new(values).as_params
141
+ params = base_params + { noWaitAfter: noWaitAfter, timeout: timeout }.compact
142
+ @channel.send_message_to_server('selectOption', params)
143
+
144
+ nil
145
+ end
146
+
147
+ def tap_point(
148
+ force: nil,
149
+ modifiers: nil,
150
+ noWaitAfter: nil,
151
+ position: nil,
152
+ timeout: nil)
153
+
154
+ params = {
155
+ force: force,
156
+ modifiers: modifiers,
157
+ noWaitAfter: noWaitAfter,
158
+ position: position,
159
+ timeout: timeout,
160
+ }.compact
161
+ @channel.send_message_to_server('tap', params)
162
+
163
+ nil
164
+ end
165
+
166
+ def fill(value, noWaitAfter: nil, timeout: nil)
167
+ params = {
168
+ value: value,
169
+ noWaitAfter: noWaitAfter,
170
+ timeout: timeout,
171
+ }
172
+ @channel.send_message_to_server('fill', params)
173
+
174
+ nil
175
+ end
176
+
177
+ def select_text(timeout: nil)
178
+ params = { timeout: timeout }.compact
179
+ @channel.send_message_to_server('selectText', params)
180
+
181
+ nil
182
+ end
183
+
184
+ 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
187
+ @channel.send_message_to_server('setInputFiles', params)
188
+
189
+ nil
190
+ end
191
+
192
+ def focus
193
+ @channel.send_message_to_server('focus')
194
+
195
+ nil
196
+ end
197
+
198
+ def type(text, delay: nil, noWaitAfter: nil, timeout: nil)
32
199
  params = {
33
200
  text: text,
34
201
  delay: delay,
@@ -52,6 +219,56 @@ module Playwright
52
219
  nil
53
220
  end
54
221
 
222
+ def check(force: nil, noWaitAfter: nil, timeout: nil)
223
+ params = {
224
+ force: force,
225
+ noWaitAfter: noWaitAfter,
226
+ timeout: timeout,
227
+ }.compact
228
+ @channel.send_message_to_server('check', params)
229
+
230
+ nil
231
+ end
232
+
233
+ def uncheck(force: nil, noWaitAfter: nil, timeout: nil)
234
+ params = {
235
+ force: force,
236
+ noWaitAfter: noWaitAfter,
237
+ timeout: timeout,
238
+ }.compact
239
+ @channel.send_message_to_server('uncheck', params)
240
+
241
+ nil
242
+ end
243
+
244
+ def bounding_box
245
+ @channel.send_message_to_server('boundingBox')
246
+ end
247
+
248
+ def screenshot(
249
+ omitBackground: nil,
250
+ path: nil,
251
+ quality: nil,
252
+ timeout: nil,
253
+ type: nil)
254
+
255
+ params = {
256
+ omitBackground: omitBackground,
257
+ path: path,
258
+ quality: quality,
259
+ timeout: timeout,
260
+ type: type,
261
+ }.compact
262
+ encoded_binary = @channel.send_message_to_server('screenshot', params)
263
+ decoded_binary = Base64.strict_decode64(encoded_binary)
264
+ if path
265
+ File.open(path, 'wb') do |f|
266
+ f.write(decoded_binary)
267
+ end
268
+ end
269
+ decoded_binary
270
+ end
271
+
55
272
  def query_selector(selector)
56
273
  resp = @channel.send_message_to_server('querySelector', selector: selector)
57
274
  ChannelOwners::ElementHandle.from_nullable(resp)
@@ -78,6 +295,20 @@ module Playwright
78
295
  JavaScript::Expression.new(pageFunction).eval_on_selector_all(@channel, selector)
79
296
  end
80
297
  end
298
+
299
+ def wait_for_element_state(state, timeout: nil)
300
+ params = { state: state, timeout: timeout }.compact
301
+ @channel.send_message_to_server('waitForElementState', params)
302
+
303
+ nil
304
+ end
305
+
306
+ def wait_for_selector(selector, state: nil, timeout: nil)
307
+ params = { selector: selector, state: state, timeout: timeout }.compact
308
+ resp = @channel.send_message_to_server('waitForSelector', params)
309
+
310
+ ChannelOwners::ElementHandle.from_nullable(resp)
311
+ end
81
312
  end
82
313
  end
83
314
  end
@@ -62,7 +62,7 @@ module Playwright
62
62
  end
63
63
  end
64
64
 
65
- def wait_for_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
65
+ def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
66
66
  option_wait_until = waitUntil || 'load'
67
67
  option_timeout = timeout || @page.send(:timeout_settings).navigation_timeout
68
68
  time_start = Time.now
@@ -100,6 +100,7 @@ module Playwright
100
100
 
101
101
  def wait_for_load_state(state: nil, timeout: nil)
102
102
  option_state = state || 'load'
103
+ option_timeout = timeout || @page.send(:timeout_settings).navigation_timeout
103
104
  unless %w(load domcontentloaded networkidle).include?(option_state)
104
105
  raise ArgumentError.new('state: expected one of (load|domcontentloaded|networkidle)')
105
106
  end
@@ -107,7 +108,7 @@ module Playwright
107
108
  return
108
109
  end
109
110
 
110
- wait_helper = setup_navigation_wait_helper(timeout: timeout)
111
+ wait_helper = setup_navigation_wait_helper(timeout: option_timeout)
111
112
 
112
113
  predicate = ->(state) { state == option_state }
113
114
  wait_helper.wait_for_event(@event_emitter, 'loadstate', predicate: predicate)
@@ -202,13 +203,50 @@ module Playwright
202
203
  nil
203
204
  end
204
205
 
206
+ def dblclick(
207
+ selector,
208
+ button: nil,
209
+ delay: nil,
210
+ force: nil,
211
+ modifiers: nil,
212
+ noWaitAfter: nil,
213
+ position: nil,
214
+ timeout: nil)
215
+
216
+ params = {
217
+ selector: selector,
218
+ button: button,
219
+ delay: delay,
220
+ force: force,
221
+ modifiers: modifiers,
222
+ noWaitAfter: noWaitAfter,
223
+ position: position,
224
+ timeout: timeout,
225
+ }.compact
226
+ @channel.send_message_to_server('dblclick', params)
227
+
228
+ nil
229
+ end
230
+
231
+ def fill(selector, value, noWaitAfter: nil, timeout: nil)
232
+ params = {
233
+ selector: selector,
234
+ value: value,
235
+ noWaitAfter: noWaitAfter,
236
+ timeout: timeout,
237
+ }.compact
238
+ @channel.send_message_to_server('fill', params)
239
+
240
+ nil
241
+ end
242
+
205
243
  def focus(selector, timeout: nil)
206
244
  params = { selector: selector, timeout: timeout }.compact
207
245
  @channel.send_message_to_server('focus', params)
208
246
  nil
209
247
  end
210
248
 
211
- def type_text(
249
+ def type(
212
250
  selector,
213
251
  text,
214
252
  delay: nil,