capybara 2.15.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 (177) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +137 -2
  3. data/README.md +36 -25
  4. data/lib/capybara/config.rb +11 -57
  5. data/lib/capybara/cucumber.rb +2 -3
  6. data/lib/capybara/driver/base.rb +19 -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 +16 -13
  11. data/lib/capybara/minitest.rb +140 -137
  12. data/lib/capybara/node/actions.rb +68 -89
  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 +32 -42
  17. data/lib/capybara/node/finders.rb +64 -71
  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 +12 -8
  21. data/lib/capybara/queries/base_query.rb +22 -18
  22. data/lib/capybara/queries/current_path_query.rb +12 -25
  23. data/lib/capybara/queries/match_query.rb +3 -7
  24. data/lib/capybara/queries/selector_query.rb +100 -96
  25. data/lib/capybara/queries/sibling_query.rb +5 -5
  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 +52 -39
  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 +116 -58
  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 +172 -163
  49. data/lib/capybara/selenium/node.rb +218 -104
  50. data/lib/capybara/server.rb +3 -2
  51. data/lib/capybara/session/config.rb +47 -59
  52. data/lib/capybara/session/matchers.rb +23 -14
  53. data/lib/capybara/session.rb +175 -229
  54. data/lib/capybara/spec/fixtures/no_extension +1 -0
  55. data/lib/capybara/spec/public/test.js +38 -6
  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 +30 -1
  59. data/lib/capybara/spec/session/all_spec.rb +31 -18
  60. data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
  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 +31 -23
  65. data/lib/capybara/spec/session/assert_title.rb +13 -3
  66. data/lib/capybara/spec/session/attach_file_spec.rb +57 -29
  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 +24 -32
  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 +19 -8
  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 +23 -0
  81. data/lib/capybara/spec/session/evaluate_script_spec.rb +5 -4
  82. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  83. data/lib/capybara/spec/session/fill_in_spec.rb +30 -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 +9 -15
  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/frame_title_spec.rb +23 -0
  91. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  92. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  93. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  94. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  95. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  96. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  97. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  98. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  99. data/lib/capybara/spec/session/has_current_path_spec.rb +49 -22
  100. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  101. data/lib/capybara/spec/session/has_link_spec.rb +5 -4
  102. data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
  103. data/lib/capybara/spec/session/has_select_spec.rb +32 -31
  104. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  105. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  106. data/lib/capybara/spec/session/has_text_spec.rb +9 -13
  107. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  108. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  109. data/lib/capybara/spec/session/headers.rb +2 -1
  110. data/lib/capybara/spec/session/html_spec.rb +1 -0
  111. data/lib/capybara/spec/session/node_spec.rb +107 -58
  112. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  113. data/lib/capybara/spec/session/refresh_spec.rb +6 -2
  114. data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
  115. data/lib/capybara/spec/session/response_code.rb +1 -0
  116. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  117. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  118. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  119. data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
  120. data/lib/capybara/spec/session/select_spec.rb +21 -20
  121. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  122. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  123. data/lib/capybara/spec/session/text_spec.rb +17 -3
  124. data/lib/capybara/spec/session/title_spec.rb +11 -1
  125. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  126. data/lib/capybara/spec/session/unselect_spec.rb +7 -6
  127. data/lib/capybara/spec/session/visit_spec.rb +64 -3
  128. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  129. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  130. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  131. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  132. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  133. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  134. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  135. data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
  136. data/lib/capybara/spec/session/within_spec.rb +1 -0
  137. data/lib/capybara/spec/spec_helper.rb +36 -18
  138. data/lib/capybara/spec/test_app.rb +17 -9
  139. data/lib/capybara/spec/views/form.erb +7 -0
  140. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  141. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  142. data/lib/capybara/spec/views/with_hover.erb +5 -0
  143. data/lib/capybara/spec/views/with_html.erb +27 -1
  144. data/lib/capybara/spec/views/with_js.erb +11 -0
  145. data/lib/capybara/spec/views/within_frames.erb +4 -1
  146. data/lib/capybara/version.rb +2 -1
  147. data/lib/capybara/window.rb +6 -10
  148. data/lib/capybara.rb +29 -26
  149. data/spec/basic_node_spec.rb +1 -0
  150. data/spec/capybara_spec.rb +16 -69
  151. data/spec/dsl_spec.rb +5 -13
  152. data/spec/filter_set_spec.rb +5 -4
  153. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  154. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  155. data/spec/minitest_spec.rb +13 -4
  156. data/spec/minitest_spec_spec.rb +12 -3
  157. data/spec/per_session_config_spec.rb +9 -8
  158. data/spec/rack_test_spec.rb +21 -20
  159. data/spec/result_spec.rb +17 -16
  160. data/spec/rspec/features_spec.rb +17 -14
  161. data/spec/rspec/scenarios_spec.rb +5 -7
  162. data/spec/rspec/shared_spec_matchers.rb +96 -99
  163. data/spec/rspec/views_spec.rb +2 -1
  164. data/spec/rspec_matchers_spec.rb +18 -2
  165. data/spec/rspec_spec.rb +11 -15
  166. data/spec/selector_spec.rb +5 -6
  167. data/spec/selenium_spec_chrome.rb +20 -11
  168. data/spec/selenium_spec_edge.rb +27 -0
  169. data/spec/selenium_spec_ie.rb +31 -0
  170. data/spec/selenium_spec_marionette.rb +38 -12
  171. data/spec/server_spec.rb +33 -33
  172. data/spec/session_spec.rb +2 -1
  173. data/spec/shared_selenium_session.rb +82 -22
  174. data/spec/spec_helper.rb +3 -6
  175. metadata +76 -81
  176. data/lib/capybara/query.rb +0 -7
  177. 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_select?' do
3
4
  before { @session.visit('/form') }
4
5
 
@@ -6,7 +7,7 @@ Capybara::SpecHelper.spec '#has_select?' do
6
7
  expect(@session).to have_select('Locale')
7
8
  expect(@session).to have_select('form_region')
8
9
  expect(@session).to have_select('Languages')
9
- expect(@session).to have_select(:'Languages')
10
+ expect(@session).to have_select(:Languages)
10
11
  end
11
12
 
12
13
  it "should be false if the field is not on the page" do
@@ -27,13 +28,13 @@ Capybara::SpecHelper.spec '#has_select?' do
27
28
  expect(@session).not_to have_select('Does not exist', selected: 'John')
28
29
  expect(@session).not_to have_select('City', selected: 'Not there')
29
30
  expect(@session).not_to have_select('Underwear', selected: [
30
- 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistant'
31
+ 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistent'
31
32
  ])
32
33
  expect(@session).not_to have_select('Underwear', selected: [
33
34
  'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', "Frenchman's Pantalons", 'Long Johns'
34
35
  ])
35
36
  expect(@session).not_to have_select('Underwear', selected: [
36
- 'Boxerbriefs', 'Briefs','Commando', "Frenchman's Pantalons"
37
+ 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons"
37
38
  ])
38
39
  end
39
40
 
@@ -69,25 +70,25 @@ Capybara::SpecHelper.spec '#has_select?' do
69
70
 
70
71
  context 'with partial select' do
71
72
  it "should be true if a field with the given partial values is on the page" do
72
- expect(@session).to have_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
73
+ expect(@session).to have_select('Underwear', with_selected: %w[Boxerbriefs Briefs])
73
74
  end
74
75
 
75
76
  it "should be false if a field with the given partial values is not on the page" do
76
- expect(@session).not_to have_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
77
+ expect(@session).not_to have_select('Underwear', with_selected: %w[Boxerbriefs Boxers])
77
78
  end
78
79
 
79
80
  it "should be true after the given partial value is selected" do
80
81
  @session.select('Boxers', from: 'Underwear')
81
- expect(@session).to have_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
82
+ expect(@session).to have_select('Underwear', with_selected: %w[Boxerbriefs Boxers])
82
83
  end
83
84
 
84
85
  it "should be false after one of the given partial values is unselected" do
85
86
  @session.unselect('Briefs', from: 'Underwear')
86
- expect(@session).not_to have_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
87
+ expect(@session).not_to have_select('Underwear', with_selected: %w[Boxerbriefs Briefs])
87
88
  end
88
89
 
89
90
  it "should be true even when the selected values are invisible, regardless of the select's visibility" do
90
- expect(@session).to have_select('Dessert', visible: false, with_options: ['Pudding', 'Tiramisu'])
91
+ expect(@session).to have_select('Dessert', visible: false, with_options: %w[Pudding Tiramisu])
91
92
  expect(@session).to have_select('Cake', with_selected: ['Chocolate Cake', 'Sponge Cake'])
92
93
  end
93
94
 
@@ -99,7 +100,7 @@ Capybara::SpecHelper.spec '#has_select?' do
99
100
 
100
101
  context 'with exact options' do
101
102
  it "should be true if a field with the given options is on the page" do
102
- expect(@session).to have_select('Region', options: ['Norway', 'Sweden', 'Finland'])
103
+ expect(@session).to have_select('Region', options: %w[Norway Sweden Finland])
103
104
  expect(@session).to have_select('Tendency', options: [])
104
105
  end
105
106
 
@@ -107,29 +108,29 @@ Capybara::SpecHelper.spec '#has_select?' do
107
108
  expect(@session).not_to have_select('Locale', options: ['Swedish'])
108
109
  expect(@session).not_to have_select('Does not exist', options: ['John'])
109
110
  expect(@session).not_to have_select('City', options: ['London', 'Made up city'])
110
- expect(@session).not_to have_select('Region', options: ['Norway', 'Sweden'])
111
- expect(@session).not_to have_select('Region', options: ['Norway', 'Norway', 'Norway'])
111
+ expect(@session).not_to have_select('Region', options: %w[Norway Sweden])
112
+ expect(@session).not_to have_select('Region', options: %w[Norway Norway Norway])
112
113
  end
113
114
 
114
115
  it "should be true even when the options are invisible, if the select itself is invisible" do
115
- expect(@session).to have_select("Icecream", visible: false, options: ['Chocolate', 'Vanilla', 'Strawberry'])
116
+ expect(@session).to have_select("Icecream", visible: false, options: %w[Chocolate Vanilla Strawberry])
116
117
  end
117
118
  end
118
119
 
119
120
  context 'with partial options' do
120
121
  it "should be true if a field with the given partial options is on the page" do
121
- expect(@session).to have_select('Region', with_options: ['Norway', 'Sweden'])
122
+ expect(@session).to have_select('Region', with_options: %w[Norway Sweden])
122
123
  expect(@session).to have_select('City', with_options: ['London'])
123
124
  end
124
125
 
125
126
  it "should be false if a field with the given partial options is not on the page" do
126
127
  expect(@session).not_to have_select('Locale', with_options: ['Uruguayan'])
127
128
  expect(@session).not_to have_select('Does not exist', with_options: ['John'])
128
- expect(@session).not_to have_select('Region', with_options: ['Norway', 'Sweden', 'Finland', 'Latvia'])
129
+ expect(@session).not_to have_select('Region', with_options: %w[Norway Sweden Finland Latvia])
129
130
  end
130
131
 
131
132
  it "should be true even when the options are invisible, if the select itself is invisible" do
132
- expect(@session).to have_select("Icecream", visible: false, with_options: ['Vanilla', 'Strawberry'])
133
+ expect(@session).to have_select("Icecream", visible: false, with_options: %w[Vanilla Strawberry])
133
134
  end
134
135
  end
135
136
 
@@ -151,9 +152,9 @@ Capybara::SpecHelper.spec '#has_select?' do
151
152
  end
152
153
 
153
154
  it "should support locator-less usage" do
154
- expect(@session.has_select?(with_options: ['Norway', 'Sweden'])).to eq true
155
+ expect(@session.has_select?(with_options: %w[Norway Sweden])).to eq true
155
156
  expect(@session).to have_select(with_options: ['London'])
156
- expect(@session.has_select?(with_selected: ['Commando', 'Boxerbriefs'])).to eq true
157
+ expect(@session.has_select?(with_selected: %w[Commando Boxerbriefs])).to eq true
157
158
  expect(@session).to have_select(with_selected: ['Briefs'])
158
159
  end
159
160
  end
@@ -185,13 +186,13 @@ Capybara::SpecHelper.spec '#has_no_select?' do
185
186
  expect(@session).to have_no_select('Does not exist', selected: 'John')
186
187
  expect(@session).to have_no_select('City', selected: 'Not there')
187
188
  expect(@session).to have_no_select('Underwear', selected: [
188
- 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistant'
189
+ 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistent'
189
190
  ])
190
191
  expect(@session).to have_no_select('Underwear', selected: [
191
192
  'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', "Frenchman's Pantalons", 'Long Johns'
192
193
  ])
193
194
  expect(@session).to have_no_select('Underwear', selected: [
194
- 'Boxerbriefs', 'Briefs','Commando', "Frenchman's Pantalons"
195
+ 'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons"
195
196
  ])
196
197
  end
197
198
 
@@ -222,21 +223,21 @@ Capybara::SpecHelper.spec '#has_no_select?' do
222
223
 
223
224
  context 'with partial select' do
224
225
  it "should be false if a field with the given partial values is on the page" do
225
- expect(@session).not_to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
226
+ expect(@session).not_to have_no_select('Underwear', with_selected: %w[Boxerbriefs Briefs])
226
227
  end
227
228
 
228
229
  it "should be true if a field with the given partial values is not on the page" do
229
- expect(@session).to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
230
+ expect(@session).to have_no_select('Underwear', with_selected: %w[Boxerbriefs Boxers])
230
231
  end
231
232
 
232
233
  it "should be false after the given partial value is selected" do
233
234
  @session.select('Boxers', from: 'Underwear')
234
- expect(@session).not_to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Boxers'])
235
+ expect(@session).not_to have_no_select('Underwear', with_selected: %w[Boxerbriefs Boxers])
235
236
  end
236
237
 
237
238
  it "should be true after one of the given partial values is unselected" do
238
239
  @session.unselect('Briefs', from: 'Underwear')
239
- expect(@session).to have_no_select('Underwear', with_selected: ['Boxerbriefs', 'Briefs'])
240
+ expect(@session).to have_no_select('Underwear', with_selected: %w[Boxerbriefs Briefs])
240
241
  end
241
242
 
242
243
  it "should support non array partial values" do
@@ -247,35 +248,35 @@ Capybara::SpecHelper.spec '#has_no_select?' do
247
248
 
248
249
  context 'with exact options' do
249
250
  it "should be false if a field with the given options is on the page" do
250
- expect(@session).not_to have_no_select('Region', options: ['Norway', 'Sweden', 'Finland'])
251
+ expect(@session).not_to have_no_select('Region', options: %w[Norway Sweden Finland])
251
252
  end
252
253
 
253
254
  it "should be true if the given field is not on the page" do
254
255
  expect(@session).to have_no_select('Locale', options: ['Swedish'])
255
256
  expect(@session).to have_no_select('Does not exist', options: ['John'])
256
257
  expect(@session).to have_no_select('City', options: ['London', 'Made up city'])
257
- expect(@session).to have_no_select('Region', options: ['Norway', 'Sweden'])
258
- expect(@session).to have_no_select('Region', options: ['Norway', 'Norway', 'Norway'])
258
+ expect(@session).to have_no_select('Region', options: %w[Norway Sweden])
259
+ expect(@session).to have_no_select('Region', options: %w[Norway Norway Norway])
259
260
  end
260
261
  end
261
262
 
262
263
  context 'with partial options' do
263
264
  it "should be false if a field with the given partial options is on the page" do
264
- expect(@session).not_to have_no_select('Region', with_options: ['Norway', 'Sweden'])
265
+ expect(@session).not_to have_no_select('Region', with_options: %w[Norway Sweden])
265
266
  expect(@session).not_to have_no_select('City', with_options: ['London'])
266
267
  end
267
268
 
268
269
  it "should be true if a field with the given partial options is not on the page" do
269
270
  expect(@session).to have_no_select('Locale', with_options: ['Uruguayan'])
270
271
  expect(@session).to have_no_select('Does not exist', with_options: ['John'])
271
- expect(@session).to have_no_select('Region', with_options: ['Norway', 'Sweden', 'Finland', 'Latvia'])
272
+ expect(@session).to have_no_select('Region', with_options: %w[Norway Sweden Finland Latvia])
272
273
  end
273
274
  end
274
275
 
275
276
  it "should support locator-less usage" do
276
- expect(@session.has_no_select?(with_options: ['Norway', 'Sweden', 'Finland', 'Latvia'])).to eq true
277
- expect(@session).to have_no_select(with_options: ['New London'] )
277
+ expect(@session.has_no_select?(with_options: %w[Norway Sweden Finland Latvia])).to eq true
278
+ expect(@session).to have_no_select(with_options: ['New London'])
278
279
  expect(@session.has_no_select?(with_selected: ['Boxers'])).to eq true
279
- expect(@session).to have_no_select(with_selected: ['Commando', 'Boxers'])
280
+ expect(@session).to have_no_select(with_selected: %w[Commando Boxers])
280
281
  end
281
282
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#has_selector?' do
3
4
  before do
4
5
  @session.visit('/with_html')
@@ -72,9 +73,10 @@ Capybara::SpecHelper.spec '#has_selector?' do
72
73
  expect(@session).not_to have_selector("//p//a", text: /Red$/)
73
74
  end
74
75
 
75
- it "should warn when extra parameters passed" do
76
- expect_any_instance_of(Kernel).to receive(:warn).with(/extra/)
77
- expect(@session).to have_selector(:css, "p a#foo", 'extra')
76
+ it "should raise when extra parameters passed" do
77
+ expect do
78
+ expect(@session).to have_selector(:css, "p a#foo", 'extra')
79
+ end.to raise_error ArgumentError, /extra/
78
80
  end
79
81
  end
80
82
 
@@ -131,7 +133,6 @@ Capybara::SpecHelper.spec '#has_no_selector?' do
131
133
  end
132
134
 
133
135
  it "should accept a filter block" do
134
- skip "RSpec < 3 doesn't pass the block along to the matcher for the Builtin::Has matcher" if rspec2?
135
136
  expect(@session).to have_no_selector(:css, "a#foo") { |el| el[:id] != "foo" }
136
137
  end
137
138
 
@@ -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
@@ -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"]')
@@ -297,14 +277,29 @@ Capybara::SpecHelper.spec "node" do
297
277
  element.drag_to(target)
298
278
  expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
299
279
  end
280
+
281
+ it "should drag and drop if scrolling is needed" do
282
+ @session.visit('/with_js')
283
+ element = @session.find('//div[@id="drag_scroll"]')
284
+ target = @session.find('//div[@id="drop_scroll"]')
285
+ element.drag_to(target)
286
+ expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
287
+ end
300
288
  end
301
289
 
302
290
  describe '#hover', requires: [:hover] do
303
291
  it "should allow hovering on an element" do
304
292
  @session.visit('/with_hover')
305
- expect(@session.find(:css,'.hidden_until_hover', visible: false)).not_to be_visible
306
- @session.find(:css,'.wrapper').hover
307
- expect(@session.find(:css, '.hidden_until_hover', visible: false)).to be_visible
293
+ expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible
294
+ @session.find(:css, '.wrapper:not(.scroll_needed)').hover
295
+ expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
296
+ end
297
+
298
+ it "should allow hovering on an element that needs to be scrolled into view" do
299
+ @session.visit('/with_hover')
300
+ expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible
301
+ @session.find(:css, '.wrapper.scroll_needed').hover
302
+ expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible
308
303
  end
309
304
  end
310
305
 
@@ -343,24 +338,84 @@ Capybara::SpecHelper.spec "node" do
343
338
  radio.click
344
339
  expect(radio).to be_checked
345
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
346
365
  end
347
366
 
348
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
+
349
372
  it "should double click an element" do
350
- pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
351
373
  @session.visit('/with_js')
352
374
  @session.find(:css, '#click-test').double_click
353
375
  expect(@session.find(:css, '#has-been-double-clicked')).to be
354
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
355
394
  end
356
395
 
357
396
  describe '#right_click', requires: [:js] do
358
397
  it "should right click an element" do
359
- pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
360
398
  @session.visit('/with_js')
361
399
  @session.find(:css, '#click-test').right_click
362
400
  expect(@session.find(:css, '#has-been-right-clicked')).to be
363
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
364
419
  end
365
420
 
366
421
  describe '#send_keys', requires: [:send_keys] do
@@ -384,10 +439,10 @@ Capybara::SpecHelper.spec "node" do
384
439
  expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'
385
440
  end
386
441
 
387
- it "should generate key events", requires: [:send_keys, :js] do
442
+ it "should generate key events", requires: %i[send_keys js] do
388
443
  pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
389
444
  @session.visit('/with_js')
390
- @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'])
391
446
  expect(@session.find(:css, '#key-events-output')).to have_text('keydown:16 keydown:84 keydown:16 keydown:87')
392
447
  end
393
448
  end
@@ -420,9 +475,9 @@ Capybara::SpecHelper.spec "node" do
420
475
  sleep(0.3)
421
476
  expect do
422
477
  expect(node).to have_text('has been reloaded')
423
- end.to raise_error do |error|
478
+ end.to(raise_error do |error|
424
479
  expect(error).to be_an_invalid_element_error(@session)
425
- end
480
+ end)
426
481
  end
427
482
  after { Capybara.automatic_reload = true }
428
483
  end
@@ -464,14 +519,10 @@ Capybara::SpecHelper.spec "node" do
464
519
 
465
520
  expect do
466
521
  expect(node).to have_text('Foo')
467
- end.to raise_error { |error|
468
- expect(error).to be_an_invalid_element_error(@session)
469
- }
522
+ end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })
470
523
  expect do
471
524
  expect(node).to have_text('Bar')
472
- end.to raise_error { |error|
473
- expect(error).to be_an_invalid_element_error(@session)
474
- }
525
+ end.to(raise_error { |error| expect(error).to be_an_invalid_element_error(@session) })
475
526
  end
476
527
 
477
528
  it "should reload nodes with options" do
@@ -485,26 +536,24 @@ Capybara::SpecHelper.spec "node" do
485
536
  end
486
537
 
487
538
  context "when #synchronize raises server errors" do
488
- it "sets an explanatory exception as the cause of server exceptions", requires: [:server, :js] do
489
- 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
490
540
  quietly { @session.visit("/error") }
491
541
  expect do
492
542
  @session.find(:css, 'span')
493
- end.to raise_error(TestApp::TestAppError) do |e|
543
+ end.to(raise_error(TestApp::TestAppError) do |e|
494
544
  expect(e.cause).to be_a Capybara::CapybaraError
495
545
  expect(e.cause.message).to match(/Your application server raised an error/)
496
- end
546
+ end)
497
547
  end
498
548
 
499
- it "sets an explanatory exception as the cause of server exceptions with errors with initializers", requires: [:server, :js] do
500
- 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
501
550
  quietly { @session.visit("/other_error") }
502
551
  expect do
503
552
  @session.find(:css, 'span')
504
- end.to raise_error(TestApp::TestAppOtherError) do |e|
553
+ end.to(raise_error(TestApp::TestAppOtherError) do |e|
505
554
  expect(e.cause).to be_a Capybara::CapybaraError
506
555
  expect(e.cause.message).to match(/Your application server raised an error/)
507
- end
556
+ end)
508
557
  end
509
558
  end
510
559