apparition 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 350a10ffb794579fb942f37a1739bf104b0230bd831945cbc22a20e2273927fd
4
- data.tar.gz: e0bbdc5f79d03fcdedabd5db29ff990ee57801087d9c33ef98e85f9de833be8d
3
+ metadata.gz: fbed62503718fca5fe4664a248445c8b222073b352e2afd1422eeb85cf7bbf40
4
+ data.tar.gz: 508d1a1883ccc043b26a617ce84bbfb30ed1a72eee407965b10a50a12e2a3a6d
5
5
  SHA512:
6
- metadata.gz: 313247fbbaccd8197d36ccd68adede1a33c944f46a5b30dce143606d4cc00bc61a3aab99ba35820dc6e2e3cbb7c09432084f221a36fee2f355fbd7d59639bb6f
7
- data.tar.gz: 73f91c766ab2bc02f2a58b07c95cce2a01bc71dff6ca8f6eb3374b36b5a8efbc73c95d26f48766e00d3fbd7f49003765b293af8725028afa64d798f2c5ebddb2
6
+ metadata.gz: 90fccfe118998a00935b4ff9c6637747a73ea917927e15db3bc29b6a02aa9ecd763bde7d8f65043b377e33c7357ff8fbe38f8064970e7e79de5aeac37bb6bcf2
7
+ data.tar.gz: 3e2220019a00bd43c8125c7ab6d75f6fb7b8b4430e57e28fe22dea73012b2b8c61fea655e1a455cb1dfa49d55cafadbf09ffc80621f1e43745c0791add88a5e1
data/README.md CHANGED
@@ -82,6 +82,29 @@ same as for `save_screenshot`.
82
82
  Sometimes its desirable to click a very specific area of the screen. You can accomplish this with
83
83
  `page.driver.click(x, y)`, where x and y are the screen coordinates.
84
84
 
85
+ ### Remote debugging (not yet implemented) ###
86
+
87
+ If you use the `:inspector => true` option (see below), remote debugging
88
+ will be enabled.
89
+
90
+ When this option is enabled, you can insert `page.driver.debug` into
91
+ your tests to pause the test and launch a browser which gives you the
92
+ WebKit inspector to view your test run with.
93
+
94
+ You can register this debugger driver with a different name and set it
95
+ as the current javascript driver. By example, in your helper file:
96
+
97
+ ```ruby
98
+ Capybara.register_driver :apparition_debug do |app|
99
+ Capybara::Apparition::Driver.new(app, :inspector => true)
100
+ end
101
+ # Capybara.javascript_driver = :apparition
102
+ Capybara.javascript_driver = :apparition_debug
103
+ ```
104
+
105
+ [Read more
106
+ here](https://www.jonathanleighton.com/articles/2012/poltergeist-0-6-0/)
107
+
85
108
  ### Manipulating request headers ###
86
109
 
87
110
  You can manipulate HTTP request headers with these methods:
@@ -152,7 +152,7 @@ module Capybara::Apparition
152
152
  current_page.command('Network.clearBrowserCache')
153
153
  end
154
154
 
155
- def command(name, params = {})
155
+ def command(name, **params)
156
156
  result = client.send_cmd(name, params).result
157
157
  log result
158
158
 
@@ -19,7 +19,7 @@ module Capybara::Apparition
19
19
  def set_cookie(cookie)
20
20
  cookie[:expires] = cookie[:expires].to_i if cookie[:expires]
21
21
 
22
- current_page.command('Network.setCookie', cookie)
22
+ current_page.command('Network.setCookie', **cookie)
23
23
  end
24
24
 
25
25
  def remove_cookie(name)
@@ -67,7 +67,13 @@ module Capybara::Apparition
67
67
  end
68
68
 
69
69
  sessions.each do |(target_id, session)|
70
- new_page = Page.create(@browser, session, target_id, opener.browser_context_id, page_options).inherit(opener)
70
+ new_page = Page.create(
71
+ @browser,
72
+ session,
73
+ target_id,
74
+ opener.browser_context_id,
75
+ **page_options
76
+ ).inherit(opener)
71
77
  @pages[target_id] = new_page
72
78
  end
73
79
  end
@@ -22,7 +22,7 @@ module Capybara::Apparition
22
22
  end
23
23
 
24
24
  def async_command(name, **params)
25
- send_cmd(name, params).discard_result
25
+ send_cmd(name, **params).discard_result
26
26
  end
27
27
 
28
28
  def async_commands(*names)
@@ -216,7 +216,7 @@ module Capybara::Apparition
216
216
  end
217
217
 
218
218
  def add_header(name, value, options = {})
219
- browser.add_header({ name => value }, { permanent: true }.merge(options))
219
+ browser.add_header({ name => value }, **{ permanent: true }.merge(options))
220
220
  end
221
221
  alias_method :header, :add_header
222
222
 
@@ -295,7 +295,7 @@ module Capybara::Apparition
295
295
  begin
296
296
  input = read.read_nonblock(80) # clear out the read buffer
297
297
  puts unless input&.end_with?("\n")
298
- rescue EOFError, IO::WaitReadable # rubocop:disable Lint/HandleExceptions
298
+ rescue EOFError, IO::WaitReadable # rubocop:disable Lint/SuppressedException
299
299
  # Ignore problems reading from STDIN.
300
300
  end
301
301
  end
@@ -208,7 +208,7 @@ module Capybara::Apparition
208
208
  puts "Calling handler for #{event_name}" if ENV['DEBUG'] == 'V'
209
209
  # TODO: Update this to use transform_keys when we dump Ruby 2.4
210
210
  # handler.call(event['params'].transform_keys(&method(:snake_sym)))
211
- handler.call(event['params'].each_with_object({}) { |(k, v), hash| hash[snake_sym(k)] = v })
211
+ handler.call(**event['params'].each_with_object({}) { |(k, v), hash| hash[snake_sym(k)] = v })
212
212
  end
213
213
  end
214
214
 
@@ -226,7 +226,7 @@ module Capybara::Apparition
226
226
  @listener = Thread.new do
227
227
  begin
228
228
  listen
229
- rescue EOFError # rubocop:disable Lint/HandleExceptions
229
+ rescue EOFError # rubocop:disable Lint/SuppressedException
230
230
  end
231
231
  end
232
232
  # @listener.abort_on_exception = true
@@ -7,8 +7,8 @@ module Capybara::Apparition
7
7
  class Launcher
8
8
  KILL_TIMEOUT = 5
9
9
 
10
- def self.start(*args)
11
- new(*args).tap(&:start)
10
+ def self.start(*args, **options)
11
+ new(*args, **options).tap(&:start)
12
12
  end
13
13
 
14
14
  def self.process_killer(pid)
@@ -29,7 +29,7 @@ module Capybara::Apparition
29
29
  break
30
30
  end
31
31
  end
32
- rescue Errno::ESRCH, Errno::ECHILD # rubocop:disable Lint/HandleExceptions
32
+ rescue Errno::ESRCH, Errno::ECHILD # rubocop:disable Lint/SuppressedException
33
33
  end
34
34
  end
35
35
  end
@@ -132,8 +132,10 @@ module Capybara::Apparition
132
132
  set_datetime_local(value)
133
133
  when 'color'
134
134
  set_color(value)
135
+ when 'range'
136
+ set_range(value)
135
137
  else
136
- set_text(value.to_s, { delay: 0 }.merge(options))
138
+ set_text(value.to_s, **{ delay: 0 }.merge(options))
137
139
  end
138
140
  elsif tag_name == 'textarea'
139
141
  set_text(value.to_s)
@@ -172,12 +174,12 @@ module Capybara::Apparition
172
174
  pos = visible_center(allow_scroll: false)
173
175
  return true if pos.nil?
174
176
 
175
- hit_node = @page.element_from_point(pos)
177
+ hit_node = @page.element_from_point(**pos)
176
178
  return true if hit_node.nil?
177
179
 
178
180
  begin
179
181
  return evaluate_on('el => !this.contains(el)', objectId: hit_node['objectId'])
180
- rescue WrongWorld # rubocop:disable Lint/HandleExceptions
182
+ rescue WrongWorld # rubocop:disable Lint/SuppressedException
181
183
  end
182
184
 
183
185
  true
@@ -196,22 +198,22 @@ module Capybara::Apparition
196
198
  end
197
199
 
198
200
  def click(keys = [], button: 'left', count: 1, **options)
199
- pos = element_click_pos(options)
201
+ pos = element_click_pos(**options)
200
202
  raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['click']) if pos.nil?
201
203
 
202
- test = mouse_event_test(pos)
204
+ test = mouse_event_test(**pos)
203
205
  raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['click']) if test.nil?
204
206
 
205
207
  unless options[:x] && options[:y]
206
208
  raise ::Capybara::Apparition::MouseEventFailed.new(self, 'args' => ['click', test.selector, pos]) unless test.success
207
209
  end
208
210
 
209
- @page.mouse.click_at pos.merge(button: button, count: count, modifiers: keys)
211
+ @page.mouse.click_at(**pos.merge(button: button, count: count, modifiers: keys))
210
212
  if ENV['DEBUG']
211
213
  begin
212
- new_pos = element_click_pos(options)
214
+ new_pos = element_click_pos(**options)
213
215
  puts "Element moved from #{pos} to #{new_pos}" unless pos == new_pos
214
- rescue WrongWorld # rubocop:disable Lint/HandleExceptions
216
+ rescue WrongWorld # rubocop:disable Lint/SuppressedException
215
217
  end
216
218
  end
217
219
  # Wait a short time to see if click triggers page load
@@ -231,7 +233,7 @@ module Capybara::Apparition
231
233
  pos = visible_center
232
234
  raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['hover']) if pos.nil?
233
235
 
234
- @page.mouse.move_to(pos)
236
+ @page.mouse.move_to(**pos)
235
237
  end
236
238
 
237
239
  EVENTS = {
@@ -534,6 +536,10 @@ module Capybara::Apparition
534
536
  update_value_js(value.to_s)
535
537
  end
536
538
 
539
+ def set_range(value)
540
+ update_value_js(value.to_s)
541
+ end
542
+
537
543
  def update_value_js(value)
538
544
  evaluate_on(<<~JS, value: value)
539
545
  value => {
@@ -759,7 +765,7 @@ module Capybara::Apparition
759
765
  # if an area element, check visibility of relevant image
760
766
  VISIBLE_JS = <<~JS
761
767
  function(){
762
- el = this;
768
+ let el = this;
763
769
  if (el.tagName == 'AREA'){
764
770
  const map_name = document.evaluate('./ancestor::map/@name', el, null, XPathResult.STRING_TYPE, null).stringValue;
765
771
  el = document.querySelector(`img[usemap='#${map_name}']`);
@@ -2,26 +2,30 @@
2
2
 
3
3
  module Capybara::Apparition
4
4
  module Drag
5
- def drag_to(other, delay: 0.1, html5: nil)
5
+ def drag_to(other, delay: 0.1, html5: nil, drop_modifiers: [])
6
+ drop_modifiers = Array(drop_modifiers)
7
+
6
8
  driver.execute_script MOUSEDOWN_TRACKER
7
9
  scroll_if_needed
8
10
  m = @page.mouse
9
- m.move_to(visible_center)
11
+ m.move_to(**visible_center)
10
12
  sleep delay
11
13
  m.down
12
14
  html5 = !driver.evaluate_script(LEGACY_DRAG_CHECK, self) if html5.nil?
13
15
  if html5
14
- driver.execute_script HTML5_DRAG_DROP_SCRIPT, self, other, delay
15
- m.up(other.visible_center)
16
+ driver.execute_script HTML5_DRAG_DROP_SCRIPT, self, other, delay, drop_modifiers
17
+ m.up(**other.visible_center)
16
18
  else
17
- begin
18
- other.scroll_if_needed
19
- sleep delay
20
- m.move_to(other.visible_center)
21
- sleep delay
22
- ensure
23
- m.up
24
- sleep delay
19
+ @page.keyboard.with_keys(drop_modifiers) do
20
+ begin
21
+ other.scroll_if_needed
22
+ sleep delay
23
+ m.move_to(**other.visible_center)
24
+ sleep delay
25
+ ensure
26
+ m.up
27
+ sleep delay
28
+ end
25
29
  end
26
30
  end
27
31
  end
@@ -31,11 +35,11 @@ module Capybara::Apparition
31
35
  raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['hover']) if pos.nil?
32
36
 
33
37
  other_pos = { x: pos[:x] + x, y: pos[:y] + y }
34
- raise ::Capybara::Apparition::MouseEventFailed.new(self, 'args' => ['drag', test['selector'], pos]) unless mouse_event_test?(pos)
38
+ raise ::Capybara::Apparition::MouseEventFailed.new(self, 'args' => ['drag', test['selector'], pos]) unless mouse_event_test?(**pos)
35
39
 
36
- @page.mouse.move_to(pos).down
40
+ @page.mouse.move_to(**pos).down
37
41
  sleep delay
38
- @page.mouse.move_to(other_pos)
42
+ @page.mouse.move_to(**other_pos)
39
43
  sleep delay
40
44
  @page.mouse.up
41
45
  end
@@ -125,9 +129,15 @@ module Capybara::Apparition
125
129
  JS
126
130
 
127
131
  HTML5_DRAG_DROP_SCRIPT = <<~JS
128
- var source = arguments[0];
129
- var target = arguments[1];
130
- var step_delay = arguments[2] * 1000;
132
+ let source = arguments[0];
133
+ const target = arguments[1];
134
+ const step_delay = arguments[2] * 1000;
135
+ const drop_modifiers = arguments[3];
136
+ const key_aliases = {
137
+ 'cmd': 'meta',
138
+ 'command': 'meta',
139
+ 'control': 'ctrl',
140
+ };
131
141
 
132
142
  function rectCenter(rect){
133
143
  return new DOMPoint(
@@ -181,6 +191,9 @@ module Capybara::Apparition
181
191
  let targetRect = target.getBoundingClientRect(),
182
192
  sourceCenter = rectCenter(source.getBoundingClientRect());
183
193
 
194
+ drop_modifiers.map(key => key_aliases[key] || key)
195
+ .forEach(key => opts[key + 'Key'] = true);
196
+
184
197
  // fire 2 dragover events to simulate dragging with a direction
185
198
  let entryPoint = pointOnRect(sourceCenter, targetRect);
186
199
  let dragOverOpts = Object.assign({clientX: entryPoint.x, clientY: entryPoint.y}, opts);
@@ -196,26 +209,27 @@ module Capybara::Apparition
196
209
  dragOverOpts = Object.assign({clientX: targetCenter.x, clientY: targetCenter.y}, opts);
197
210
  dragOverEvent = new DragEvent('dragover', dragOverOpts);
198
211
  target.dispatchEvent(dragOverEvent);
199
- setTimeout(resolve, step_delay, dragOverEvent.defaultPrevented);
212
+ setTimeout(resolve, step_delay, { drop: dragOverEvent.defaultPrevented, opts: dragOverOpts});
200
213
  })
201
214
  }
202
215
 
203
- function dragLeave(drop) {
216
+ function dragLeave({ drop, opts: dragOverOpts }) {
204
217
  return new Promise( resolve => {
205
- var dragLeaveEvent = new DragEvent('dragleave', opts);
218
+ var dragLeaveOptions = { ...opts, ...dragOverOpts };
219
+ var dragLeaveEvent = new DragEvent('dragleave', dragLeaveOptions);
206
220
  target.dispatchEvent(dragLeaveEvent);
207
221
  if (drop) {
208
- var dropEvent = new DragEvent('drop', opts);
222
+ var dropEvent = new DragEvent('drop', dragLeaveOptions);
209
223
  target.dispatchEvent(dropEvent);
210
224
  }
211
- var dragEndEvent = new DragEvent('dragend', opts);
225
+ var dragEndEvent = new DragEvent('dragend', dragLeaveOptions);
212
226
  source.dispatchEvent(dragEndEvent);
213
227
  setTimeout(resolve, step_delay);
214
228
  })
215
229
  }
216
230
 
217
- var dt = new DataTransfer();
218
- var opts = { cancelable: true, bubbles: true, dataTransfer: dt };
231
+ const dt = new DataTransfer();
232
+ const opts = { cancelable: true, bubbles: true, dataTransfer: dt };
219
233
 
220
234
  while (source && !source.draggable) {
221
235
  source = source.parentElement;
@@ -22,7 +22,7 @@ module Capybara::Apparition
22
22
  # Provides a lot of info - but huge overhead
23
23
  # session.command 'Page.setLifecycleEventsEnabled', enabled: true
24
24
 
25
- page = Page.new(browser, session, id, browser_context_id, options)
25
+ page = Page.new(browser, session, id, browser_context_id, **options)
26
26
 
27
27
  session.async_commands 'Network.enable', 'Runtime.enable', 'Security.enable', 'DOM.enable'
28
28
  session.async_command 'Security.setIgnoreCertificateErrors', ignore: !!ignore_https_errors
@@ -150,7 +150,7 @@ module Capybara::Apparition
150
150
  params[:paperWidth] = @browser.paper_size[:width].to_f
151
151
  params[:paperHeight] = @browser.paper_size[:height].to_f
152
152
  end
153
- command('Page.printToPDF', params)
153
+ command('Page.printToPDF', **params)
154
154
  else
155
155
  clip_options = if options[:selector]
156
156
  pos = evaluate("document.querySelector('#{options.delete(:selector)}').getBoundingClientRect().toJSON();")
@@ -165,7 +165,7 @@ module Capybara::Apparition
165
165
  JS
166
166
  end
167
167
  options[:clip] = { x: 0, y: 0, scale: scale }.merge(clip_options)
168
- command('Page.captureScreenshot', options)
168
+ command('Page.captureScreenshot', **options)
169
169
  end['data']
170
170
  end
171
171
 
@@ -284,7 +284,7 @@ module Capybara::Apparition
284
284
  @status_code = 0
285
285
  navigate_opts = { url: url, transitionType: 'reload' }
286
286
  navigate_opts[:referrer] = extra_headers['Referer'] if extra_headers['Referer']
287
- response = command('Page.navigate', navigate_opts)
287
+ response = command('Page.navigate', **navigate_opts)
288
288
  raise StatusFailError, 'args' => [url, response['errorText']] if response['errorText']
289
289
 
290
290
  main_frame.loading(response['loaderId'])
@@ -335,7 +335,7 @@ module Capybara::Apparition
335
335
  }
336
336
  metrics[:screenWidth], metrics[:screenHeight] = *screen if screen
337
337
 
338
- command('Emulation.setDeviceMetricsOverride', metrics)
338
+ command('Emulation.setDeviceMetricsOverride', **metrics)
339
339
  end
340
340
 
341
341
  def fullscreen
@@ -366,7 +366,7 @@ module Capybara::Apparition
366
366
  end
367
367
 
368
368
  def async_command(name, **params)
369
- @browser.command_for_session(@session.session_id, name, params).discard_result
369
+ @browser.command_for_session(@session.session_id, name, **params).discard_result
370
370
  end
371
371
 
372
372
  def extra_headers
@@ -386,7 +386,7 @@ module Capybara::Apparition
386
386
  if page
387
387
  self.url_whitelist = page.url_whitelist.dup
388
388
  self.url_blacklist = page.url_blacklist.dup
389
- set_viewport(page.viewport_size) if page.viewport_size
389
+ set_viewport(**page.viewport_size) if page.viewport_size
390
390
  end
391
391
  self
392
392
  end
@@ -330,6 +330,7 @@ module Capybara::Apparition
330
330
  'z': { 'keyCode': 90, 'code': 'KeyZ', 'shiftKey': 'Z', 'key': 'z' },
331
331
  'meta': { 'keyCode': 91, 'key': 'Meta', 'code': 'MetaLeft' },
332
332
  'command': { 'keyCode': 91, 'key': 'Meta', 'code': 'MetaLeft' },
333
+ 'cmd': { 'keyCode': 91, 'key': 'Meta', 'code': 'MetaLeft' },
333
334
  '*': { 'keyCode': 106, 'key': '*', 'code': 'NumpadMultiply', 'location': 3 },
334
335
  '+': { 'keyCode': 107, 'key': '+', 'code': 'NumpadAdd', 'location': 3 },
335
336
  '-': { 'keyCode': 109, 'key': '-', 'code': 'NumpadSubtract', 'location': 3 },
@@ -14,8 +14,8 @@ module Capybara::Apparition
14
14
  count.times do |num|
15
15
  @keyboard.with_keys(modifiers) do
16
16
  mouse_params = { x: x, y: y, button: button, count: num + 1 }
17
- down mouse_params
18
- up mouse_params
17
+ down(**mouse_params)
18
+ up(**mouse_params)
19
19
  end
20
20
  end
21
21
  self
@@ -29,7 +29,7 @@ module Capybara::Apparition
29
29
 
30
30
  def down(button: 'left', **options)
31
31
  options = @current_pos.merge(button: button).merge(options)
32
- mouse_event('mousePressed', options)
32
+ mouse_event('mousePressed', **options)
33
33
  @current_buttons |= BUTTONS[button.to_sym]
34
34
  self
35
35
  end
@@ -37,7 +37,7 @@ module Capybara::Apparition
37
37
  def up(button: 'left', **options)
38
38
  options = @current_pos.merge(button: button).merge(options)
39
39
  @current_buttons &= ~BUTTONS[button.to_sym]
40
- mouse_event('mouseReleased', options)
40
+ mouse_event('mouseReleased', **options)
41
41
  self
42
42
  end
43
43
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Capybara
4
4
  module Apparition
5
- VERSION = '0.4.0'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apparition
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Walpole
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-15 00:00:00.000000000 Z
11
+ date: 2020-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -291,7 +291,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
291
291
  - !ruby/object:Gem::Version
292
292
  version: '0'
293
293
  requirements: []
294
- rubygems_version: 3.0.3
294
+ rubygems_version: 3.1.2
295
295
  signing_key:
296
296
  specification_version: 4
297
297
  summary: Chrome driver using CDP for Capybara