cuprite 0.14.3 → 0.15.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6480f3033eff59cc4f7d261e47c37ae7169ef8dd806c9b1f471d4d59be5b5a7
4
- data.tar.gz: 4d35f4b5df0457b7ea51842738e66c1b6aecc2d1753bdec5d7dbf82d28273ecd
3
+ metadata.gz: 78b7dde58d02147e2985473da0a7527d338ff086e4a4aaf0fd9302e5faf3ee11
4
+ data.tar.gz: 777726c6161975950df923a305b0bdb9da54b5531b7a5339ed0d4beaf264beb6
5
5
  SHA512:
6
- metadata.gz: c347f3f5555138a6ae5660de778ec13d9e7686007ffdf9d635b826e6fa13a42520cb137693ee0142395b7cb00efa3a5939c9ccfc6fa75411397310f0593fef33
7
- data.tar.gz: 82dd53121faab3a9f700928873d13dc42c33aae6a6065b88efcbadf02094356226ef8d72fa2d3ccfaf460a89ecfaf53950db49a57e6d9222ef9cf968eea7d6d2
6
+ metadata.gz: 04e88a47d9d2d2df68ad11dca8224f6d24001340b1743f538e6fdb64e818381037da7987b9db25284336b469c986d9d9e883192743749c4c6cad6c43adc160a1
7
+ data.tar.gz: a059dae9790af13c8a56999d6d76d5920e863e217b346a721a4051f0cc786e295a35c0e574c00e425b87e2d0c7a8b140c991183ab3246d1678566318745c9ecf
data/README.md CHANGED
@@ -4,9 +4,7 @@ Cuprite is a pure Ruby driver (read as _no_ Selenium/WebDriver/ChromeDriver
4
4
  dependency) for [Capybara](https://github.com/teamcapybara/capybara). It allows
5
5
  you to run Capybara tests on a headless Chrome or Chromium. Under the hood it
6
6
  uses [Ferrum](https://github.com/rubycdp/ferrum#index) which is high-level API
7
- to the browser by CDP protocol. The design of the driver is as close to
8
- [Poltergeist](https://github.com/teampoltergeist/poltergeist) as possible though
9
- it's not a goal.
7
+ to the browser by CDP protocol.
10
8
 
11
9
 
12
10
  ## Install
@@ -43,8 +41,7 @@ browser = page.driver.browser
43
41
  browser.mouse.move(x: 123, y: 456).down.up
44
42
  ```
45
43
 
46
- If you already have tests on Poltergeist then it should simply work, for
47
- Selenium you better check your code for `manage` calls because it works
44
+ For Selenium you better check your code for `manage` calls because it works
48
45
  differently in Cuprite, see the documentation below.
49
46
 
50
47
 
@@ -64,8 +61,8 @@ end
64
61
  `Cuprite`-specific options are:
65
62
 
66
63
  * options `Hash`
67
- * `:url_blacklist` (Array) - array of strings to match against requested URLs
68
- * `:url_whitelist` (Array) - array of strings to match against requested URLs
64
+ * `:url_blacklist` (Array) - array of regexes to match against requested URLs
65
+ * `:url_whitelist` (Array) - array of regexes to match against requested URLs
69
66
 
70
67
 
71
68
  ## Debugging
@@ -183,6 +180,9 @@ Besides capybara screenshot method you can get image as Base64:
183
180
  ## Authorization
184
181
 
185
182
  * `page.driver.basic_authorize(user, password)`
183
+
184
+ ## Proxy
185
+
186
186
  * `page.driver.set_proxy(ip, port, type, user, password)`
187
187
 
188
188
 
@@ -192,14 +192,14 @@ Cuprite supports URL blacklisting, which allows you to prevent scripts from
192
192
  running on designated domains:
193
193
 
194
194
  ```ruby
195
- page.driver.browser.url_blacklist = ["http://www.example.com"]
195
+ page.driver.browser.url_blacklist = %r{http://www.example.com}
196
196
  ```
197
197
 
198
198
  and also URL whitelisting, which allows scripts to only run on designated
199
199
  domains:
200
200
 
201
201
  ```ruby
202
- page.driver.browser.url_whitelist = ["http://www.example.com"]
202
+ page.driver.browser.url_whitelist = %r{http://www.example.com}
203
203
  ```
204
204
 
205
205
  If you are experiencing slower run times, consider creating a URL whitelist of
@@ -11,48 +11,65 @@ module Capybara
11
11
  find_modal accept_confirm dismiss_confirm accept_prompt
12
12
  dismiss_prompt reset_modals] => :page
13
13
 
14
- attr_reader :url_blacklist, :url_whitelist
15
-
16
14
  def initialize(options = nil)
17
- options ||= {}
18
- @client = nil
19
- self.url_blacklist = options[:url_blacklist]
20
- self.url_whitelist = options[:url_whitelist]
21
-
22
15
  super
23
- @page = false
16
+
17
+ @options.url_blacklist = prepare_wildcards(options&.dig(:url_blacklist))
18
+ @options.url_whitelist = prepare_wildcards(options&.dig(:url_whitelist))
19
+
20
+ @page = nil
24
21
  end
25
22
 
26
- def timeout=(value)
23
+ def command(...)
27
24
  super
28
- @page.timeout = value unless @page.nil?
25
+ rescue Ferrum::DeadBrowserError
26
+ restart
27
+ raise
29
28
  end
30
29
 
31
30
  def page
32
- raise Ferrum::NoSuchPageError if @page.nil?
31
+ raise Ferrum::NoSuchPageError if @page&.closed?
33
32
 
34
33
  @page ||= attach_page
35
34
  end
36
35
 
37
36
  def reset
38
37
  super
39
- @page = attach_page
38
+ @options.reset_window_size
39
+ @page = nil
40
40
  end
41
41
 
42
42
  def quit
43
43
  super
44
- @page = false
44
+ @page = nil
45
45
  end
46
46
 
47
+ def resize(**options)
48
+ @options.window_size = [options[:width], options[:height]]
49
+ super
50
+ end
51
+
52
+ def url_whitelist
53
+ @options.url_whitelist
54
+ end
55
+ alias url_allowlist url_whitelist
56
+
47
57
  def url_whitelist=(patterns)
48
- @url_whitelist = prepare_wildcards(patterns)
49
- page.network.intercept if @client && !@url_whitelist.empty?
58
+ @options.url_whitelist = prepare_wildcards(patterns)
59
+ page.network.whitelist = @options.url_whitelist if @client && @options.url_whitelist.any?
60
+ end
61
+ alias url_allowlist= url_whitelist=
62
+
63
+ def url_blacklist
64
+ @options.url_blacklist
50
65
  end
66
+ alias url_blocklist url_blacklist
51
67
 
52
68
  def url_blacklist=(patterns)
53
- @url_blacklist = prepare_wildcards(patterns)
54
- page.network.intercept if @client && !@url_blacklist.empty?
69
+ @options.url_blacklist = prepare_wildcards(patterns)
70
+ page.network.blacklist = @options.url_blacklist if @client && @options.url_blacklist.any?
55
71
  end
72
+ alias url_blocklist= url_blacklist=
56
73
 
57
74
  def visit(*args)
58
75
  goto(*args)
@@ -105,8 +122,13 @@ module Capybara
105
122
  target = targets[target_id]
106
123
  raise Ferrum::NoSuchPageError unless target
107
124
 
108
- @page = nil if @page.target_id == target.id
125
+ @page = ClosedPage.new if @page.target_id == target.id
109
126
  target.page.close
127
+ targets.delete(target_id) # page.close is async, delete target asap
128
+ end
129
+
130
+ def active_element
131
+ evaluate("document.activeElement")
110
132
  end
111
133
 
112
134
  def browser_error
@@ -117,24 +139,26 @@ module Capybara
117
139
  raise NotImplementedError
118
140
  end
119
141
 
120
- def drag(node, other)
142
+ def drag(node, other, steps, delay = nil)
121
143
  x1, y1 = node.find_position
122
144
  x2, y2 = other.find_position
123
145
 
124
146
  mouse.move(x: x1, y: y1)
125
147
  mouse.down
126
- mouse.move(x: x2, y: y2)
148
+ sleep delay if delay
149
+ mouse.move(x: x2, y: y2, steps: steps)
127
150
  mouse.up
128
151
  end
129
152
 
130
- def drag_by(node, x, y)
153
+ def drag_by(node, x, y, steps, delay = nil)
131
154
  x1, y1 = node.find_position
132
155
  x2 = x1 + x
133
156
  y2 = y1 + y
134
157
 
135
158
  mouse.move(x: x1, y: y1)
136
159
  mouse.down
137
- mouse.move(x: x2, y: y2)
160
+ sleep delay if delay
161
+ mouse.move(x: x2, y: y2, steps: steps)
138
162
  mouse.up
139
163
  end
140
164
 
@@ -199,24 +223,31 @@ module Capybara
199
223
  raise
200
224
  end
201
225
 
202
- def prepare_wildcards(wc)
203
- Array(wc).map do |wildcard|
204
- if wildcard.is_a?(Regexp)
205
- wildcard
226
+ def prepare_wildcards(patterns)
227
+ string_passed = false
228
+
229
+ Array(patterns).map do |pattern|
230
+ if pattern.is_a?(Regexp)
231
+ pattern
206
232
  else
207
- wildcard = wildcard.gsub("*", ".*")
208
- Regexp.new(wildcard, Regexp::IGNORECASE)
233
+ string_passed = true
234
+ pattern = pattern.gsub("*", ".*")
235
+ Regexp.new(pattern, Regexp::IGNORECASE)
209
236
  end
210
237
  end
238
+ ensure
239
+ if string_passed
240
+ warn "Passing strings to blacklist/whitelist is deprecated, pass regexp at #{caller(4..4).first}"
241
+ end
211
242
  end
212
243
 
213
244
  def attach_page(target_id = nil)
214
245
  target = targets[target_id] if target_id
215
246
  target ||= default_context.default_target
216
- return target.page if target.attached?
247
+ return target.page if target.connected?
217
248
 
218
249
  target.maybe_sleep_if_new_window
219
- target.page = Page.new(target.id, self)
250
+ target.page = Page.new(target.client, context_id: target.context_id, target_id: target.id)
220
251
  target.page
221
252
  end
222
253
  end
@@ -3,9 +3,9 @@
3
3
  require "uri"
4
4
  require "forwardable"
5
5
 
6
+ # rubocop:disable Metrics/ClassLength
6
7
  module Capybara
7
8
  module Cuprite
8
- # rubocop:disable Metrics/ClassLength
9
9
  class Driver < Capybara::Driver::Base
10
10
  DEFAULT_MAXIMIZE_SCREEN_SIZE = [1366, 768].freeze
11
11
  EXTENSION = File.expand_path("javascripts/index.js", __dir__)
@@ -14,7 +14,8 @@ module Capybara
14
14
 
15
15
  delegate %i[restart quit status_code timeout timeout= current_url title body
16
16
  window_handles close_window switch_to_window within_window window_handle
17
- back forward refresh wait_for_reload] => :browser
17
+ back forward refresh wait_for_reload viewport_size device_pixel_ratio] => :browser
18
+ delegate %i[send_keys] => :active_element
18
19
  alias html body
19
20
  alias current_window_handle window_handle
20
21
  alias go_back back
@@ -32,10 +33,13 @@ module Capybara
32
33
 
33
34
  @screen_size = @options.delete(:screen_size)
34
35
  @screen_size ||= DEFAULT_MAXIMIZE_SCREEN_SIZE
36
+ @options[:save_path] ||= File.expand_path(Capybara.save_path) if Capybara.save_path
35
37
 
36
- @options[:save_path] = File.expand_path(Capybara.save_path) if Capybara.save_path
37
-
38
- ENV["FERRUM_DEBUG"] = "true" if ENV["CUPRITE_DEBUG"]
38
+ # It's set for debug() to make devtools tab open correctly.
39
+ @options[:browser_options] ||= {}
40
+ unless @options[:browser_options][:"remote-allow-origins"]
41
+ @options[:browser_options].merge!("remote-allow-origins": "*")
42
+ end
39
43
 
40
44
  super()
41
45
  end
@@ -65,6 +69,10 @@ module Capybara
65
69
  evaluate_script("document.title")
66
70
  end
67
71
 
72
+ def active_element
73
+ Node.new(self, browser.active_element)
74
+ end
75
+
68
76
  def find_xpath(selector)
69
77
  find(:xpath, selector)
70
78
  end
@@ -110,7 +118,7 @@ module Capybara
110
118
  def open_new_window
111
119
  target = browser.default_context.create_target
112
120
  target.maybe_sleep_if_new_window
113
- target.page = Page.new(target.id, browser)
121
+ target.page = Page.new(target.client, context_id: target.context_id, target_id: target.id)
114
122
  target.page
115
123
  end
116
124
 
@@ -206,16 +214,7 @@ module Capybara
206
214
  end
207
215
 
208
216
  def set_proxy(host, port, user = nil, password = nil, bypass = nil)
209
- browser_options = @options.fetch(:browser_options, {})
210
- browser_options = browser_options.merge("proxy-server" => "#{host}:#{port}")
211
- browser_options = browser_options.merge("proxy-bypass-list" => bypass) if bypass
212
- @options[:browser_options] = browser_options
213
-
214
- return unless user && password
215
-
216
- browser.network.authorize(user: user, password: password, type: :proxy) do |request, _index, _total|
217
- request.continue
218
- end
217
+ @options.merge!(proxy: { host: host, port: port, user: user, password: password, bypass: bypass })
219
218
  end
220
219
 
221
220
  def headers
@@ -275,7 +274,12 @@ module Capybara
275
274
  alias authorize basic_authorize
276
275
 
277
276
  def debug_url
278
- "http://#{browser.process.host}:#{browser.process.port}"
277
+ response = JSON.parse(Net::HTTP.get(URI(build_remote_debug_url(path: "/json"))))
278
+
279
+ devtools_frontend_path = response[0]&.[]("devtoolsFrontendUrl")
280
+ raise "Could not generate debug url for remote debugging session" unless devtools_frontend_path
281
+
282
+ build_remote_debug_url(path: devtools_frontend_path)
279
283
  end
280
284
 
281
285
  def debug(binding = nil)
@@ -373,6 +377,10 @@ module Capybara
373
377
 
374
378
  private
375
379
 
380
+ def build_remote_debug_url(path:)
381
+ "http://#{browser.process.host}:#{browser.process.port}#{path}"
382
+ end
383
+
376
384
  def default_domain
377
385
  if @started
378
386
  URI.parse(browser.current_url).host
@@ -423,6 +431,6 @@ module Capybara
423
431
  options[:format].to_s == "pdf"
424
432
  end
425
433
  end
426
- # rubocop:enable Metrics/ClassLength
427
434
  end
428
435
  end
436
+ # rubocop:enable Metrics/ClassLength
@@ -84,7 +84,6 @@ class Cuprite {
84
84
  return true;
85
85
  }
86
86
 
87
-
88
87
  isDisabled(node) {
89
88
  let xpath = "parent::optgroup[@disabled] | \
90
89
  ancestor::select[@disabled] | \
@@ -151,7 +150,7 @@ class Cuprite {
151
150
  // call the following functions in order, if one returns false (preventDefault),
152
151
  // stop the call chain
153
152
  [
154
- () => this.keyupdowned(node, "keydown", keyCode),
153
+ () => this.keyupdowned(node, "keydown", char, keyCode),
155
154
  () => this.keypressed(node, false, false, false, false, char.charCodeAt(0), char.charCodeAt(0)),
156
155
  () => {
157
156
  this.setValue(node, node.value + char)
@@ -159,7 +158,7 @@ class Cuprite {
159
158
  }
160
159
  ].some(fn => fn())
161
160
 
162
- this.keyupdowned(node, "keyup", keyCode);
161
+ this.keyupdowned(node, "keyup", char, keyCode);
163
162
  }
164
163
  }
165
164
 
@@ -180,19 +179,22 @@ class Cuprite {
180
179
  }
181
180
 
182
181
  input(node) {
183
- let event = document.createEvent("HTMLEvents");
184
- event.initEvent("input", true, false);
182
+ let event = new InputEvent("input", { inputType: "insertText", bubbles: true, cancelable: false });
185
183
  node.dispatchEvent(event);
186
184
  }
187
185
 
188
186
  /**
189
187
  * @return {boolean} false when an event handler called preventDefault()
190
188
  */
191
- keyupdowned(node, eventName, keyCode) {
192
- let event = document.createEvent("UIEvents");
193
- event.initEvent(eventName, true, true);
194
- event.keyCode = keyCode;
195
- event.charCode = 0;
189
+ keyupdowned(node, eventName, char, keyCode) {
190
+ let event = new KeyboardEvent(
191
+ eventName, {
192
+ bubbles: true,
193
+ cancelable: true,
194
+ key: char,
195
+ keyCode: keyCode
196
+ }
197
+ );
196
198
  return !node.dispatchEvent(event);
197
199
  }
198
200
 
@@ -200,15 +202,18 @@ class Cuprite {
200
202
  * @return {boolean} false when an event handler called preventDefault()
201
203
  */
202
204
  keypressed(node, altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {
203
- event = document.createEvent("UIEvents");
204
- event.initEvent("keypress", true, true);
205
- event.window = window;
206
- event.altKey = altKey;
207
- event.ctrlKey = ctrlKey;
208
- event.shiftKey = shiftKey;
209
- event.metaKey = metaKey;
210
- event.keyCode = keyCode;
211
- event.charCode = charCode;
205
+ let event = new KeyboardEvent(
206
+ "keypress", {
207
+ bubbles: true,
208
+ cancelable: true,
209
+ altKey: altKey,
210
+ ctrlKey: ctrlKey,
211
+ shiftKey: shiftKey,
212
+ metaKey: metaKey,
213
+ keyCode: keyCode,
214
+ charCode: charCode
215
+ }
216
+ );
212
217
  return !node.dispatchEvent(event);
213
218
  }
214
219
 
@@ -338,10 +343,24 @@ class Cuprite {
338
343
 
339
344
  _isInViewport(node) {
340
345
  let rect = node.getBoundingClientRect();
341
- return rect.top >= 0 &&
342
- rect.left >= 0 &&
343
- rect.bottom <= window.innerHeight &&
344
- rect.right <= window.innerWidth;
346
+
347
+ let inViewport = rect.top >= 0 &&
348
+ rect.left >= 0 &&
349
+ rect.bottom <= window.innerHeight &&
350
+ rect.right <= window.innerWidth;
351
+
352
+ if (inViewport) {
353
+ // check if obscured by another element
354
+ let x = rect.width/2;
355
+ let y = rect.height/2 ;
356
+
357
+ let px = rect.left + x,
358
+ py = rect.top + y,
359
+ e = document.elementFromPoint(px, py);
360
+ return node == e;
361
+ }
362
+
363
+ return false;
345
364
  }
346
365
 
347
366
  select(node, value) {
@@ -350,12 +369,13 @@ class Cuprite {
350
369
  } else if (value == false && !node.parentNode.multiple) {
351
370
  return false;
352
371
  } else {
353
- this.trigger(node.parentNode, "focus");
372
+ let parentNode = node.parentNode;
373
+ this.trigger(parentNode, "focus");
354
374
 
355
375
  node.selected = value;
356
376
  this.changed(node);
357
377
 
358
- this.trigger(node.parentNode, "blur");
378
+ this.trigger(parentNode, "blur");
359
379
  return true;
360
380
  }
361
381
  }
@@ -159,12 +159,16 @@ module Capybara
159
159
  command(:hover)
160
160
  end
161
161
 
162
- def drag_to(other)
163
- command(:drag, other.node)
162
+ def drag_to(other, **options)
163
+ options[:steps] ||= 1
164
+
165
+ command(:drag, other.node, options[:steps], options[:delay])
164
166
  end
165
167
 
166
- def drag_by(x, y)
167
- command(:drag_by, x, y)
168
+ def drag_by(x, y, **options)
169
+ options[:steps] ||= 1
170
+
171
+ command(:drag_by, x, y, options[:steps], options[:delay])
168
172
  end
169
173
 
170
174
  def trigger(event)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ferrum
4
+ class Browser
5
+ class Options
6
+ attr_writer :window_size
7
+ attr_accessor :url_blacklist, :url_whitelist
8
+
9
+ def reset_window_size
10
+ @window_size = @options[:window_size]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -4,6 +4,12 @@ require "forwardable"
4
4
 
5
5
  module Capybara
6
6
  module Cuprite
7
+ class ClosedPage
8
+ def closed?
9
+ true
10
+ end
11
+ end
12
+
7
13
  class Page < Ferrum::Page
8
14
  MODAL_WAIT = ENV.fetch("CUPRITE_MODAL_WAIT", 0.05).to_f
9
15
  TRIGGER_CLICK_WAIT = ENV.fetch("CUPRITE_TRIGGER_CLICK_WAIT", 0.1).to_f
@@ -13,10 +19,11 @@ module Capybara
13
19
  current_url current_title body execution_id execution_id!
14
20
  evaluate evaluate_on evaluate_async execute] => :active_frame
15
21
 
16
- def initialize(*args)
22
+ def initialize(...)
17
23
  @frame_stack = []
18
24
  @accept_modal = []
19
25
  @modal_messages = []
26
+ @modal_response = nil
20
27
  super
21
28
  end
22
29
 
@@ -69,17 +76,17 @@ module Capybara
69
76
 
70
77
  def find_modal(options)
71
78
  start = Ferrum::Utils::ElapsedTime.monotonic_time
72
- timeout = options.fetch(:wait, browser.timeout)
73
79
  expect_text = options[:text]
74
80
  expect_regexp = expect_text.is_a?(Regexp) ? expect_text : Regexp.escape(expect_text.to_s)
75
81
  not_found_msg = "Unable to find modal dialog"
76
82
  not_found_msg += " with #{expect_text}" if expect_text
83
+ wait = options.fetch(:wait, timeout)
77
84
 
78
85
  begin
79
86
  modal_text = @modal_messages.shift
80
87
  raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp))
81
88
  rescue Capybara::ModalNotFound => e
82
- raise e, not_found_msg if Ferrum::Utils::ElapsedTime.timeout?(start, timeout)
89
+ raise e, not_found_msg if Ferrum::Utils::ElapsedTime.timeout?(start, wait)
83
90
 
84
91
  sleep(MODAL_WAIT)
85
92
  retry
@@ -128,37 +135,22 @@ module Capybara
128
135
  active_frame.current_title
129
136
  end
130
137
 
138
+ def closed?
139
+ false
140
+ end
141
+
131
142
  private
132
143
 
133
- # rubocop:disable Metrics/CyclomaticComplexity
134
- # rubocop:disable Metrics/PerceivedComplexity
135
- # rubocop:disable Style/GuardClause
136
144
  def prepare_page
137
145
  super
138
146
 
139
- network.intercept if !Array(@browser.url_whitelist).empty? ||
140
- !Array(@browser.url_blacklist).empty?
141
-
142
- on(:request) do |request, index, total|
143
- if @browser.url_blacklist && !@browser.url_blacklist.empty?
144
- if @browser.url_blacklist.any? { |r| request.match?(r) }
145
- request.abort and next
146
- else
147
- request.continue and next
148
- end
149
- elsif @browser.url_whitelist && !@browser.url_whitelist.empty?
150
- if @browser.url_whitelist.any? { |r| request.match?(r) }
151
- request.continue and next
152
- else
153
- request.abort and next
154
- end
155
- elsif index + 1 < total
156
- # There are other callbacks that may handle this request
157
- next
158
- else
159
- # If there are no callbacks then just continue
160
- request.continue
161
- end
147
+ width, height = @options.window_size
148
+ resize(width: width, height: height)
149
+
150
+ if @options.url_blacklist.any?
151
+ network.blacklist = @options.url_blacklist
152
+ elsif @options.url_whitelist.any?
153
+ network.whitelist = @options.url_whitelist
162
154
  end
163
155
 
164
156
  on("Page.javascriptDialogOpening") do |params|
@@ -181,9 +173,6 @@ module Capybara
181
173
  command("Page.handleJavaScriptDialog", **options)
182
174
  end
183
175
  end
184
- # rubocop:enable Metrics/CyclomaticComplexity
185
- # rubocop:enable Metrics/PerceivedComplexity
186
- # rubocop:enable Style/GuardClause
187
176
 
188
177
  def find_position(node, **options)
189
178
  node.find_position(**options)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Capybara
4
4
  module Cuprite
5
- VERSION = "0.14.3"
5
+ VERSION = "0.15.1"
6
6
  end
7
7
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ENV["FERRUM_DEBUG"] = "true" if ENV["CUPRITE_DEBUG"]
4
+
3
5
  require "ferrum"
4
6
  require "capybara"
5
7
  require "capybara/cuprite/driver"
6
8
  require "capybara/cuprite/browser"
7
9
  require "capybara/cuprite/page"
10
+ require "capybara/cuprite/options"
8
11
  require "capybara/cuprite/node"
9
12
  require "capybara/cuprite/errors"
10
13
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuprite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.3
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Vorotilin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-12 00:00:00.000000000 Z
11
+ date: 2024-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -30,140 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.13.0
33
+ version: 0.15.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.13.0
41
- - !ruby/object:Gem::Dependency
42
- name: byebug
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '11.1'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '11.1'
55
- - !ruby/object:Gem::Dependency
56
- name: chunky_png
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.4'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.4'
69
- - !ruby/object:Gem::Dependency
70
- name: image_size
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '3.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '3.0'
83
- - !ruby/object:Gem::Dependency
84
- name: launchy
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '2.5'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '2.5'
97
- - !ruby/object:Gem::Dependency
98
- name: pdf-reader
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '2.5'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '2.5'
111
- - !ruby/object:Gem::Dependency
112
- name: puma
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '4.3'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '4.3'
125
- - !ruby/object:Gem::Dependency
126
- name: rake
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '13.0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '13.0'
139
- - !ruby/object:Gem::Dependency
140
- name: rspec
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '3.10'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '3.10'
153
- - !ruby/object:Gem::Dependency
154
- name: sinatra
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: '2.1'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '2.1'
40
+ version: 0.15.0
167
41
  description: Cuprite is a driver for Capybara that allows you to run your tests on
168
42
  a headless Chrome browser
169
43
  email:
@@ -181,6 +55,7 @@ files:
181
55
  - lib/capybara/cuprite/errors.rb
182
56
  - lib/capybara/cuprite/javascripts/index.js
183
57
  - lib/capybara/cuprite/node.rb
58
+ - lib/capybara/cuprite/options.rb
184
59
  - lib/capybara/cuprite/page.rb
185
60
  - lib/capybara/cuprite/version.rb
186
61
  homepage: https://github.com/rubycdp/cuprite
@@ -189,7 +64,7 @@ licenses:
189
64
  metadata:
190
65
  homepage_uri: https://cuprite.rubycdp.com/
191
66
  bug_tracker_uri: https://github.com/rubycdp/cuprite/issues
192
- documentation_uri: https://github.com/rubycdp/cuprite/blob/master/README.md
67
+ documentation_uri: https://github.com/rubycdp/cuprite/blob/main/README.md
193
68
  source_code_uri: https://github.com/rubycdp/cuprite
194
69
  rubygems_mfa_required: 'true'
195
70
  post_install_message:
@@ -200,14 +75,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
75
  requirements:
201
76
  - - ">="
202
77
  - !ruby/object:Gem::Version
203
- version: 2.6.0
78
+ version: 2.7.0
204
79
  required_rubygems_version: !ruby/object:Gem::Requirement
205
80
  requirements:
206
81
  - - ">="
207
82
  - !ruby/object:Gem::Version
208
83
  version: '0'
209
84
  requirements: []
210
- rubygems_version: 3.3.7
85
+ rubygems_version: 3.5.11
211
86
  signing_key:
212
87
  specification_version: 4
213
88
  summary: Headless Chrome driver for Capybara