capybara 2.18.0 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +26 -1
  3. data/README.md +12 -12
  4. data/lib/capybara.rb +13 -25
  5. data/lib/capybara/config.rb +11 -57
  6. data/lib/capybara/cucumber.rb +2 -3
  7. data/lib/capybara/driver/base.rb +5 -16
  8. data/lib/capybara/driver/node.rb +5 -4
  9. data/lib/capybara/dsl.rb +1 -0
  10. data/lib/capybara/helpers.rb +16 -28
  11. data/lib/capybara/minitest.rb +139 -138
  12. data/lib/capybara/minitest/spec.rb +15 -14
  13. data/lib/capybara/node/actions.rb +59 -81
  14. data/lib/capybara/node/base.rb +11 -18
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +8 -8
  17. data/lib/capybara/node/element.rb +30 -40
  18. data/lib/capybara/node/finders.rb +62 -70
  19. data/lib/capybara/node/matchers.rb +48 -71
  20. data/lib/capybara/node/simple.rb +11 -17
  21. data/lib/capybara/queries/ancestor_query.rb +4 -6
  22. data/lib/capybara/queries/base_query.rb +18 -17
  23. data/lib/capybara/queries/current_path_query.rb +8 -24
  24. data/lib/capybara/queries/match_query.rb +3 -7
  25. data/lib/capybara/queries/selector_query.rb +92 -95
  26. data/lib/capybara/queries/sibling_query.rb +4 -4
  27. data/lib/capybara/queries/text_query.rb +37 -34
  28. data/lib/capybara/queries/title_query.rb +8 -11
  29. data/lib/capybara/rack_test/browser.rb +15 -18
  30. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  31. data/lib/capybara/rack_test/driver.rb +6 -10
  32. data/lib/capybara/rack_test/form.rb +50 -40
  33. data/lib/capybara/rack_test/node.rb +70 -56
  34. data/lib/capybara/rails.rb +2 -6
  35. data/lib/capybara/result.rb +22 -22
  36. data/lib/capybara/rspec.rb +5 -10
  37. data/lib/capybara/rspec/compound.rb +5 -10
  38. data/lib/capybara/rspec/features.rb +17 -48
  39. data/lib/capybara/rspec/matcher_proxies.rb +31 -15
  40. data/lib/capybara/rspec/matchers.rb +70 -60
  41. data/lib/capybara/selector.rb +129 -117
  42. data/lib/capybara/selector/css.rb +6 -11
  43. data/lib/capybara/selector/filter.rb +1 -17
  44. data/lib/capybara/selector/filter_set.rb +17 -14
  45. data/lib/capybara/selector/filters/base.rb +7 -6
  46. data/lib/capybara/selector/filters/expression_filter.rb +6 -23
  47. data/lib/capybara/selector/filters/node_filter.rb +2 -12
  48. data/lib/capybara/selector/selector.rb +27 -33
  49. data/lib/capybara/selenium/driver.rb +113 -127
  50. data/lib/capybara/selenium/node.rb +148 -113
  51. data/lib/capybara/server.rb +3 -2
  52. data/lib/capybara/session.rb +137 -223
  53. data/lib/capybara/session/config.rb +47 -67
  54. data/lib/capybara/session/matchers.rb +8 -7
  55. data/lib/capybara/spec/public/test.js +26 -4
  56. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
  57. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
  58. data/lib/capybara/spec/session/accept_prompt_spec.rb +1 -0
  59. data/lib/capybara/spec/session/all_spec.rb +31 -18
  60. data/lib/capybara/spec/session/ancestor_spec.rb +2 -4
  61. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
  62. data/lib/capybara/spec/session/assert_current_path.rb +12 -11
  63. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  64. data/lib/capybara/spec/session/assert_text.rb +18 -17
  65. data/lib/capybara/spec/session/assert_title.rb +1 -0
  66. data/lib/capybara/spec/session/attach_file_spec.rb +14 -13
  67. data/lib/capybara/spec/session/body_spec.rb +1 -0
  68. data/lib/capybara/spec/session/check_spec.rb +7 -6
  69. data/lib/capybara/spec/session/choose_spec.rb +5 -4
  70. data/lib/capybara/spec/session/click_button_spec.rb +20 -28
  71. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
  72. data/lib/capybara/spec/session/click_link_spec.rb +8 -7
  73. data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
  74. data/lib/capybara/spec/session/current_url_spec.rb +7 -6
  75. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
  76. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
  77. data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
  78. data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
  79. data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
  80. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +3 -2
  81. data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
  82. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  83. data/lib/capybara/spec/session/fill_in_spec.rb +6 -5
  84. data/lib/capybara/spec/session/find_button_spec.rb +4 -3
  85. data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
  86. data/lib/capybara/spec/session/find_field_spec.rb +8 -14
  87. data/lib/capybara/spec/session/find_link_spec.rb +6 -5
  88. data/lib/capybara/spec/session/find_spec.rb +37 -31
  89. data/lib/capybara/spec/session/first_spec.rb +60 -33
  90. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  91. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  92. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  93. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  94. data/lib/capybara/spec/session/has_all_selectors_spec.rb +15 -15
  95. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  96. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  97. data/lib/capybara/spec/session/has_current_path_spec.rb +12 -28
  98. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  99. data/lib/capybara/spec/session/has_link_spec.rb +1 -0
  100. data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
  101. data/lib/capybara/spec/session/has_select_spec.rb +30 -29
  102. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  103. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  104. data/lib/capybara/spec/session/has_text_spec.rb +6 -5
  105. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  106. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  107. data/lib/capybara/spec/session/headers.rb +2 -1
  108. data/lib/capybara/spec/session/html_spec.rb +1 -0
  109. data/lib/capybara/spec/session/node_spec.rb +91 -56
  110. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  111. data/lib/capybara/spec/session/refresh_spec.rb +4 -2
  112. data/lib/capybara/spec/session/reset_session_spec.rb +1 -0
  113. data/lib/capybara/spec/session/response_code.rb +1 -0
  114. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  115. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  116. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  117. data/lib/capybara/spec/session/save_screenshot_spec.rb +1 -1
  118. data/lib/capybara/spec/session/select_spec.rb +20 -20
  119. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  120. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  121. data/lib/capybara/spec/session/text_spec.rb +1 -0
  122. data/lib/capybara/spec/session/title_spec.rb +1 -1
  123. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  124. data/lib/capybara/spec/session/unselect_spec.rb +6 -5
  125. data/lib/capybara/spec/session/visit_spec.rb +9 -3
  126. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  127. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  128. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  129. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  130. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  131. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  132. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  133. data/lib/capybara/spec/session/window/within_window_spec.rb +13 -68
  134. data/lib/capybara/spec/session/within_spec.rb +1 -0
  135. data/lib/capybara/spec/spec_helper.rb +26 -18
  136. data/lib/capybara/spec/test_app.rb +8 -9
  137. data/lib/capybara/spec/views/form.erb +1 -0
  138. data/lib/capybara/spec/views/with_html.erb +3 -1
  139. data/lib/capybara/spec/views/within_frames.erb +4 -1
  140. data/lib/capybara/version.rb +2 -1
  141. data/lib/capybara/window.rb +6 -10
  142. data/spec/basic_node_spec.rb +1 -0
  143. data/spec/capybara_spec.rb +9 -32
  144. data/spec/dsl_spec.rb +5 -13
  145. data/spec/filter_set_spec.rb +5 -4
  146. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  147. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  148. data/spec/minitest_spec.rb +4 -3
  149. data/spec/minitest_spec_spec.rb +3 -2
  150. data/spec/per_session_config_spec.rb +9 -8
  151. data/spec/rack_test_spec.rb +21 -20
  152. data/spec/result_spec.rb +17 -16
  153. data/spec/rspec/features_spec.rb +17 -14
  154. data/spec/rspec/scenarios_spec.rb +5 -7
  155. data/spec/rspec/shared_spec_matchers.rb +96 -99
  156. data/spec/rspec/views_spec.rb +2 -1
  157. data/spec/rspec_matchers_spec.rb +19 -2
  158. data/spec/rspec_spec.rb +11 -15
  159. data/spec/selector_spec.rb +5 -6
  160. data/spec/selenium_spec_chrome.rb +7 -4
  161. data/spec/selenium_spec_marionette.rb +26 -12
  162. data/spec/server_spec.rb +33 -33
  163. data/spec/session_spec.rb +2 -1
  164. data/spec/shared_selenium_session.rb +27 -21
  165. data/spec/spec_helper.rb +2 -5
  166. metadata +66 -87
  167. data/lib/capybara/query.rb +0 -7
  168. data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#has_table?' do
3
4
  before do
4
5
  @session.visit('/tables')
@@ -7,7 +8,7 @@ Capybara::SpecHelper.spec '#has_table?' do
7
8
  it "should be true if the table is on the page" do
8
9
  expect(@session).to have_table('Villain')
9
10
  expect(@session).to have_table('villain_table')
10
- expect(@session).to have_table(:'villain_table')
11
+ expect(@session).to have_table(:villain_table)
11
12
  end
12
13
 
13
14
  it "should be false if the table is not on the page" do
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#has_text?' do
3
4
  it "should be true if the given text is on the page at least once" do
4
5
  @session.visit('/with_html')
5
6
  expect(@session).to have_text('est')
6
7
  expect(@session).to have_text('Lorem')
7
8
  expect(@session).to have_text('Redirect')
8
- expect(@session).to have_text(:'Redirect')
9
+ expect(@session).to have_text(:Redirect)
9
10
  end
10
11
 
11
12
  it "should be true if scoped to an element which has the text" do
@@ -51,12 +52,12 @@ Capybara::SpecHelper.spec '#has_text?' do
51
52
 
52
53
  it 'should handle double quotes in the text' do
53
54
  @session.visit('/with-quotes')
54
- expect(@session).to have_text(%q{"No," he said})
55
+ expect(@session).to have_text('"No," he said')
55
56
  end
56
57
 
57
58
  it 'should handle mixed single and double quotes in the text' do
58
59
  @session.visit('/with-quotes')
59
- expect(@session).to have_text(%q{"you can't do that."})
60
+ expect(@session).to have_text(%q("you can't do that."))
60
61
  end
61
62
 
62
63
  it 'should be false if text is in the title tag in the head' do
@@ -265,12 +266,12 @@ Capybara::SpecHelper.spec '#has_no_text?' do
265
266
 
266
267
  it 'should handle double quotes in the text' do
267
268
  @session.visit('/with-quotes')
268
- expect(@session).not_to have_no_text(%q{"No," he said})
269
+ expect(@session).not_to have_no_text('"No," he said')
269
270
  end
270
271
 
271
272
  it 'should handle mixed single and double quotes in the text' do
272
273
  @session.visit('/with-quotes')
273
- expect(@session).not_to have_no_text(%q{"you can't do that."})
274
+ expect(@session).not_to have_no_text(%q("you can't do that."))
274
275
  end
275
276
 
276
277
  it 'should be true if text is in the title tag in the head' do
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#has_title?' do
3
4
  before do
4
5
  @session.visit('/with_js')
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#has_xpath?' do
3
4
  before do
4
5
  @session.visit('/with_html')
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#response_headers' do
3
4
  it "should return response headers", requires: [:response_headers] do
4
5
  @session.visit('/with_simple_html')
5
- expect(@session.response_headers['Content-Type']).to match %r(text/html)
6
+ expect(@session.response_headers['Content-Type']).to match %r{text/html}
6
7
  end
7
8
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#html' do
3
4
  it "should return the unmodified page body" do
4
5
  @session.visit('/')
@@ -27,14 +27,6 @@ Capybara::SpecHelper.spec "node" do
27
27
  end
28
28
  end
29
29
 
30
- describe "#parent" do
31
- it "should be deprecated" do
32
- @node = @session.find(:css, '#first')
33
- expect(@node).to receive(:warn).with(/^DEPRECATED:/)
34
- expect(@node.parent).to eq(@node.query_scope)
35
- end
36
- end
37
-
38
30
  describe "#text" do
39
31
  it "should extract node texts" do
40
32
  expect(@session.all('//a')[0].text).to eq('labore')
@@ -102,44 +94,32 @@ Capybara::SpecHelper.spec "node" do
102
94
  expect(@session.first('//input').value).to eq('')
103
95
  end
104
96
 
105
- it "should not set if the text field is readonly" do
106
- expect(@session.first('//input[@readonly]').value).to eq('should not change')
107
- @session.first('//input[@readonly]').set('changed')
108
- expect(@session.first('//input[@readonly]').value).to eq('should not change')
109
- end
110
-
111
97
  it "should raise if the text field is readonly" do
112
- expect(@session.first('//input[@readonly]').set('changed')).to raise_error(Capybara::ReadOnlyElementError)
113
- end if Capybara::VERSION.to_f > 3.0
114
-
115
- it "should not set if the textarea is readonly" do
116
- expect(@session.first('//textarea[@readonly]').value).to eq('textarea should not change')
117
- @session.first('//textarea[@readonly]').set('changed')
118
- expect(@session.first('//textarea[@readonly]').value).to eq('textarea should not change')
98
+ expect { @session.first('//input[@readonly]').set('changed') }.to raise_error(Capybara::ReadOnlyElementError)
119
99
  end
120
100
 
121
101
  it "should raise if the text field is readonly" do
122
- expect(@session.first('//textarea[@readonly]').set('changed')).to raise_error(Capybara::ReadOnlyElementError)
123
- end if Capybara::VERSION.to_f > 3.0
102
+ expect { @session.first('//textarea[@readonly]').set('changed') }.to raise_error(Capybara::ReadOnlyElementError)
103
+ end
124
104
 
125
105
  context "with a contenteditable element", requires: [:js] do
126
106
  it 'should allow me to change the contents' do
127
107
  @session.visit('/with_js')
128
- @session.find(:css,'#existing_content_editable').set('WYSIWYG')
129
- expect(@session.find(:css,'#existing_content_editable').text).to eq('WYSIWYG')
108
+ @session.find(:css, '#existing_content_editable').set('WYSIWYG')
109
+ expect(@session.find(:css, '#existing_content_editable').text).to eq('WYSIWYG')
130
110
  end
131
111
 
132
112
  it 'should allow me to set the contents' do
133
113
  @session.visit('/with_js')
134
- @session.find(:css,'#blank_content_editable').set('WYSIWYG')
135
- expect(@session.find(:css,'#blank_content_editable').text).to eq('WYSIWYG')
114
+ @session.find(:css, '#blank_content_editable').set('WYSIWYG')
115
+ expect(@session.find(:css, '#blank_content_editable').text).to eq('WYSIWYG')
136
116
  end
137
117
 
138
118
  it 'should allow me to change the contents of a child element' do
139
119
  @session.visit('/with_js')
140
- @session.find(:css,'#existing_content_editable_child').set('WYSIWYG')
141
- expect(@session.find(:css,'#existing_content_editable_child').text).to eq('WYSIWYG')
142
- expect(@session.find(:css,'#existing_content_editable_child_parent').text).to eq('Some content WYSIWYG')
120
+ @session.find(:css, '#existing_content_editable_child').set('WYSIWYG')
121
+ expect(@session.find(:css, '#existing_content_editable_child').text).to eq('WYSIWYG')
122
+ expect(@session.find(:css, '#existing_content_editable_child_parent').text).to eq('Some content WYSIWYG')
143
123
  end
144
124
  end
145
125
  end
@@ -258,9 +238,9 @@ Capybara::SpecHelper.spec "node" do
258
238
 
259
239
  describe "#==" do
260
240
  it "preserve object identity" do
261
- expect(@session.find('//h1') == @session.find('//h1')).to be true
262
- expect(@session.find('//h1') === @session.find('//h1')).to be true
263
- expect(@session.find('//h1').eql? @session.find('//h1')).to be false
241
+ expect(@session.find('//h1') == @session.find('//h1')).to be true # rubocop:disable Lint/UselessComparison
242
+ expect(@session.find('//h1') === @session.find('//h1')).to be true # rubocop:disable Style/CaseEquality, Lint/UselessComparison
243
+ expect(@session.find('//h1').eql?(@session.find('//h1'))).to be false
264
244
  end
265
245
 
266
246
  it "returns false for unrelated object" do
@@ -281,7 +261,7 @@ Capybara::SpecHelper.spec "node" do
281
261
  end
282
262
  end
283
263
 
284
- describe "#trigger", requires: [:js, :trigger] do
264
+ describe "#trigger", requires: %i[js trigger] do
285
265
  it "should allow triggering of custom JS events" do
286
266
  @session.visit('/with_js')
287
267
  @session.find(:css, '#with_focus_event').trigger(:focus)
@@ -289,7 +269,7 @@ Capybara::SpecHelper.spec "node" do
289
269
  end
290
270
  end
291
271
 
292
- describe '#drag_to', requires: [:js, :drag] do
272
+ describe '#drag_to', requires: %i[js drag] do
293
273
  it "should drag and drop an object" do
294
274
  @session.visit('/with_js')
295
275
  element = @session.find('//div[@id="drag"]')
@@ -311,14 +291,14 @@ Capybara::SpecHelper.spec "node" do
311
291
  it "should allow hovering on an element" do
312
292
  @session.visit('/with_hover')
313
293
  expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible
314
- @session.find(:css,'.wrapper:not(.scroll_needed)').hover
294
+ @session.find(:css, '.wrapper:not(.scroll_needed)').hover
315
295
  expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
316
296
  end
317
297
 
318
298
  it "should allow hovering on an element that needs to be scrolled into view" do
319
299
  @session.visit('/with_hover')
320
300
  expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible
321
- @session.find(:css,'.wrapper.scroll_needed').hover
301
+ @session.find(:css, '.wrapper.scroll_needed').hover
322
302
  expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible
323
303
  end
324
304
  end
@@ -358,15 +338,59 @@ Capybara::SpecHelper.spec "node" do
358
338
  radio.click
359
339
  expect(radio).to be_checked
360
340
  end
341
+
342
+ it "should allow modifiers", requires: [:js] do
343
+ @session.visit('/with_js')
344
+ @session.find(:css, '#click-test').click(:shift)
345
+ expect(@session).to have_link('Has been shift clicked')
346
+ end
347
+
348
+ it "should allow multiple modifiers", requires: [:js] do
349
+ @session.visit('with_js')
350
+ @session.find(:css, '#click-test').click(:control, :alt, :meta, :shift)
351
+ # Selenium with Chrome on OSX ctrl-click generates a right click so just verify all keys but not click type
352
+ expect(@session).to have_link("alt control meta shift")
353
+ end
354
+
355
+ it "should allow to adjust the click offset", requires: [:js] do
356
+ @session.visit('with_js')
357
+ @session.find(:css, '#click-test').click(x: 5, y: 5)
358
+ link = @session.find(:link, 'has-been-clicked')
359
+ locations = link.text.match(/^Has been clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
360
+ # 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
361
+ # integer/float conversions and rounding.
362
+ expect(locations[:x].to_f).to be_within(1).of(5)
363
+ expect(locations[:y].to_f).to be_within(1).of(5)
364
+ end
361
365
  end
362
366
 
363
367
  describe '#double_click', requires: [:js] do
368
+ before do
369
+ pending "selenium-webdriver/geckodriver doesn't generate double click event" if marionette_lt?(59, @session)
370
+ end
371
+
364
372
  it "should double click an element" do
365
- pending "selenium-webdriver/geckodriver doesn't generate double click event" if marionette?(@session)
366
373
  @session.visit('/with_js')
367
374
  @session.find(:css, '#click-test').double_click
368
375
  expect(@session.find(:css, '#has-been-double-clicked')).to be
369
376
  end
377
+
378
+ it "should allow modifiers", requires: [:js] do
379
+ @session.visit('/with_js')
380
+ @session.find(:css, '#click-test').double_click(:alt)
381
+ expect(@session).to have_link('Has been alt double clicked')
382
+ end
383
+
384
+ it "should allow to adjust the offset", requires: [:js] do
385
+ @session.visit('with_js')
386
+ @session.find(:css, '#click-test').double_click(x: 10, y: 5)
387
+ link = @session.find(:link, 'has-been-double-clicked')
388
+ locations = link.text.match(/^Has been double clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
389
+ # Resulting click location should be very close to 10, 5 relative to top left corner of the element, but may not be exact due
390
+ # to integer/float conversions and rounding.
391
+ expect(locations[:x].to_f).to be_within(1).of(10)
392
+ expect(locations[:y].to_f).to be_within(1).of(5)
393
+ end
370
394
  end
371
395
 
372
396
  describe '#right_click', requires: [:js] do
@@ -375,6 +399,23 @@ Capybara::SpecHelper.spec "node" do
375
399
  @session.find(:css, '#click-test').right_click
376
400
  expect(@session.find(:css, '#has-been-right-clicked')).to be
377
401
  end
402
+
403
+ it "should allow modifiers", requires: [:js] do
404
+ @session.visit('/with_js')
405
+ @session.find(:css, '#click-test').right_click(:meta)
406
+ expect(@session).to have_link('Has been meta right clicked')
407
+ end
408
+
409
+ it "should allow to adjust the offset", requires: [:js] do
410
+ @session.visit('with_js')
411
+ @session.find(:css, '#click-test').right_click(x: 10, y: 10)
412
+ link = @session.find(:link, 'has-been-right-clicked')
413
+ locations = link.text.match(/^Has been right clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
414
+ # Resulting click location should be very close to 10, 10 relative to top left corner of the element, but may not be exact due
415
+ # to integer/float conversions and rounding
416
+ expect(locations[:x].to_f).to be_within(1).of(10)
417
+ expect(locations[:y].to_f).to be_within(1).of(10)
418
+ end
378
419
  end
379
420
 
380
421
  describe '#send_keys', requires: [:send_keys] do
@@ -398,10 +439,10 @@ Capybara::SpecHelper.spec "node" do
398
439
  expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'
399
440
  end
400
441
 
401
- it "should generate key events", requires: [:send_keys, :js] do
442
+ it "should generate key events", requires: %i[send_keys js] do
402
443
  pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
403
444
  @session.visit('/with_js')
404
- @session.find(:css, '#with-key-events').send_keys([:shift,'t'], [:shift,'w'])
445
+ @session.find(:css, '#with-key-events').send_keys([:shift, 't'], [:shift, 'w'])
405
446
  expect(@session.find(:css, '#key-events-output')).to have_text('keydown:16 keydown:84 keydown:16 keydown:87')
406
447
  end
407
448
  end
@@ -434,9 +475,9 @@ Capybara::SpecHelper.spec "node" do
434
475
  sleep(0.3)
435
476
  expect do
436
477
  expect(node).to have_text('has been reloaded')
437
- end.to raise_error do |error|
478
+ end.to(raise_error do |error|
438
479
  expect(error).to be_an_invalid_element_error(@session)
439
- end
480
+ end)
440
481
  end
441
482
  after { Capybara.automatic_reload = true }
442
483
  end
@@ -478,14 +519,10 @@ Capybara::SpecHelper.spec "node" do
478
519
 
479
520
  expect do
480
521
  expect(node).to have_text('Foo')
481
- end.to raise_error { |error|
482
- expect(error).to be_an_invalid_element_error(@session)
483
- }
522
+ end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })
484
523
  expect do
485
524
  expect(node).to have_text('Bar')
486
- end.to raise_error { |error|
487
- expect(error).to be_an_invalid_element_error(@session)
488
- }
525
+ end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })
489
526
  end
490
527
 
491
528
  it "should reload nodes with options" do
@@ -499,26 +536,24 @@ Capybara::SpecHelper.spec "node" do
499
536
  end
500
537
 
501
538
  context "when #synchronize raises server errors" do
502
- it "sets an explanatory exception as the cause of server exceptions", requires: [:server, :js] do
503
- skip "This version of ruby doesn't support exception causes" unless Exception.instance_methods.include? :cause
539
+ it "sets an explanatory exception as the cause of server exceptions", requires: %i[server js] do
504
540
  quietly { @session.visit("/error") }
505
541
  expect do
506
542
  @session.find(:css, 'span')
507
- end.to raise_error(TestApp::TestAppError) do |e|
543
+ end.to(raise_error(TestApp::TestAppError) do |e|
508
544
  expect(e.cause).to be_a Capybara::CapybaraError
509
545
  expect(e.cause.message).to match(/Your application server raised an error/)
510
- end
546
+ end)
511
547
  end
512
548
 
513
- it "sets an explanatory exception as the cause of server exceptions with errors with initializers", requires: [:server, :js] do
514
- skip "This version of ruby doesn't support exception causes" unless Exception.instance_methods.include? :cause
549
+ it "sets an explanatory exception as the cause of server exceptions with errors with initializers", requires: %i[server js] do
515
550
  quietly { @session.visit("/other_error") }
516
551
  expect do
517
552
  @session.find(:css, 'span')
518
- end.to raise_error(TestApp::TestAppOtherError) do |e|
553
+ end.to(raise_error(TestApp::TestAppOtherError) do |e|
519
554
  expect(e.cause).to be_a Capybara::CapybaraError
520
555
  expect(e.cause.message).to match(/Your application server raised an error/)
521
- end
556
+ end)
522
557
  end
523
558
  end
524
559
 
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec "#to_capybara_node" do
4
+ before do
5
+ @session.visit('/with_html')
6
+ end
7
+
8
+ class NodeWrapper
9
+ def initialize(element); @element = element end
10
+ def to_capybara_node(); @element end
11
+ end
12
+
13
+ it "should support have_xxx expectations" do
14
+ para = NodeWrapper.new(@session.find(:css, '#first'))
15
+ expect(para).to have_link("ullamco")
16
+ end
17
+
18
+ it "should support within" do
19
+ para = NodeWrapper.new(@session.find(:css, '#first'))
20
+ expect(@session).to have_css('#second')
21
+ @session.within(para) do
22
+ expect(@session).to have_link('ullamco')
23
+ expect(@session).not_to have_css('#second')
24
+ end
25
+ end
26
+
27
+ it "should generate correct errors" do
28
+ para = NodeWrapper.new(@session.find(:css, '#first'))
29
+ expect do
30
+ expect(para).to have_text("Header Class Test One")
31
+ end.to raise_error(/^expected to find text "Header Class Test One" in "Lore/)
32
+ expect do
33
+ expect(para).to have_css('#second')
34
+ end.to raise_error(/^expected to find visible css "#second" within #<Capybara::Node::Element/)
35
+ end
36
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#refresh' do
3
4
  it "reload the page" do
4
5
  @session.visit('/form')
@@ -17,12 +18,13 @@ Capybara::SpecHelper.spec '#refresh' do
17
18
  end
18
19
 
19
20
  it "it reposts" do
21
+ skip "Firefox insists on prompting without providing a way to suppress" if marionette?(@session)
20
22
  @session.visit('/form')
21
23
  @session.select('Sweden', from: 'form_region')
22
24
  @session.click_button('awesome')
23
- expect {
25
+ expect do
24
26
  @session.refresh
25
27
  sleep 2
26
- }.to change{ extract_results(@session)['post_count'] }.by(1)
28
+ end.to change { extract_results(@session)['post_count'] }.by(1)
27
29
  end
28
30
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#reset_session!' do
3
4
  it "removes cookies" do
4
5
  @session.visit('/set_cookie')
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#status_code' do
3
4
  it "should return response codes", requires: [:status_code] do
4
5
  @session.visit('/with_simple_html')
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'launchy'
3
4
 
4
5
  Capybara::SpecHelper.spec '#save_and_open_page' do
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'launchy'
3
4
 
4
5
  Capybara::SpecHelper.spec '#save_and_open_screenshot' do
@@ -13,8 +14,8 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
13
14
 
14
15
  @session.save_and_open_screenshot
15
16
 
16
- expect(@session.driver).to have_received(:save_screenshot).
17
- with(expected_file_regex, {})
17
+ expect(@session.driver).to have_received(:save_screenshot)
18
+ .with(expected_file_regex, {})
18
19
  expect(Launchy).to have_received(:open).with(expected_file_regex)
19
20
  end
20
21
 
@@ -25,8 +26,8 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
25
26
 
26
27
  @session.save_and_open_screenshot(custom_path)
27
28
 
28
- expect(@session.driver).to have_received(:save_screenshot).
29
- with(/#{custom_path}$/, {})
29
+ expect(@session.driver).to have_received(:save_screenshot)
30
+ .with(/#{custom_path}$/, {})
30
31
  expect(Launchy).to have_received(:open).with(/#{custom_path}$/)
31
32
  end
32
33
 
@@ -34,14 +35,8 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
34
35
  it 'prints out a correct warning message', requires: [:screenshot] do
35
36
  file_path = File.join(Dir.tmpdir, 'test.png')
36
37
  allow(@session).to receive(:require).with('launchy').and_raise(LoadError)
37
- allow(@session).to receive(:warn)
38
-
38
+ expect(@session).to receive(:warn).with("File saved to #{file_path}.\nPlease install the launchy gem to open the file automatically.")
39
39
  @session.save_and_open_screenshot(file_path)
40
-
41
- expect(@session).to have_received(:warn).
42
- with("File saved to #{file_path}.")
43
- expect(@session).to have_received(:warn).
44
- with('Please install the launchy gem to open the file automatically.')
45
40
  end
46
41
  end
47
42
  end