playwright-ruby-client 0.0.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/docs/api_coverage.md +159 -101
  4. data/lib/playwright.rb +5 -2
  5. data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
  6. data/lib/playwright/api_implementation.rb +18 -0
  7. data/lib/playwright/channel.rb +13 -6
  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 +12 -12
  11. data/lib/playwright/channel_owners/binding_call.rb +3 -0
  12. data/lib/playwright/channel_owners/browser.rb +1 -1
  13. data/lib/playwright/channel_owners/browser_context.rb +157 -3
  14. data/lib/playwright/channel_owners/dialog.rb +28 -0
  15. data/lib/playwright/channel_owners/download.rb +27 -0
  16. data/lib/playwright/channel_owners/element_handle.rb +15 -4
  17. data/lib/playwright/channel_owners/frame.rb +24 -5
  18. data/lib/playwright/channel_owners/js_handle.rb +1 -1
  19. data/lib/playwright/channel_owners/page.rb +367 -29
  20. data/lib/playwright/channel_owners/playwright.rb +4 -0
  21. data/lib/playwright/channel_owners/request.rb +35 -3
  22. data/lib/playwright/channel_owners/response.rb +60 -0
  23. data/lib/playwright/channel_owners/route.rb +78 -0
  24. data/lib/playwright/channel_owners/selectors.rb +19 -1
  25. data/lib/playwright/errors.rb +1 -1
  26. data/lib/playwright/event_emitter.rb +8 -1
  27. data/lib/playwright/event_emitter_proxy.rb +49 -0
  28. data/lib/playwright/file_chooser_impl.rb +23 -0
  29. data/lib/playwright/http_headers.rb +20 -0
  30. data/lib/playwright/input_files.rb +1 -1
  31. data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +5 -1
  32. data/lib/playwright/mouse_impl.rb +7 -0
  33. data/lib/playwright/playwright_api.rb +59 -20
  34. data/lib/playwright/route_handler_entry.rb +36 -0
  35. data/lib/playwright/select_option_values.rb +14 -4
  36. data/lib/playwright/touchscreen_impl.rb +7 -0
  37. data/lib/playwright/utils.rb +4 -3
  38. data/lib/playwright/version.rb +1 -1
  39. data/lib/playwright/wait_helper.rb +1 -1
  40. data/lib/playwright_api/android.rb +82 -11
  41. data/lib/playwright_api/android_device.rb +148 -32
  42. data/lib/playwright_api/android_input.rb +17 -13
  43. data/lib/playwright_api/android_socket.rb +16 -0
  44. data/lib/playwright_api/android_web_view.rb +21 -0
  45. data/lib/playwright_api/binding_call.rb +14 -5
  46. data/lib/playwright_api/browser.rb +22 -23
  47. data/lib/playwright_api/browser_context.rb +49 -35
  48. data/lib/playwright_api/browser_type.rb +24 -64
  49. data/lib/playwright_api/chromium_browser_context.rb +10 -8
  50. data/lib/playwright_api/console_message.rb +10 -6
  51. data/lib/playwright_api/dialog.rb +37 -6
  52. data/lib/playwright_api/download.rb +28 -11
  53. data/lib/playwright_api/element_handle.rb +107 -96
  54. data/lib/playwright_api/file_chooser.rb +18 -10
  55. data/lib/playwright_api/frame.rb +124 -117
  56. data/lib/playwright_api/js_handle.rb +20 -22
  57. data/lib/playwright_api/keyboard.rb +5 -5
  58. data/lib/playwright_api/page.rb +206 -148
  59. data/lib/playwright_api/playwright.rb +33 -45
  60. data/lib/playwright_api/request.rb +11 -12
  61. data/lib/playwright_api/response.rb +30 -16
  62. data/lib/playwright_api/route.rb +27 -5
  63. data/lib/playwright_api/selectors.rb +14 -10
  64. data/lib/playwright_api/web_socket.rb +10 -1
  65. data/lib/playwright_api/worker.rb +13 -13
  66. metadata +16 -7
  67. data/lib/playwright/input_type.rb +0 -19
  68. data/lib/playwright/input_types/mouse.rb +0 -4
  69. data/lib/playwright/input_types/touchscreen.rb +0 -4
@@ -1,5 +1,9 @@
1
1
  module Playwright
2
- define_input_type :AndroidInput do
2
+ define_api_implementation :AndroidInputImpl do
3
+ def initialize(channel)
4
+ @channel = channel
5
+ end
6
+
3
7
  def type(text)
4
8
  @channel.send_message_to_server('inputType', text: text)
5
9
  end
@@ -0,0 +1,18 @@
1
+ module Playwright
2
+ # Each Impl class include this module.
3
+ # Used for detecting whether the object is a XXXXImpl or not.
4
+ module ApiImplementation ; end
5
+
6
+ def self.define_api_implementation(class_name, &block)
7
+ klass = Class.new
8
+ klass.include(ApiImplementation)
9
+ klass.class_eval(&block) if block
10
+ if ::Playwright.const_defined?(class_name)
11
+ raise ArgumentError.new("Playwright::#{class_name} already exist. Choose another class name.")
12
+ end
13
+ ::Playwright.const_set(class_name, klass)
14
+ end
15
+ end
16
+
17
+ # load subclasses
18
+ Dir[File.join(__dir__, '*_impl.rb')].each { |f| require f }
@@ -16,12 +16,19 @@ module Playwright
16
16
  # @param method [String]
17
17
  # @param params [Hash]
18
18
  def send_message_to_server(method, params = {})
19
- result = @connection.send_message_to_server(@guid, method, params)
20
- if result.is_a?(Hash)
21
- _type, channel_owner = result.first
22
- channel_owner
23
- else
24
- nil
19
+ async_send_message_to_server(method, params).value!
20
+ end
21
+
22
+ # @param method [String]
23
+ # @param params [Hash]
24
+ def async_send_message_to_server(method, params = {})
25
+ @connection.async_send_message_to_server(@guid, method, params).then do |result|
26
+ if result.is_a?(Hash)
27
+ _type, channel_owner = result.first
28
+ channel_owner
29
+ else
30
+ nil
31
+ end
25
32
  end
26
33
  end
27
34
  end
@@ -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,8 +2,8 @@ module Playwright
2
2
  define_channel_owner :AndroidDevice do
3
3
  include Utils::PrepareBrowserContextOptions
4
4
 
5
- def after_initialize
6
- @input = InputTypes::AndroidInput.new(@channel)
5
+ private def after_initialize
6
+ @input = AndroidInputImpl.new(@channel)
7
7
  end
8
8
 
9
9
  attr_reader :input
@@ -104,17 +104,17 @@ module Playwright
104
104
  isMobile: nil,
105
105
  javaScriptEnabled: nil,
106
106
  locale: nil,
107
- logger: nil,
107
+ noViewport: nil,
108
108
  offline: nil,
109
109
  permissions: nil,
110
110
  proxy: nil,
111
- recordHar: nil,
112
- recordVideo: nil,
111
+ record_har_omit_content: nil,
112
+ record_har_path: nil,
113
+ record_video_dir: nil,
114
+ record_video_size: nil,
113
115
  storageState: nil,
114
116
  timezoneId: nil,
115
117
  userAgent: nil,
116
- videoSize: nil,
117
- videosPath: nil,
118
118
  viewport: nil,
119
119
  &block)
120
120
  params = {
@@ -131,17 +131,17 @@ module Playwright
131
131
  isMobile: isMobile,
132
132
  javaScriptEnabled: javaScriptEnabled,
133
133
  locale: locale,
134
- logger: logger,
134
+ noViewport: noViewport,
135
135
  offline: offline,
136
136
  permissions: permissions,
137
137
  proxy: proxy,
138
- recordHar: recordHar,
139
- 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,
140
142
  storageState: storageState,
141
143
  timezoneId: timezoneId,
142
144
  userAgent: userAgent,
143
- videoSize: videoSize,
144
- videosPath: videosPath,
145
145
  viewport: viewport,
146
146
  }.compact
147
147
  prepare_browser_context_options(params)
@@ -1,4 +1,7 @@
1
1
  module Playwright
2
2
  define_channel_owner :BindingCall do
3
+ def name
4
+ @initializer['name']
5
+ end
3
6
  end
4
7
  end
@@ -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
@@ -2,13 +2,21 @@ module Playwright
2
2
  # @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser_context.py
3
3
  define_channel_owner :BrowserContext do
4
4
  include Utils::Errors::SafeCloseError
5
- attr_writer :browser, :owner_page, :options
5
+ attr_accessor :browser
6
+ attr_writer :owner_page, :options
6
7
 
7
- def after_initialize
8
+ private def after_initialize
8
9
  @pages = Set.new
10
+ @routes = Set.new
11
+ @bindings = {}
12
+ @timeout_settings = TimeoutSettings.new
9
13
 
14
+ @channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
10
15
  @channel.once('close', ->(_) { on_close })
11
- @channel.on('page', ->(hash) { on_page(ChannelOwners::Page.from(hash['page']) )})
16
+ @channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
17
+ @channel.on('route', ->(params) {
18
+ on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
19
+ })
12
20
  end
13
21
 
14
22
  private def on_page(page)
@@ -17,6 +25,35 @@ module Playwright
17
25
  emit(Events::BrowserContext::Page, page)
18
26
  end
19
27
 
28
+ private def on_route(route, request)
29
+ # It is not desired to use PlaywrightApi.wrap directly.
30
+ # However it is a little difficult to define wrapper for `handler` parameter in generate_api.
31
+ # Just a workaround...
32
+ wrapped_route = PlaywrightApi.wrap(route)
33
+ wrapped_request = PlaywrightApi.wrap(request)
34
+
35
+ if @routes.none? { |handler_entry| handler_entry.handle(wrapped_route, wrapped_request) }
36
+ route.continue
37
+ end
38
+ end
39
+
40
+ private def on_binding(binding_call)
41
+ func = @binding[binding_call.name]
42
+ if func
43
+ binding_call.call(func)
44
+ end
45
+ end
46
+
47
+ def set_default_navigation_timeout(timeout)
48
+ @timeout_settings.default_navigation_timeout = timeout
49
+ @channel.send_message_to_server('setDefaultNavigationTimeoutNoReply', timeout: timeout)
50
+ end
51
+
52
+ def set_default_timeout(timeout)
53
+ @timeout_settings.default_timeout = timeout
54
+ @channel.send_message_to_server('setDefaultTimeoutNoReply', timeout: timeout)
55
+ end
56
+
20
57
  def pages
21
58
  @pages.to_a
22
59
  end
@@ -28,6 +65,111 @@ module Playwright
28
65
  ChannelOwners::Page.from(resp)
29
66
  end
30
67
 
68
+ def cookies(urls: nil)
69
+ target_urls =
70
+ if urls.nil?
71
+ []
72
+ elsif urls.is_a?(Enumerable)
73
+ urls
74
+ else
75
+ [urls]
76
+ end
77
+ @channel.send_message_to_server('cookies', urls: urls)
78
+ end
79
+
80
+ def add_cookies(cookies)
81
+ @channel.send_message_to_server('addCookies', cookies: cookies)
82
+ end
83
+
84
+ def clear_cookies
85
+ @channel.send_message_to_server('clearCookies')
86
+ end
87
+
88
+ def grant_permissions(permissions, origin: nil)
89
+ params = {
90
+ permissions: permissions,
91
+ origin: origin,
92
+ }.compact
93
+ @channel.send_message_to_server('grantPermissions', params)
94
+ end
95
+
96
+ def clear_permissions
97
+ @channel.send_message_to_server('clearPermissions')
98
+ end
99
+
100
+ def set_geolocation(geolocation)
101
+ @channel.send_message_to_server('setGeolocation', geolocation: geolocation)
102
+ end
103
+
104
+ def set_extra_http_headers(headers)
105
+ @channel.send_message_to_server('setExtraHTTPHeaders',
106
+ headers: HttpHeaders.new(headers).as_serialized)
107
+ end
108
+
109
+ def set_offline(offline)
110
+ @channel.send_message_to_server('setOffline', offline: offline)
111
+ end
112
+
113
+ def add_init_script(path: nil, script: nil)
114
+ source =
115
+ if path
116
+ File.read(path)
117
+ elsif script
118
+ script
119
+ else
120
+ raise ArgumentError.new('Either path or script parameter must be specified')
121
+ end
122
+
123
+ @channel.send_message_to_server('addInitScript', source: script)
124
+ nil
125
+ end
126
+
127
+ def expose_binding(name, callback, handle: nil)
128
+ if @pages.any? { |page| page.send(:has_bindings?, name) }
129
+ raise ArgumentError.new("Function \"#{name}\" has been already registered in one of the pages")
130
+ end
131
+ if @bindings.key?(name)
132
+ raise ArgumentError.new("Function \"#{name}\" has been already registered")
133
+ end
134
+ params = {
135
+ name: name,
136
+ needsHandle: handle,
137
+ }.compact
138
+ @bindings[name] = callback
139
+ @channel.send_message_to_server('exposeBinding', params)
140
+ end
141
+
142
+ def expose_function(name, callback)
143
+ expose_binding(name, ->(_source, *args) { callback.call(*args) }, )
144
+ end
145
+
146
+ def route(url, handler)
147
+ entry = RouteHandlerEntry.new(url, handler)
148
+ @routes << entry
149
+ if @routes.count >= 1
150
+ @channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: true)
151
+ end
152
+ end
153
+
154
+ def unroute(url, handler: nil)
155
+ @routes.reject! do |handler_entry|
156
+ handler_entry.same_value?(url: url, handler: handler)
157
+ end
158
+ if @routes.count == 0
159
+ @channel.send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
160
+ end
161
+ end
162
+
163
+ def expect_event(event, predicate: nil, timeout: nil, &block)
164
+ wait_helper = WaitHelper.new
165
+ wait_helper.reject_on_timeout(timeout || @timeout_settings.timeout, "Timeout while waiting for event \"#{event}\"")
166
+ wait_helper.wait_for_event(self, event, predicate: predicate)
167
+
168
+ block&.call
169
+
170
+ wait_helper.promise.value!
171
+ end
172
+
31
173
  private def on_close
32
174
  @closed_or_closing = true
33
175
  @browser&.send(:remove_context, self)
@@ -43,6 +185,18 @@ module Playwright
43
185
  raise unless safe_close_error?(err)
44
186
  end
45
187
 
188
+ def pause
189
+ @channel.send_message_to_server('pause')
190
+ end
191
+
192
+ def expect_page(predicate: nil, timeout: nil)
193
+ params = {
194
+ predicate: predicate,
195
+ timeout: timeout,
196
+ }.compact
197
+ expect_event(Events::BrowserContext::Page, params)
198
+ end
199
+
46
200
  # called from Page#on_close with send(:remove_page, page), so keep private
47
201
  private def remove_page(page)
48
202
  @pages.delete(page)
@@ -0,0 +1,28 @@
1
+ module Playwright
2
+ define_channel_owner :Dialog do
3
+ def type
4
+ @initializer['type']
5
+ end
6
+
7
+ def message
8
+ @initializer['message']
9
+ end
10
+
11
+ def default_value
12
+ @initializer['defaultValue']
13
+ end
14
+
15
+ def accept(promptText: nil)
16
+ accept_async(prompt_text: promptText).value!
17
+ end
18
+
19
+ def accept_async(promptText: nil)
20
+ params = { promptText: promptText }.compact
21
+ @channel.async_send_message_to_server('accept', params)
22
+ end
23
+
24
+ def dismiss
25
+ @channel.async_send_message_to_server('dismiss')
26
+ end
27
+ end
28
+ 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