capybara 3.31.0 → 3.33.0

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +51 -0
  3. data/README.md +10 -3
  4. data/lib/capybara.rb +17 -7
  5. data/lib/capybara/cucumber.rb +1 -1
  6. data/lib/capybara/minitest.rb +215 -141
  7. data/lib/capybara/minitest/spec.rb +153 -97
  8. data/lib/capybara/node/actions.rb +16 -20
  9. data/lib/capybara/node/element.rb +2 -0
  10. data/lib/capybara/node/matchers.rb +4 -6
  11. data/lib/capybara/queries/selector_query.rb +8 -1
  12. data/lib/capybara/queries/style_query.rb +1 -1
  13. data/lib/capybara/queries/text_query.rb +6 -0
  14. data/lib/capybara/rack_test/browser.rb +3 -1
  15. data/lib/capybara/registration_container.rb +44 -0
  16. data/lib/capybara/registrations/servers.rb +1 -1
  17. data/lib/capybara/result.rb +5 -1
  18. data/lib/capybara/rspec/matcher_proxies.rb +4 -4
  19. data/lib/capybara/rspec/matchers/have_text.rb +1 -1
  20. data/lib/capybara/selector.rb +10 -1
  21. data/lib/capybara/selector/definition.rb +5 -4
  22. data/lib/capybara/selector/definition/button.rb +1 -0
  23. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  24. data/lib/capybara/selector/definition/link.rb +8 -0
  25. data/lib/capybara/selector/definition/table.rb +1 -1
  26. data/lib/capybara/selector/selector.rb +4 -0
  27. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
  28. data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
  29. data/lib/capybara/selenium/driver.rb +7 -4
  30. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +7 -9
  31. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +7 -9
  32. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
  33. data/lib/capybara/selenium/node.rb +69 -9
  34. data/lib/capybara/selenium/nodes/chrome_node.rb +0 -9
  35. data/lib/capybara/selenium/nodes/firefox_node.rb +2 -2
  36. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  37. data/lib/capybara/selenium/patches/logs.rb +3 -5
  38. data/lib/capybara/session.rb +3 -3
  39. data/lib/capybara/session/config.rb +3 -1
  40. data/lib/capybara/spec/public/test.js +18 -0
  41. data/lib/capybara/spec/session/click_button_spec.rb +11 -0
  42. data/lib/capybara/spec/session/fill_in_spec.rb +9 -0
  43. data/lib/capybara/spec/session/find_spec.rb +11 -8
  44. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  45. data/lib/capybara/spec/session/has_css_spec.rb +9 -6
  46. data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
  47. data/lib/capybara/spec/session/has_field_spec.rb +16 -0
  48. data/lib/capybara/spec/session/has_select_spec.rb +4 -4
  49. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  50. data/lib/capybara/spec/session/node_spec.rb +54 -27
  51. data/lib/capybara/spec/session/window/window_spec.rb +7 -7
  52. data/lib/capybara/spec/spec_helper.rb +2 -2
  53. data/lib/capybara/spec/test_app.rb +14 -18
  54. data/lib/capybara/spec/views/form.erb +7 -1
  55. data/lib/capybara/spec/views/with_dragula.erb +3 -1
  56. data/lib/capybara/spec/views/with_html.erb +2 -2
  57. data/lib/capybara/spec/views/with_js.erb +1 -0
  58. data/lib/capybara/version.rb +1 -1
  59. data/spec/capybara_spec.rb +1 -1
  60. data/spec/dsl_spec.rb +14 -1
  61. data/spec/minitest_spec.rb +1 -1
  62. data/spec/rack_test_spec.rb +13 -0
  63. data/spec/regexp_dissassembler_spec.rb +0 -4
  64. data/spec/result_spec.rb +38 -31
  65. data/spec/rspec/shared_spec_matchers.rb +65 -53
  66. data/spec/selector_spec.rb +1 -1
  67. data/spec/selenium_spec_chrome.rb +4 -2
  68. data/spec/selenium_spec_chrome_remote.rb +2 -0
  69. data/spec/server_spec.rb +41 -49
  70. data/spec/shared_selenium_node.rb +18 -0
  71. data/spec/shared_selenium_session.rb +25 -7
  72. data/spec/spec_helper.rb +1 -1
  73. metadata +5 -3
@@ -92,11 +92,6 @@ private
92
92
  end
93
93
  end
94
94
 
95
- def w3c?
96
- (defined?(Selenium::WebDriver::VERSION) && (Selenium::WebDriver::VERSION.to_f >= 4)) ||
97
- capabilities.is_a?(::Selenium::WebDriver::Remote::W3C::Capabilities)
98
- end
99
-
100
95
  def browser_version(to_float = true)
101
96
  caps = capabilities
102
97
  ver = (caps[:browser_version] || caps[:version])
@@ -116,10 +111,6 @@ private
116
111
  capabilities['chrome']['chromedriverVersion'].split(' ')[0]
117
112
  end
118
113
 
119
- def capabilities
120
- driver.browser.capabilities
121
- end
122
-
123
114
  def native_displayed?
124
115
  (driver.options[:native_displayed] != false) &&
125
116
  (w3c? && chromedriver_supports_displayed_endpoint?) &&
@@ -42,7 +42,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
42
42
 
43
43
  def send_keys(*args)
44
44
  # https://github.com/mozilla/geckodriver/issues/846
45
- return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none? { |arg| arg.is_a? Array }
45
+ return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)
46
46
 
47
47
  native.click
48
48
  _send_keys(args).perform
@@ -85,7 +85,7 @@ private
85
85
  (driver.options[:native_displayed] != false) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']
86
86
  end
87
87
 
88
- def click_with_options(click_options)
88
+ def perform_with_options(click_options)
89
89
  # Firefox/marionette has an issue clicking with offset near viewport edge
90
90
  # scroll element to middle just in case
91
91
  scroll_to_center if click_options.coords?
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionPauser
4
+ def initialize(mouse, keyboard)
5
+ super
6
+ @devices[:pauser] = Pauser.new
7
+ end
8
+
9
+ def pause(duration)
10
+ @actions << [:pauser, :pause, [duration]]
11
+ self
12
+ end
13
+
14
+ class Pauser
15
+ def pause(duration)
16
+ sleep duration
17
+ end
18
+ end
19
+
20
+ private_constant :Pauser
21
+ end
22
+
23
+ if defined?(::Selenium::WebDriver::VERSION) && (::Selenium::WebDriver::VERSION.to_f < 4) &&
24
+ defined?(::Selenium::WebDriver::ActionBuilder)
25
+ ::Selenium::WebDriver::ActionBuilder.prepend(ActionPauser)
26
+ end
@@ -33,11 +33,9 @@ module Capybara
33
33
  end
34
34
 
35
35
  Array(data).map do |l|
36
- begin
37
- ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
38
- rescue KeyError
39
- next
40
- end
36
+ ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
37
+ rescue KeyError
38
+ next
41
39
  end
42
40
  rescue ::Selenium::WebDriver::Error::UnknownCommandError
43
41
  raise NotImplementedError, LOG_MSG
@@ -97,8 +97,8 @@ module Capybara
97
97
 
98
98
  def driver
99
99
  @driver ||= begin
100
- unless Capybara.drivers.key?(mode)
101
- other_drivers = Capybara.drivers.keys.map(&:inspect)
100
+ unless Capybara.drivers[mode]
101
+ other_drivers = Capybara.drivers.names.map(&:inspect)
102
102
  raise Capybara::DriverNotFoundError, "no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}"
103
103
  end
104
104
  driver = Capybara.drivers[mode].call(app)
@@ -192,7 +192,7 @@ module Capybara
192
192
  # @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
193
193
  #
194
194
  def html
195
- driver.html
195
+ driver.html || ''
196
196
  end
197
197
  alias_method :body, :html
198
198
  alias_method :source, :html
@@ -8,7 +8,7 @@ module Capybara
8
8
  automatic_reload match exact exact_text raise_server_errors visible_text_only
9
9
  automatic_label_click enable_aria_label save_path asset_host default_host app_host
10
10
  server_host server_port server_errors default_set_options disable_animation test_id
11
- predicates_wait default_normalize_ws w3c_click_offset].freeze
11
+ predicates_wait default_normalize_ws w3c_click_offset enable_aria_role].freeze
12
12
 
13
13
  attr_accessor(*OPTIONS)
14
14
 
@@ -37,6 +37,8 @@ module Capybara
37
37
  # See {Capybara.configure}
38
38
  # @!method enable_aria_label
39
39
  # See {Capybara.configure}
40
+ # @!method enable_aria_role
41
+ # See {Capybara.configure}
40
42
  # @!method save_path
41
43
  # See {Capybara.configure}
42
44
  # @!method asset_host
@@ -108,6 +108,13 @@ $(function() {
108
108
  }, 4000);
109
109
  return false;
110
110
  });
111
+ $('#aria-button').click(function() {
112
+ var span = $(this);
113
+ setTimeout(function() {
114
+ $(span).after('<span role="button">ARIA button has been clicked</span>')
115
+ }, 1000);
116
+ return false;
117
+ });
111
118
  $('#waiter').change(function() {
112
119
  activeRequests = 1;
113
120
  setTimeout(function() {
@@ -153,6 +160,7 @@ $(function() {
153
160
  });
154
161
  $('#click-test').on({
155
162
  click: function(e) {
163
+ window.click_delay = ((new Date().getTime()) - window.mouse_down_time)/1000.0;
156
164
  var desc = "";
157
165
  if (e.altKey) desc += 'alt ';
158
166
  if (e.ctrlKey) desc += 'control ';
@@ -179,6 +187,16 @@ $(function() {
179
187
  if (e.shiftKey) desc += 'shift ';
180
188
  var pos = this.getBoundingClientRect();
181
189
  $(this).after('<a id="has-been-right-clicked" href="#">Has been ' + desc + 'right clicked at ' + (e.clientX - pos.left) + ',' + (e.clientY - pos.top) + '</a>');
190
+ },
191
+ mousedown: function(e) {
192
+ window.click_delay = undefined;
193
+ window.right_click_delay = undefined;
194
+ window.mouse_down_time = new Date().getTime();
195
+ },
196
+ mouseup: function(e) {
197
+ if (e.button == 2){
198
+ window.right_click_delay = ((new Date().getTime()) - window.mouse_down_time)/1000.0;
199
+ }
182
200
  }
183
201
  });
184
202
  $('#open-alert').click(function() {
@@ -193,6 +193,17 @@ Capybara::SpecHelper.spec '#click_button' do
193
193
  end
194
194
  end
195
195
 
196
+ context 'when Capybara.enable_aria_role = true' do
197
+ it 'should click on a button role', requires: [:js] do
198
+ Capybara.enable_aria_role = true
199
+ @session.using_wait_time(1.5) do
200
+ @session.visit('/with_js')
201
+ @session.click_button('ARIA button')
202
+ expect(@session).to have_button('ARIA button has been clicked')
203
+ end
204
+ end
205
+ end
206
+
196
207
  context 'with fields associated with the form using the form attribute', requires: [:form_attribute] do
197
208
  let(:results) { extract_results(@session) }
198
209
 
@@ -47,6 +47,15 @@ Capybara::SpecHelper.spec '#fill_in' do
47
47
  expect(extract_results(@session)['description']).to eq('Texty text')
48
48
  end
49
49
 
50
+ it 'should fill in a textarea in a reasonable time by default' do
51
+ textarea = @session.find(:fillable_field, 'form[description]')
52
+ value = 'a' * 4000
53
+ start = Time.now
54
+ textarea.fill_in(with: value)
55
+ expect(Time.now.to_f).to be_within(0.25).of start.to_f
56
+ expect(textarea.value).to eq value
57
+ end
58
+
50
59
  it 'should fill in a password field by id' do
51
60
  @session.fill_in('form_password', with: 'supasikrit')
52
61
  @session.click_button('awesome')
@@ -451,32 +451,35 @@ Capybara::SpecHelper.spec '#find' do
451
451
  context 'with spatial filters', requires: [:spatial] do
452
452
  before do
453
453
  @session.visit('/spatial')
454
- @center = @session.find(:css, 'div.center')
454
+ end
455
+
456
+ let :center do
457
+ @session.find(:css, 'div.center')
455
458
  end
456
459
 
457
460
  it 'should find an element above another element' do
458
- expect(@session.find(:css, 'div:not(.corner)', above: @center).text).to eq('2')
461
+ expect(@session.find(:css, 'div:not(.corner)', above: center).text).to eq('2')
459
462
  end
460
463
 
461
464
  it 'should find an element below another element' do
462
- expect(@session.find(:css, 'div:not(.corner):not(.footer)', below: @center).text).to eq('8')
465
+ expect(@session.find(:css, 'div:not(.corner):not(.footer)', below: center).text).to eq('8')
463
466
  end
464
467
 
465
468
  it 'should find an element left of another element' do
466
- expect(@session.find(:css, 'div:not(.corner)', left_of: @center).text).to eq('4')
469
+ expect(@session.find(:css, 'div:not(.corner)', left_of: center).text).to eq('4')
467
470
  end
468
471
 
469
472
  it 'should find an element right of another element' do
470
- expect(@session.find(:css, 'div:not(.corner)', right_of: @center).text).to eq('6')
473
+ expect(@session.find(:css, 'div:not(.corner)', right_of: center).text).to eq('6')
471
474
  end
472
475
 
473
476
  it 'should combine spatial filters' do
474
- expect(@session.find(:css, 'div', left_of: @center, above: @center).text).to eq('1')
475
- expect(@session.find(:css, 'div', right_of: @center, below: @center).text).to eq('9')
477
+ expect(@session.find(:css, 'div', left_of: center, above: center).text).to eq('1')
478
+ expect(@session.find(:css, 'div', right_of: center, below: center).text).to eq('9')
476
479
  end
477
480
 
478
481
  it 'should find an element "near" another element' do
479
- expect(@session.find(:css, 'div.distance', near: @center).text).to eq('2')
482
+ expect(@session.find(:css, 'div.distance', near: center).text).to eq('2')
480
483
  end
481
484
  end
482
485
 
@@ -39,6 +39,14 @@ Capybara::SpecHelper.spec '#has_button?' do
39
39
  expect(@session).to have_button('awe123', type: 'submit')
40
40
  expect(@session).not_to have_button('awe123', type: 'reset')
41
41
  end
42
+
43
+ it 'should be true for role=button when enable_aria_role: true' do
44
+ expect(@session).to have_button('ARIA button', enable_aria_role: true)
45
+ end
46
+
47
+ it 'should be false for role=button when enable_aria_role: false' do
48
+ expect(@session).not_to have_button('ARIA button', enable_aria_role: false)
49
+ end
42
50
  end
43
51
 
44
52
  Capybara::SpecHelper.spec '#has_no_button?' do
@@ -66,4 +74,12 @@ Capybara::SpecHelper.spec '#has_no_button?' do
66
74
  it 'should be false for disabled buttons if disabled: false' do
67
75
  expect(@session).to have_no_button('Disabled button', disabled: false)
68
76
  end
77
+
78
+ it 'should be true for role=button when enable_aria_role: false' do
79
+ expect(@session).to have_no_button('ARIA button', enable_aria_role: false)
80
+ end
81
+
82
+ it 'should be false for role=button when enable_aria_role: true' do
83
+ expect(@session).not_to have_no_button('ARIA button', enable_aria_role: true)
84
+ end
69
85
  end
@@ -234,18 +234,21 @@ Capybara::SpecHelper.spec '#has_css?' do
234
234
  context 'with spatial requirements', requires: [:spatial] do
235
235
  before do
236
236
  @session.visit('/spatial')
237
- @center = @session.find(:css, '.center')
237
+ end
238
+
239
+ let :center do
240
+ @session.find(:css, '.center')
238
241
  end
239
242
 
240
243
  it 'accepts spatial options' do
241
- expect(@session).to have_css('div', above: @center).thrice
242
- expect(@session).to have_css('div', above: @center, right_of: @center).once
244
+ expect(@session).to have_css('div', above: center).thrice
245
+ expect(@session).to have_css('div', above: center, right_of: center).once
243
246
  end
244
247
 
245
248
  it 'supports spatial sugar' do
246
- expect(@session).to have_css('div').left_of(@center).thrice
247
- expect(@session).to have_css('div').below(@center).right_of(@center).once
248
- expect(@session).to have_css('div').near(@center).exactly(8).times
249
+ expect(@session).to have_css('div').left_of(center).thrice
250
+ expect(@session).to have_css('div').below(center).right_of(center).once
251
+ expect(@session).to have_css('div').near(center).exactly(8).times
249
252
  end
250
253
  end
251
254
 
@@ -128,11 +128,11 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
128
128
  # Without ignore_query option
129
129
  expect do
130
130
  expect(@session).not_to have_current_path('/with_js')
131
- end. not_to raise_exception
131
+ end.not_to raise_exception
132
132
 
133
133
  # With ignore_query option
134
134
  expect do
135
135
  expect(@session).not_to have_current_path('/with_js', ignore_query: true)
136
- end. not_to raise_exception
136
+ end.not_to raise_exception
137
137
  end
138
138
  end
@@ -60,6 +60,22 @@ Capybara::SpecHelper.spec '#has_field' do
60
60
  end
61
61
  end
62
62
 
63
+ context 'with validation message', requires: [:html_validation] do
64
+ it 'should accept a regexp' do
65
+ @session.fill_in('form_zipcode', with: '1234')
66
+ expect(@session).to have_field('form_zipcode', validation_message: /match the requested format/)
67
+ expect(@session).not_to have_field('form_zipcode', validation_message: /random/)
68
+ end
69
+
70
+ it 'should accept a string' do
71
+ @session.fill_in('form_zipcode', with: '1234')
72
+ expect(@session).to have_field('form_zipcode', validation_message: 'Please match the requested format.')
73
+ expect(@session).not_to have_field('form_zipcode', validation_message: 'match the requested format.')
74
+ @session.fill_in('form_zipcode', with: '12345')
75
+ expect(@session).to have_field('form_zipcode', validation_message: '')
76
+ end
77
+ end
78
+
63
79
  context 'with type' do
64
80
  it 'should be true if a field with the given type is on the page' do
65
81
  expect(@session).to have_field('First Name', type: 'text')
@@ -63,7 +63,7 @@ Capybara::SpecHelper.spec '#has_select?' do
63
63
  end
64
64
 
65
65
  it "should be true even when the selected option invisible, regardless of the select's visibility" do
66
- expect(@session).to have_select('Icecream', visible: false, selected: 'Chocolate')
66
+ expect(@session).to have_select('Icecream', visible: :hidden, selected: 'Chocolate')
67
67
  expect(@session).to have_select('Sorbet', selected: 'Vanilla')
68
68
  end
69
69
  end
@@ -88,7 +88,7 @@ Capybara::SpecHelper.spec '#has_select?' do
88
88
  end
89
89
 
90
90
  it "should be true even when the selected values are invisible, regardless of the select's visibility" do
91
- expect(@session).to have_select('Dessert', visible: false, with_options: %w[Pudding Tiramisu])
91
+ expect(@session).to have_select('Dessert', visible: :hidden, with_options: %w[Pudding Tiramisu])
92
92
  expect(@session).to have_select('Cake', with_selected: ['Chocolate Cake', 'Sponge Cake'])
93
93
  end
94
94
 
@@ -113,7 +113,7 @@ Capybara::SpecHelper.spec '#has_select?' do
113
113
  end
114
114
 
115
115
  it 'should be true even when the options are invisible, if the select itself is invisible' do
116
- expect(@session).to have_select('Icecream', visible: false, options: %w[Chocolate Vanilla Strawberry])
116
+ expect(@session).to have_select('Icecream', visible: :hidden, options: %w[Chocolate Vanilla Strawberry])
117
117
  end
118
118
  end
119
119
 
@@ -158,7 +158,7 @@ Capybara::SpecHelper.spec '#has_select?' do
158
158
  end
159
159
 
160
160
  it 'should be true even when the options are invisible, if the select itself is invisible' do
161
- expect(@session).to have_select('Icecream', visible: false, with_options: %w[Vanilla Strawberry])
161
+ expect(@session).to have_select('Icecream', visible: :hidden, with_options: %w[Vanilla Strawberry])
162
162
  end
163
163
  end
164
164
 
@@ -61,12 +61,12 @@ Capybara::SpecHelper.spec '#has_selector?' do
61
61
  end
62
62
 
63
63
  it 'should respect visibility setting' do
64
- expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: false)
65
- expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: true)
64
+ expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
65
+ expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
66
66
  Capybara.ignore_hidden_elements = false
67
- expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: false)
67
+ expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
68
68
  Capybara.visible_text_only = true
69
- expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: true)
69
+ expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
70
70
  end
71
71
 
72
72
  it 'should discard all matches where the given regexp is not matched' do
@@ -271,12 +271,12 @@ Capybara::SpecHelper.spec 'node' do
271
271
 
272
272
  it 'works when details is toggled open and closed' do
273
273
  @session.find(:css, '#closed_details > summary').click
274
- expect(@session).to have_css('#closed_details *', visible: true, count: 5)
274
+ expect(@session).to have_css('#closed_details *', visible: :visible, count: 5)
275
275
  .and(have_no_css('#closed_details *', visible: :hidden))
276
276
 
277
277
  @session.find(:css, '#closed_details > summary').click
278
278
  descendants_css = '#closed_details > *:not(summary), #closed_details > *:not(summary) *'
279
- expect(@session).to have_no_css(descendants_css, visible: true)
279
+ expect(@session).to have_no_css(descendants_css, visible: :visible)
280
280
  .and(have_css(descendants_css, visible: :hidden, count: 3))
281
281
  end
282
282
  end
@@ -446,7 +446,7 @@ Capybara::SpecHelper.spec 'node' do
446
446
 
447
447
  it 'should work with Dragula' do
448
448
  @session.visit('/with_dragula')
449
- @session.within(:css, '#sortable') do
449
+ @session.within(:css, '#sortable.ready') do
450
450
  src = @session.find('div', text: 'Item 1')
451
451
  target = @session.find('div', text: 'Item 3')
452
452
  src.drag_to target
@@ -758,7 +758,7 @@ Capybara::SpecHelper.spec 'node' do
758
758
  @session.visit('with_js')
759
759
  @session.find(:css, '#click-test').click(x: 5, y: 5)
760
760
  link = @session.find(:link, 'has-been-clicked')
761
- locations = link.text.match(/^Has been clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
761
+ locations = link.text.match(/^Has been clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
762
762
  # Resulting click location should be very close to 0, 0 relative to top left corner of the element, but may not be exact due to
763
763
  # integer/float conversions and rounding.
764
764
  expect(locations[:x].to_f).to be_within(1).of(5)
@@ -808,7 +808,10 @@ Capybara::SpecHelper.spec 'node' do
808
808
  context 'offset', requires: [:js] do
809
809
  before do
810
810
  @session.visit('/offset')
811
- @clicker = @session.find(:id, 'clicker')
811
+ end
812
+
813
+ let :clicker do
814
+ @session.find(:id, 'clicker')
812
815
  end
813
816
 
814
817
  context 'when w3c_click_offset is false' do
@@ -817,17 +820,17 @@ Capybara::SpecHelper.spec 'node' do
817
820
  end
818
821
 
819
822
  it 'should offset from top left of element' do
820
- @clicker.click(x: 10, y: 5)
823
+ clicker.click(x: 10, y: 5)
821
824
  expect(@session).to have_text(/clicked at 110,105/)
822
825
  end
823
826
 
824
827
  it 'should offset outside the element' do
825
- @clicker.click(x: -15, y: -10)
828
+ clicker.click(x: -15, y: -10)
826
829
  expect(@session).to have_text(/clicked at 85,90/)
827
830
  end
828
831
 
829
832
  it 'should default to click the middle' do
830
- @clicker.click
833
+ clicker.click
831
834
  expect(@session).to have_text(/clicked at 150,150/)
832
835
  end
833
836
  end
@@ -838,21 +841,30 @@ Capybara::SpecHelper.spec 'node' do
838
841
  end
839
842
 
840
843
  it 'should offset from center of element' do
841
- @clicker.click(x: 10, y: 5)
844
+ clicker.click(x: 10, y: 5)
842
845
  expect(@session).to have_text(/clicked at 160,155/)
843
846
  end
844
847
 
845
848
  it 'should offset outside from center of element' do
846
- @clicker.click(x: -65, y: -60)
849
+ clicker.click(x: -65, y: -60)
847
850
  expect(@session).to have_text(/clicked at 85,90/)
848
851
  end
849
852
 
850
853
  it 'should default to click the middle' do
851
- @clicker.click
854
+ clicker.click
852
855
  expect(@session).to have_text(/clicked at 150,150/)
853
856
  end
854
857
  end
855
858
  end
859
+
860
+ context 'delay', requires: [:js] do
861
+ it 'should delay the mouse up' do
862
+ @session.visit('with_js')
863
+ @session.find(:css, '#click-test').click(delay: 2)
864
+ delay = @session.evaluate_script('window.click_delay')
865
+ expect(delay).to be >= 2
866
+ end
867
+ end
856
868
  end
857
869
 
858
870
  describe '#double_click', requires: [:js] do
@@ -872,7 +884,7 @@ Capybara::SpecHelper.spec 'node' do
872
884
  @session.visit('with_js')
873
885
  @session.find(:css, '#click-test').double_click(x: 10, y: 5)
874
886
  link = @session.find(:link, 'has-been-double-clicked')
875
- locations = link.text.match(/^Has been double clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
887
+ locations = link.text.match(/^Has been double clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
876
888
  # Resulting click location should be very close to 10, 5 relative to top left corner of the element, but may not be exact due
877
889
  # to integer/float conversions and rounding.
878
890
  expect(locations[:x].to_f).to be_within(1).of(10)
@@ -891,7 +903,10 @@ Capybara::SpecHelper.spec 'node' do
891
903
  context 'offset', requires: [:js] do
892
904
  before do
893
905
  @session.visit('/offset')
894
- @clicker = @session.find(:id, 'clicker')
906
+ end
907
+
908
+ let :clicker do
909
+ @session.find(:id, 'clicker')
895
910
  end
896
911
 
897
912
  context 'when w3c_click_offset is false' do
@@ -900,17 +915,17 @@ Capybara::SpecHelper.spec 'node' do
900
915
  end
901
916
 
902
917
  it 'should offset from top left of element' do
903
- @clicker.double_click(x: 10, y: 5)
918
+ clicker.double_click(x: 10, y: 5)
904
919
  expect(@session).to have_text(/clicked at 110,105/)
905
920
  end
906
921
 
907
922
  it 'should offset outside the element' do
908
- @clicker.double_click(x: -15, y: -10)
923
+ clicker.double_click(x: -15, y: -10)
909
924
  expect(@session).to have_text(/clicked at 85,90/)
910
925
  end
911
926
 
912
927
  it 'should default to click the middle' do
913
- @clicker.double_click
928
+ clicker.double_click
914
929
  expect(@session).to have_text(/clicked at 150,150/)
915
930
  end
916
931
  end
@@ -921,17 +936,17 @@ Capybara::SpecHelper.spec 'node' do
921
936
  end
922
937
 
923
938
  it 'should offset from center of element' do
924
- @clicker.double_click(x: 10, y: 5)
939
+ clicker.double_click(x: 10, y: 5)
925
940
  expect(@session).to have_text(/clicked at 160,155/)
926
941
  end
927
942
 
928
943
  it 'should offset outside from center of element' do
929
- @clicker.double_click(x: -65, y: -60)
944
+ clicker.double_click(x: -65, y: -60)
930
945
  expect(@session).to have_text(/clicked at 85,90/)
931
946
  end
932
947
 
933
948
  it 'should default to click the middle' do
934
- @clicker.double_click
949
+ clicker.double_click
935
950
  expect(@session).to have_text(/clicked at 150,150/)
936
951
  end
937
952
  end
@@ -955,7 +970,7 @@ Capybara::SpecHelper.spec 'node' do
955
970
  @session.visit('with_js')
956
971
  @session.find(:css, '#click-test').right_click(x: 10, y: 10)
957
972
  link = @session.find(:link, 'has-been-right-clicked')
958
- locations = link.text.match(/^Has been right clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
973
+ locations = link.text.match(/^Has been right clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
959
974
  # Resulting click location should be very close to 10, 10 relative to top left corner of the element, but may not be exact due
960
975
  # to integer/float conversions and rounding
961
976
  expect(locations[:x].to_f).to be_within(1).of(10)
@@ -974,7 +989,10 @@ Capybara::SpecHelper.spec 'node' do
974
989
  context 'offset', requires: [:js] do
975
990
  before do
976
991
  @session.visit('/offset')
977
- @clicker = @session.find(:id, 'clicker')
992
+ end
993
+
994
+ let :clicker do
995
+ @session.find(:id, 'clicker')
978
996
  end
979
997
 
980
998
  context 'when w3c_click_offset is false' do
@@ -983,17 +1001,17 @@ Capybara::SpecHelper.spec 'node' do
983
1001
  end
984
1002
 
985
1003
  it 'should offset from top left of element' do
986
- @clicker.right_click(x: 10, y: 5)
1004
+ clicker.right_click(x: 10, y: 5)
987
1005
  expect(@session).to have_text(/clicked at 110,105/)
988
1006
  end
989
1007
 
990
1008
  it 'should offset outside the element' do
991
- @clicker.right_click(x: -15, y: -10)
1009
+ clicker.right_click(x: -15, y: -10)
992
1010
  expect(@session).to have_text(/clicked at 85,90/)
993
1011
  end
994
1012
 
995
1013
  it 'should default to click the middle' do
996
- @clicker.right_click
1014
+ clicker.right_click
997
1015
  expect(@session).to have_text(/clicked at 150,150/)
998
1016
  end
999
1017
  end
@@ -1004,21 +1022,30 @@ Capybara::SpecHelper.spec 'node' do
1004
1022
  end
1005
1023
 
1006
1024
  it 'should offset from center of element' do
1007
- @clicker.right_click(x: 10, y: 5)
1025
+ clicker.right_click(x: 10, y: 5)
1008
1026
  expect(@session).to have_text(/clicked at 160,155/)
1009
1027
  end
1010
1028
 
1011
1029
  it 'should offset outside from center of element' do
1012
- @clicker.right_click(x: -65, y: -60)
1030
+ clicker.right_click(x: -65, y: -60)
1013
1031
  expect(@session).to have_text(/clicked at 85,90/)
1014
1032
  end
1015
1033
 
1016
1034
  it 'should default to click the middle' do
1017
- @clicker.right_click
1035
+ clicker.right_click
1018
1036
  expect(@session).to have_text(/clicked at 150,150/)
1019
1037
  end
1020
1038
  end
1021
1039
  end
1040
+
1041
+ context 'delay', requires: [:js] do
1042
+ it 'should delay the mouse up' do
1043
+ @session.visit('with_js')
1044
+ @session.find(:css, '#click-test').right_click(delay: 2)
1045
+ delay = @session.evaluate_script('window.right_click_delay')
1046
+ expect(delay).to be >= 2
1047
+ end
1048
+ end
1022
1049
  end
1023
1050
 
1024
1051
  describe '#send_keys', requires: [:send_keys] do