capybara 2.18.0 → 3.0.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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +55 -1
  3. data/README.md +18 -17
  4. data/lib/capybara/config.rb +11 -58
  5. data/lib/capybara/cucumber.rb +2 -3
  6. data/lib/capybara/driver/base.rb +15 -16
  7. data/lib/capybara/driver/node.rb +5 -4
  8. data/lib/capybara/dsl.rb +1 -0
  9. data/lib/capybara/helpers.rb +19 -29
  10. data/lib/capybara/minitest/spec.rb +15 -14
  11. data/lib/capybara/minitest.rb +139 -138
  12. data/lib/capybara/node/actions.rb +60 -81
  13. data/lib/capybara/node/base.rb +11 -18
  14. data/lib/capybara/node/document.rb +2 -2
  15. data/lib/capybara/node/document_matchers.rb +8 -8
  16. data/lib/capybara/node/element.rb +30 -40
  17. data/lib/capybara/node/finders.rb +62 -70
  18. data/lib/capybara/node/matchers.rb +50 -71
  19. data/lib/capybara/node/simple.rb +11 -17
  20. data/lib/capybara/queries/ancestor_query.rb +11 -7
  21. data/lib/capybara/queries/base_query.rb +22 -18
  22. data/lib/capybara/queries/current_path_query.rb +8 -24
  23. data/lib/capybara/queries/match_query.rb +3 -7
  24. data/lib/capybara/queries/selector_query.rb +92 -95
  25. data/lib/capybara/queries/sibling_query.rb +4 -4
  26. data/lib/capybara/queries/text_query.rb +35 -35
  27. data/lib/capybara/queries/title_query.rb +8 -11
  28. data/lib/capybara/rack_test/browser.rb +15 -18
  29. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  30. data/lib/capybara/rack_test/driver.rb +6 -10
  31. data/lib/capybara/rack_test/form.rb +50 -40
  32. data/lib/capybara/rack_test/node.rb +93 -63
  33. data/lib/capybara/rails.rb +2 -6
  34. data/lib/capybara/result.rb +22 -22
  35. data/lib/capybara/rspec/compound.rb +5 -10
  36. data/lib/capybara/rspec/features.rb +17 -48
  37. data/lib/capybara/rspec/matcher_proxies.rb +31 -15
  38. data/lib/capybara/rspec/matchers.rb +70 -61
  39. data/lib/capybara/rspec.rb +5 -10
  40. data/lib/capybara/selector/css.rb +6 -11
  41. data/lib/capybara/selector/filter.rb +1 -17
  42. data/lib/capybara/selector/filter_set.rb +18 -15
  43. data/lib/capybara/selector/filters/base.rb +7 -6
  44. data/lib/capybara/selector/filters/expression_filter.rb +6 -23
  45. data/lib/capybara/selector/filters/node_filter.rb +2 -12
  46. data/lib/capybara/selector/selector.rb +28 -34
  47. data/lib/capybara/selector.rb +129 -117
  48. data/lib/capybara/selenium/driver.rb +131 -125
  49. data/lib/capybara/selenium/node.rb +197 -115
  50. data/lib/capybara/server.rb +3 -2
  51. data/lib/capybara/session/config.rb +47 -67
  52. data/lib/capybara/session/matchers.rb +8 -7
  53. data/lib/capybara/session.rb +138 -224
  54. data/lib/capybara/spec/public/test.js +25 -4
  55. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
  56. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
  57. data/lib/capybara/spec/session/accept_prompt_spec.rb +1 -0
  58. data/lib/capybara/spec/session/all_spec.rb +31 -18
  59. data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
  60. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
  61. data/lib/capybara/spec/session/assert_current_path.rb +12 -11
  62. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  63. data/lib/capybara/spec/session/assert_text.rb +23 -23
  64. data/lib/capybara/spec/session/assert_title.rb +13 -3
  65. data/lib/capybara/spec/session/attach_file_spec.rb +51 -30
  66. data/lib/capybara/spec/session/body_spec.rb +1 -0
  67. data/lib/capybara/spec/session/check_spec.rb +7 -6
  68. data/lib/capybara/spec/session/choose_spec.rb +5 -4
  69. data/lib/capybara/spec/session/click_button_spec.rb +24 -32
  70. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
  71. data/lib/capybara/spec/session/click_link_spec.rb +8 -7
  72. data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
  73. data/lib/capybara/spec/session/current_url_spec.rb +17 -6
  74. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
  75. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
  76. data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
  77. data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
  78. data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
  79. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +3 -2
  80. data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
  81. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  82. data/lib/capybara/spec/session/fill_in_spec.rb +30 -5
  83. data/lib/capybara/spec/session/find_button_spec.rb +4 -3
  84. data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
  85. data/lib/capybara/spec/session/find_field_spec.rb +9 -15
  86. data/lib/capybara/spec/session/find_link_spec.rb +6 -5
  87. data/lib/capybara/spec/session/find_spec.rb +37 -31
  88. data/lib/capybara/spec/session/first_spec.rb +60 -33
  89. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  90. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  91. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  92. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  93. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  94. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  95. data/lib/capybara/spec/session/has_all_selectors_spec.rb +15 -15
  96. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  97. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  98. data/lib/capybara/spec/session/has_current_path_spec.rb +12 -28
  99. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  100. data/lib/capybara/spec/session/has_link_spec.rb +1 -0
  101. data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
  102. data/lib/capybara/spec/session/has_select_spec.rb +30 -29
  103. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  104. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  105. data/lib/capybara/spec/session/has_text_spec.rb +9 -13
  106. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  107. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  108. data/lib/capybara/spec/session/headers.rb +2 -1
  109. data/lib/capybara/spec/session/html_spec.rb +1 -0
  110. data/lib/capybara/spec/session/node_spec.rb +91 -56
  111. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  112. data/lib/capybara/spec/session/refresh_spec.rb +6 -2
  113. data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
  114. data/lib/capybara/spec/session/response_code.rb +1 -0
  115. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  116. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  117. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  118. data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
  119. data/lib/capybara/spec/session/select_spec.rb +20 -20
  120. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  121. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  122. data/lib/capybara/spec/session/text_spec.rb +17 -3
  123. data/lib/capybara/spec/session/title_spec.rb +11 -1
  124. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  125. data/lib/capybara/spec/session/unselect_spec.rb +6 -5
  126. data/lib/capybara/spec/session/visit_spec.rb +9 -3
  127. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  128. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  129. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  130. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  131. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  132. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  133. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  134. data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
  135. data/lib/capybara/spec/session/within_spec.rb +1 -0
  136. data/lib/capybara/spec/spec_helper.rb +34 -18
  137. data/lib/capybara/spec/test_app.rb +17 -9
  138. data/lib/capybara/spec/views/form.erb +7 -0
  139. data/lib/capybara/spec/views/with_html.erb +23 -1
  140. data/lib/capybara/spec/views/within_frames.erb +4 -1
  141. data/lib/capybara/version.rb +2 -1
  142. data/lib/capybara/window.rb +6 -10
  143. data/lib/capybara.rb +28 -25
  144. data/spec/basic_node_spec.rb +1 -0
  145. data/spec/capybara_spec.rb +11 -50
  146. data/spec/dsl_spec.rb +5 -13
  147. data/spec/filter_set_spec.rb +5 -4
  148. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  149. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  150. data/spec/minitest_spec.rb +4 -3
  151. data/spec/minitest_spec_spec.rb +3 -2
  152. data/spec/per_session_config_spec.rb +9 -8
  153. data/spec/rack_test_spec.rb +21 -20
  154. data/spec/result_spec.rb +17 -16
  155. data/spec/rspec/features_spec.rb +17 -14
  156. data/spec/rspec/scenarios_spec.rb +5 -7
  157. data/spec/rspec/shared_spec_matchers.rb +96 -99
  158. data/spec/rspec/views_spec.rb +2 -1
  159. data/spec/rspec_matchers_spec.rb +18 -2
  160. data/spec/rspec_spec.rb +11 -15
  161. data/spec/selector_spec.rb +5 -6
  162. data/spec/selenium_spec_chrome.rb +9 -4
  163. data/spec/selenium_spec_edge.rb +27 -0
  164. data/spec/selenium_spec_ie.rb +31 -0
  165. data/spec/selenium_spec_marionette.rb +28 -12
  166. data/spec/server_spec.rb +33 -33
  167. data/spec/session_spec.rb +2 -1
  168. data/spec/shared_selenium_session.rb +36 -22
  169. data/spec/spec_helper.rb +3 -6
  170. metadata +68 -85
  171. data/lib/capybara/query.rb +0 -7
  172. data/spec/selenium_spec_firefox.rb +0 -68
@@ -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
@@ -28,14 +29,9 @@ Capybara::SpecHelper.spec '#has_text?' do
28
29
  expect(@session).to have_text('exercitation ullamco laboris')
29
30
  end
30
31
 
31
- it "should ignore extra whitespace and newlines" do
32
- @session.visit('/with_html')
33
- expect(@session).to have_text('text with whitespace')
34
- end
35
-
36
- it "should ignore whitespace and newlines in the search string" do
32
+ it "should search correctly normalized text" do
37
33
  @session.visit('/with_html')
38
- expect(@session).to have_text("text with \n\n whitespace")
34
+ expect(@session).to have_text('text with whitespace')
39
35
  end
40
36
 
41
37
  it "should be false if the given text is not on the page" do
@@ -51,12 +47,12 @@ Capybara::SpecHelper.spec '#has_text?' do
51
47
 
52
48
  it 'should handle double quotes in the text' do
53
49
  @session.visit('/with-quotes')
54
- expect(@session).to have_text(%q{"No," he said})
50
+ expect(@session).to have_text('"No," he said')
55
51
  end
56
52
 
57
53
  it 'should handle mixed single and double quotes in the text' do
58
54
  @session.visit('/with-quotes')
59
- expect(@session).to have_text(%q{"you can't do that."})
55
+ expect(@session).to have_text(%q("you can't do that."))
60
56
  end
61
57
 
62
58
  it 'should be false if text is in the title tag in the head' do
@@ -265,12 +261,12 @@ Capybara::SpecHelper.spec '#has_no_text?' do
265
261
 
266
262
  it 'should handle double quotes in the text' do
267
263
  @session.visit('/with-quotes')
268
- expect(@session).not_to have_no_text(%q{"No," he said})
264
+ expect(@session).not_to have_no_text('"No," he said')
269
265
  end
270
266
 
271
267
  it 'should handle mixed single and double quotes in the text' do
272
268
  @session.visit('/with-quotes')
273
- expect(@session).not_to have_no_text(%q{"you can't do that."})
269
+ expect(@session).not_to have_no_text(%q("you can't do that."))
274
270
  end
275
271
 
276
272
  it 'should be true if text is in the title tag in the head' do
@@ -325,7 +321,7 @@ Capybara::SpecHelper.spec '#has_no_text?' do
325
321
  it "should not find element if it appears after given wait duration" do
326
322
  @session.visit('/with_js')
327
323
  @session.click_link('Click me')
328
- expect(@session).to have_no_text('Has been clicked', wait: 0.1)
324
+ expect(@session).to have_no_text('Has been clicked', wait: 0.05)
329
325
  end
330
326
  end
331
327
  end
@@ -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\nWYSIWYG")
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,15 @@ Capybara::SpecHelper.spec '#refresh' do
17
18
  end
18
19
 
19
20
  it "it reposts" do
21
+ if marionette?(@session) || edge?(@session) || ie?(@session)
22
+ skip "Firefox and Edge insist on prompting without providing a way to suppress"
23
+ end
20
24
  @session.visit('/form')
21
25
  @session.select('Sweden', from: 'form_region')
22
26
  @session.click_button('awesome')
23
- expect {
27
+ expect do
24
28
  @session.refresh
25
29
  sleep 2
26
- }.to change{ extract_results(@session)['post_count'] }.by(1)
30
+ end.to change { extract_results(@session)['post_count'] }.by(1)
27
31
  end
28
32
  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')
@@ -62,6 +63,24 @@ Capybara::SpecHelper.spec '#reset_session!' do
62
63
  expect(@session.current_path).to eq("/")
63
64
  end
64
65
 
66
+ it "closes extra windows", requires: [:windows] do
67
+ @session.visit('/with_html')
68
+ @session.open_new_window
69
+ @session.open_new_window
70
+ expect(@session.windows.size).to eq 3
71
+ @session.reset_session!
72
+ expect(@session.windows.size).to eq 1
73
+ end
74
+
75
+ it "closes extra windows when not on the first window", requires: [:windows] do
76
+ @session.visit('/with_html')
77
+ @session.switch_to_window(@session.open_new_window)
78
+ @session.open_new_window
79
+ expect(@session.windows.size).to eq 3
80
+ @session.reset_session!
81
+ expect(@session.windows.size).to eq 1
82
+ end
83
+
65
84
  context "When reuse_server == false" do
66
85
  before do
67
86
  @reuse_server = Capybara.reuse_server
@@ -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
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#save_page' do
3
4
  let(:alternative_path) { File.join(Dir.pwd, "save_and_open_page_tmp") }
4
5
  before do
@@ -6,7 +7,6 @@ Capybara::SpecHelper.spec '#save_page' do
6
7
  end
7
8
 
8
9
  after do
9
- Capybara.save_and_open_page_path = nil
10
10
  Capybara.save_path = nil
11
11
  Dir.glob("capybara-*.html").each do |file|
12
12
  FileUtils.rm(file)
@@ -104,20 +104,4 @@ Capybara::SpecHelper.spec '#save_page' do
104
104
  expect(result).to include("Bar")
105
105
  end
106
106
  end
107
-
108
- context "with deprecated save_and_open_page_path" do
109
- it "can store files in a specified directory" do
110
- Capybara.save_and_open_page_path = alternative_path
111
- @session.save_page
112
- path = Dir.glob(alternative_path + "/capybara-*.html").first
113
- expect(File.read(path)).to include("Another World")
114
- end
115
-
116
- it "returns an absolute path in given directory" do
117
- Capybara.save_and_open_page_path = alternative_path
118
- result = @session.save_page
119
- path = File.expand_path(Dir.glob(alternative_path + "/capybara-*.html").first, alternative_path)
120
- expect(result).to eq(path)
121
- end
122
- end
123
107
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
3
4
  let(:alternative_path) { File.join(Dir.pwd, "save_screenshot_tmp") }
4
5
  before do
@@ -6,7 +7,6 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
6
7
  end
7
8
 
8
9
  after do
9
- Capybara.save_and_open_page_path = nil
10
10
  Capybara.save_path = nil
11
11
  FileUtils.rm_rf alternative_path
12
12
  end
@@ -16,7 +16,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
16
16
 
17
17
  @session.save_screenshot
18
18
 
19
- regexp = Regexp.new(File.expand_path('capybara-\d+\.png'))
19
+ regexp = Regexp.new(File.join(Dir.pwd, 'capybara-\d+\.png'))
20
20
  expect(@session.driver).to have_received(:save_screenshot).with(regexp, {})
21
21
  end
22
22
 
@@ -36,7 +36,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
36
36
 
37
37
  @session.save_screenshot
38
38
 
39
- regexp = Regexp.new(File.expand_path('capybara-\d+\.png', alternative_path))
39
+ regexp = Regexp.new(File.join(alternative_path, 'capybara-\d+\.png'))
40
40
  expect(@session.driver).to have_received(:save_screenshot).with(regexp, {})
41
41
  end
42
42