capybara 3.16.1 → 3.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +321 -0
  4. data/README.md +51 -60
  5. data/lib/capybara.rb +71 -114
  6. data/lib/capybara/config.rb +8 -5
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/node.rb +15 -3
  9. data/lib/capybara/dsl.rb +10 -2
  10. data/lib/capybara/helpers.rb +5 -3
  11. data/lib/capybara/minitest.rb +242 -141
  12. data/lib/capybara/minitest/spec.rb +159 -90
  13. data/lib/capybara/node/actions.rb +85 -74
  14. data/lib/capybara/node/base.rb +4 -4
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +3 -3
  17. data/lib/capybara/node/element.rb +216 -117
  18. data/lib/capybara/node/finders.rb +65 -65
  19. data/lib/capybara/node/matchers.rb +228 -126
  20. data/lib/capybara/node/simple.rb +9 -4
  21. data/lib/capybara/queries/ancestor_query.rb +5 -7
  22. data/lib/capybara/queries/base_query.rb +2 -1
  23. data/lib/capybara/queries/current_path_query.rb +1 -1
  24. data/lib/capybara/queries/selector_query.rb +296 -30
  25. data/lib/capybara/queries/sibling_query.rb +5 -4
  26. data/lib/capybara/queries/style_query.rb +2 -2
  27. data/lib/capybara/queries/text_query.rb +13 -1
  28. data/lib/capybara/queries/title_query.rb +1 -1
  29. data/lib/capybara/rack_test/browser.rb +7 -2
  30. data/lib/capybara/rack_test/driver.rb +1 -1
  31. data/lib/capybara/rack_test/form.rb +1 -1
  32. data/lib/capybara/rack_test/node.rb +43 -7
  33. data/lib/capybara/registration_container.rb +44 -0
  34. data/lib/capybara/registrations/drivers.rb +36 -0
  35. data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
  36. data/lib/capybara/registrations/servers.rb +44 -0
  37. data/lib/capybara/result.rb +36 -8
  38. data/lib/capybara/rspec/matcher_proxies.rb +6 -4
  39. data/lib/capybara/rspec/matchers.rb +100 -63
  40. data/lib/capybara/rspec/matchers/base.rb +23 -10
  41. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  42. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  43. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  44. data/lib/capybara/rspec/matchers/have_selector.rb +16 -8
  45. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  46. data/lib/capybara/rspec/matchers/have_text.rb +4 -4
  47. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  48. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  49. data/lib/capybara/rspec/matchers/match_style.rb +2 -2
  50. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  51. data/lib/capybara/selector.rb +219 -588
  52. data/lib/capybara/selector/builders/css_builder.rb +10 -6
  53. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  54. data/lib/capybara/selector/css.rb +4 -2
  55. data/lib/capybara/selector/definition.rb +277 -0
  56. data/lib/capybara/selector/definition/button.rb +52 -0
  57. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  58. data/lib/capybara/selector/definition/css.rb +10 -0
  59. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  60. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  61. data/lib/capybara/selector/definition/element.rb +27 -0
  62. data/lib/capybara/selector/definition/field.rb +40 -0
  63. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  64. data/lib/capybara/selector/definition/file_field.rb +13 -0
  65. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  66. data/lib/capybara/selector/definition/frame.rb +17 -0
  67. data/lib/capybara/selector/definition/id.rb +6 -0
  68. data/lib/capybara/selector/definition/label.rb +62 -0
  69. data/lib/capybara/selector/definition/link.rb +54 -0
  70. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  71. data/lib/capybara/selector/definition/option.rb +27 -0
  72. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  73. data/lib/capybara/selector/definition/select.rb +81 -0
  74. data/lib/capybara/selector/definition/table.rb +109 -0
  75. data/lib/capybara/selector/definition/table_row.rb +21 -0
  76. data/lib/capybara/selector/definition/xpath.rb +5 -0
  77. data/lib/capybara/selector/filter_set.rb +13 -9
  78. data/lib/capybara/selector/filters/base.rb +11 -2
  79. data/lib/capybara/selector/filters/locator_filter.rb +13 -3
  80. data/lib/capybara/selector/regexp_disassembler.rb +9 -2
  81. data/lib/capybara/selector/selector.rb +43 -448
  82. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  83. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  84. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  85. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  86. data/lib/capybara/selenium/driver.rb +125 -56
  87. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +73 -17
  88. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  89. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +41 -2
  90. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
  91. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +14 -5
  92. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  93. data/lib/capybara/selenium/extensions/find.rb +67 -45
  94. data/lib/capybara/selenium/extensions/html5_drag.rb +152 -36
  95. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  96. data/lib/capybara/selenium/logger_suppressor.rb +34 -0
  97. data/lib/capybara/selenium/node.rb +227 -56
  98. data/lib/capybara/selenium/nodes/chrome_node.rb +93 -8
  99. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  100. data/lib/capybara/selenium/nodes/firefox_node.rb +37 -59
  101. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  102. data/lib/capybara/selenium/nodes/safari_node.rb +27 -54
  103. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  104. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  105. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  106. data/lib/capybara/selenium/patches/logs.rb +45 -0
  107. data/lib/capybara/server.rb +19 -3
  108. data/lib/capybara/server/animation_disabler.rb +2 -2
  109. data/lib/capybara/server/checker.rb +6 -2
  110. data/lib/capybara/server/middleware.rb +23 -13
  111. data/lib/capybara/session.rb +124 -106
  112. data/lib/capybara/session/config.rb +12 -10
  113. data/lib/capybara/session/matchers.rb +6 -6
  114. data/lib/capybara/spec/public/offset.js +6 -0
  115. data/lib/capybara/spec/public/test.js +94 -5
  116. data/lib/capybara/spec/session/all_spec.rb +84 -6
  117. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  118. data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
  119. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  120. data/lib/capybara/spec/session/attach_file_spec.rb +14 -6
  121. data/lib/capybara/spec/session/check_spec.rb +10 -4
  122. data/lib/capybara/spec/session/choose_spec.rb +8 -2
  123. data/lib/capybara/spec/session/click_button_spec.rb +44 -1
  124. data/lib/capybara/spec/session/click_link_spec.rb +11 -0
  125. data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
  126. data/lib/capybara/spec/session/fill_in_spec.rb +37 -2
  127. data/lib/capybara/spec/session/find_spec.rb +60 -6
  128. data/lib/capybara/spec/session/first_spec.rb +1 -1
  129. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
  130. data/lib/capybara/spec/session/frame/within_frame_spec.rb +12 -1
  131. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  132. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  133. data/lib/capybara/spec/session/has_css_spec.rb +35 -6
  134. data/lib/capybara/spec/session/has_current_path_spec.rb +6 -4
  135. data/lib/capybara/spec/session/has_field_spec.rb +34 -0
  136. data/lib/capybara/spec/session/has_select_spec.rb +32 -4
  137. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  138. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  139. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  140. data/lib/capybara/spec/session/has_text_spec.rb +47 -0
  141. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  142. data/lib/capybara/spec/session/node_spec.rb +574 -16
  143. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  144. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  145. data/lib/capybara/spec/session/scroll_spec.rb +1 -1
  146. data/lib/capybara/spec/session/select_spec.rb +5 -10
  147. data/lib/capybara/spec/session/selectors_spec.rb +24 -3
  148. data/lib/capybara/spec/session/uncheck_spec.rb +2 -2
  149. data/lib/capybara/spec/session/unselect_spec.rb +1 -1
  150. data/lib/capybara/spec/session/window/window_spec.rb +10 -9
  151. data/lib/capybara/spec/spec_helper.rb +7 -2
  152. data/lib/capybara/spec/test_app.rb +26 -21
  153. data/lib/capybara/spec/views/animated.erb +49 -0
  154. data/lib/capybara/spec/views/form.erb +25 -4
  155. data/lib/capybara/spec/views/frame_child.erb +2 -1
  156. data/lib/capybara/spec/views/frame_one.erb +1 -0
  157. data/lib/capybara/spec/views/obscured.erb +9 -9
  158. data/lib/capybara/spec/views/offset.erb +32 -0
  159. data/lib/capybara/spec/views/react.erb +45 -0
  160. data/lib/capybara/spec/views/spatial.erb +31 -0
  161. data/lib/capybara/spec/views/with_animation.erb +29 -1
  162. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  163. data/lib/capybara/spec/views/with_html.erb +28 -2
  164. data/lib/capybara/spec/views/with_js.erb +2 -1
  165. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  166. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  167. data/lib/capybara/version.rb +1 -1
  168. data/lib/capybara/window.rb +10 -10
  169. data/spec/basic_node_spec.rb +6 -6
  170. data/spec/capybara_spec.rb +28 -28
  171. data/spec/dsl_spec.rb +16 -3
  172. data/spec/filter_set_spec.rb +5 -5
  173. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  174. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  175. data/spec/minitest_spec.rb +12 -2
  176. data/spec/minitest_spec_spec.rb +56 -45
  177. data/spec/rack_test_spec.rb +25 -12
  178. data/spec/regexp_dissassembler_spec.rb +53 -39
  179. data/spec/result_spec.rb +50 -54
  180. data/spec/rspec/features_spec.rb +1 -0
  181. data/spec/rspec/shared_spec_matchers.rb +78 -62
  182. data/spec/rspec_spec.rb +5 -5
  183. data/spec/sauce_spec_chrome.rb +1 -0
  184. data/spec/selector_spec.rb +26 -16
  185. data/spec/selenium_spec_chrome.rb +84 -5
  186. data/spec/selenium_spec_chrome_remote.rb +23 -8
  187. data/spec/selenium_spec_edge.rb +23 -8
  188. data/spec/selenium_spec_firefox.rb +16 -21
  189. data/spec/selenium_spec_firefox_remote.rb +4 -13
  190. data/spec/selenium_spec_ie.rb +23 -15
  191. data/spec/selenium_spec_safari.rb +17 -17
  192. data/spec/server_spec.rb +87 -42
  193. data/spec/session_spec.rb +11 -4
  194. data/spec/shared_selenium_node.rb +83 -0
  195. data/spec/shared_selenium_session.rb +62 -72
  196. data/spec/spec_helper.rb +43 -5
  197. metadata +114 -16
@@ -25,6 +25,8 @@ skipped_tests = %i[
25
25
  download
26
26
  css
27
27
  scroll
28
+ spatial
29
+ html_validation
28
30
  ]
29
31
  Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
30
32
  case example.metadata[:full_description]
@@ -80,11 +82,10 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
80
82
 
81
83
  describe '#fill_in' do
82
84
  it 'should warn that :fill_options are not supported' do
83
- allow_any_instance_of(Capybara::RackTest::Node).to receive(:warn)
84
85
  session.visit '/with_html'
85
- field = session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true }
86
+ expect { session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true } }.to \
87
+ output(/^Options passed to Node#set but the RackTest driver doesn't support any - ignoring/).to_stderr
86
88
  expect(session).to have_field('test_field', with: 'not_monkey')
87
- expect(field.base).to have_received(:warn).with("Options passed to Node#set but the RackTest driver doesn't support any - ignoring")
88
89
  end
89
90
  end
90
91
 
@@ -127,6 +128,18 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
127
128
  session.find(:label, 'Female').click
128
129
  expect(session).to have_unchecked_field('gender_male')
129
130
  end
131
+
132
+ it 'should rewrite the forms action query for get submission' do
133
+ session.visit('/form')
134
+ session.click_button('mediocre')
135
+ expect(session).not_to have_current_path(/foo|bar/)
136
+ end
137
+
138
+ it 'should rewrite the submit buttons formaction query for get submission' do
139
+ session.visit('/form')
140
+ session.click_button('mediocre2')
141
+ expect(session).not_to have_current_path(/foo|bar/)
142
+ end
130
143
  end
131
144
  end
132
145
 
@@ -155,27 +168,27 @@ RSpec.describe Capybara::RackTest::Driver do
155
168
 
156
169
  describe ':headers option' do
157
170
  it 'should always set headers' do
158
- driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
171
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
159
172
  driver.visit('/get_header')
160
173
  expect(driver.html).to include('foobar')
161
174
  end
162
175
 
163
176
  it 'should keep headers on link clicks' do
164
- driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
177
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
165
178
  driver.visit('/header_links')
166
179
  driver.find_xpath('.//a').first.click
167
180
  expect(driver.html).to include('foobar')
168
181
  end
169
182
 
170
183
  it 'should keep headers on form submit' do
171
- driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
184
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
172
185
  driver.visit('/header_links')
173
186
  driver.find_xpath('.//input').first.click
174
187
  expect(driver.html).to include('foobar')
175
188
  end
176
189
 
177
190
  it 'should keep headers on redirects' do
178
- driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
191
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
179
192
  driver.visit('/get_header_via_redirect')
180
193
  expect(driver.html).to include('foobar')
181
194
  end
@@ -183,7 +196,7 @@ RSpec.describe Capybara::RackTest::Driver do
183
196
 
184
197
  describe ':follow_redirects option' do
185
198
  it 'defaults to following redirects' do
186
- driver = Capybara::RackTest::Driver.new(TestApp)
199
+ driver = described_class.new(TestApp)
187
200
 
188
201
  driver.visit('/redirect')
189
202
  expect(driver.response.header['Location']).to be_nil
@@ -191,7 +204,7 @@ RSpec.describe Capybara::RackTest::Driver do
191
204
  end
192
205
 
193
206
  it 'is possible to not follow redirects' do
194
- driver = Capybara::RackTest::Driver.new(TestApp, follow_redirects: false)
207
+ driver = described_class.new(TestApp, follow_redirects: false)
195
208
 
196
209
  driver.visit('/redirect')
197
210
  expect(driver.response.header['Location']).to match %r{/redirect_again$}
@@ -201,7 +214,7 @@ RSpec.describe Capybara::RackTest::Driver do
201
214
 
202
215
  describe ':redirect_limit option' do
203
216
  context 'with default redirect limit' do
204
- let(:driver) { Capybara::RackTest::Driver.new(TestApp) }
217
+ let(:driver) { described_class.new(TestApp) }
205
218
 
206
219
  it 'should follow 5 redirects' do
207
220
  driver.visit('/redirect/5/times')
@@ -216,7 +229,7 @@ RSpec.describe Capybara::RackTest::Driver do
216
229
  end
217
230
 
218
231
  context 'with 21 redirect limit' do
219
- let(:driver) { Capybara::RackTest::Driver.new(TestApp, redirect_limit: 21) }
232
+ let(:driver) { described_class.new(TestApp, redirect_limit: 21) }
220
233
 
221
234
  it 'should follow 21 redirects' do
222
235
  driver.visit('/redirect/21/times')
@@ -251,6 +264,6 @@ RSpec.describe Capybara::RackTest::CSSHandlers do
251
264
  include CSSHandlerIncludeTester
252
265
 
253
266
  it 'should not be extended by global includes' do
254
- expect(Capybara::RackTest::CSSHandlers.new).not_to respond_to(:dont_extend_css_handler)
267
+ expect(described_class.new).not_to respond_to(:dont_extend_css_handler)
255
268
  end
256
269
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe Capybara::Selector::RegexpDisassembler do
5
+ RSpec.describe Capybara::Selector::RegexpDisassembler, :aggregate_failures do
6
6
  it 'handles strings' do
7
7
  verify_strings(
8
8
  /abcdef/ => %w[abcdef],
@@ -44,20 +44,22 @@ RSpec.describe Capybara::Selector::RegexpDisassembler do
44
44
  /abc?def?g/ => %w[ab de g],
45
45
  /d?/ => []
46
46
  }.each do |regexp, expected|
47
- expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
47
+ expect(described_class.new(regexp).substrings).to eq expected
48
48
  end
49
49
  end
50
50
 
51
51
  it 'handles optional characters for #alternated_substrings' do
52
52
  verify_alternated_strings(
53
- /abc*def/ => [%w[ab def]],
54
- /abc*/ => [%w[ab]],
55
- /c*/ => [],
56
- /abc?def/ => [%w[abdef], %w[abcdef]],
57
- /abc?/ => [%w[ab]],
58
- /abc?def?/ => [%w[abde], %w[abcde]],
59
- /abc?def?g/ => [%w[abdeg], %w[abdefg], %w[abcdeg], %w[abcdefg]],
60
- /d?/ => []
53
+ {
54
+ /abc*def/ => [%w[ab def]],
55
+ /abc*/ => [%w[ab]],
56
+ /c*/ => [],
57
+ /abc?def/ => [%w[abdef], %w[abcdef]],
58
+ /abc?/ => [%w[ab]],
59
+ /abc?def?/ => [%w[abde], %w[abcde]],
60
+ /abc?def?g/ => [%w[abdeg], %w[abdefg], %w[abcdeg], %w[abcdefg]],
61
+ /d?/ => []
62
+ }
61
63
  )
62
64
  end
63
65
 
@@ -131,40 +133,42 @@ RSpec.describe Capybara::Selector::RegexpDisassembler do
131
133
  /ab(cd|cd)?ef/ => %w[ab ef],
132
134
  /ab\\?cd/ => %w[ab cd]
133
135
  }.each do |regexp, expected|
134
- expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
136
+ expect(described_class.new(regexp).substrings).to eq expected
135
137
  end
136
138
  end
137
139
 
138
140
  it 'handles alternation for #alternated_substrings' do
139
141
  verify_alternated_strings(
140
- /abc|def/ => [%w[abc], %w[def]],
141
- /ab(?:c|d)/ => [%w[abc], %w[abd]],
142
- /ab(c|d|e)fg/ => [%w[abcfg], %w[abdfg], %w[abefg]],
143
- /ab?(c|d)fg/ => [%w[acfg], %w[adfg], %w[abcfg], %w[abdfg]],
144
- /ab(c|d)ef/ => [%w[abcef], %w[abdef]],
145
- /ab(cd?|ef)g/ => [%w[abcg], %w[abcdg], %w[abefg]],
146
- /ab(cd|ef*)g/ => [%w[abcdg], %w[abe g]],
147
- /ab|cd*/ => [%w[ab], %w[c]],
148
- /cd(?:ef|gh)|xyz/ => [%w[cdef], %w[cdgh], %w[xyz]],
149
- /(cd(?:ef|gh)|xyz)/ => [%w[cdef], %w[cdgh], %w[xyz]],
150
- /cd(ef|gh)+/ => [%w[cdef], %w[cdgh]],
151
- /cd(ef|gh)?/ => [%w[cd]],
152
- /cd(ef|gh)?ij/ => [%w[cdij], %w[cdefij], %w[cdghij]],
153
- /cd(ef|gh)+ij/ => [%w[cdef ij], %w[cdgh ij]],
154
- /cd(ef|gh){2}ij/ => [%w[cdefefij], %w[cdefghij], %w[cdghefij], %w[cdghghij]],
155
- /(cd(ef|g*))/ => [%w[cd]],
156
- /a|b*/ => [],
157
- /ab(?:c|d?)/ => [%w[ab]],
158
- /ab(c|d)|a*/ => [],
159
- /(abc)?(d|e)/ => [%w[d], %w[e]],
160
- /(abc*de)?(d|e)/ => [%w[d], %w[e]],
161
- /(abc*de)?(d|e?)/ => [],
162
- /(abc)?(d|e?)/ => [],
163
- /ab(cd){0,2}ef/ => [%w[ab ef]],
164
- /ab(cd){0,1}ef/ => [%w[abef], %w[abcdef]],
165
- /ab(cd|cd)ef/ => [%w[abcdef]],
166
- /ab(cd|cd)?ef/ => [%w[abef], %w[abcdef]],
167
- /ab\\?cd/ => [%w[abcd], %w[ab\cd]]
142
+ {
143
+ /abc|def/ => [%w[abc], %w[def]],
144
+ /ab(?:c|d)/ => [%w[abc], %w[abd]],
145
+ /ab(c|d|e)fg/ => [%w[abcfg], %w[abdfg], %w[abefg]],
146
+ /ab?(c|d)fg/ => [%w[acfg], %w[adfg], %w[abcfg], %w[abdfg]],
147
+ /ab(c|d)ef/ => [%w[abcef], %w[abdef]],
148
+ /ab(cd?|ef)g/ => [%w[abcg], %w[abcdg], %w[abefg]],
149
+ /ab(cd|ef*)g/ => [%w[abcdg], %w[abe g]],
150
+ /ab|cd*/ => [%w[ab], %w[c]],
151
+ /cd(?:ef|gh)|xyz/ => [%w[cdef], %w[cdgh], %w[xyz]],
152
+ /(cd(?:ef|gh)|xyz)/ => [%w[cdef], %w[cdgh], %w[xyz]],
153
+ /cd(ef|gh)+/ => [%w[cdef], %w[cdgh]],
154
+ /cd(ef|gh)?/ => [%w[cd]],
155
+ /cd(ef|gh)?ij/ => [%w[cdij], %w[cdefij], %w[cdghij]],
156
+ /cd(ef|gh)+ij/ => [%w[cdef ij], %w[cdgh ij]],
157
+ /cd(ef|gh){2}ij/ => [%w[cdefefij], %w[cdefghij], %w[cdghefij], %w[cdghghij]],
158
+ /(cd(ef|g*))/ => [%w[cd]],
159
+ /a|b*/ => [],
160
+ /ab(?:c|d?)/ => [%w[ab]],
161
+ /ab(c|d)|a*/ => [],
162
+ /(abc)?(d|e)/ => [%w[d], %w[e]],
163
+ /(abc*de)?(d|e)/ => [%w[d], %w[e]],
164
+ /(abc*de)?(d|e?)/ => [],
165
+ /(abc)?(d|e?)/ => [],
166
+ /ab(cd){0,2}ef/ => [%w[ab ef]],
167
+ /ab(cd){0,1}ef/ => [%w[abef], %w[abcdef]],
168
+ /ab(cd|cd)ef/ => [%w[abcdef]],
169
+ /ab(cd|cd)?ef/ => [%w[abef], %w[abcdef]],
170
+ /ab\\?cd/ => [%w[abcd], %w[ab\cd]]
171
+ }
168
172
  )
169
173
  end
170
174
 
@@ -212,6 +216,16 @@ RSpec.describe Capybara::Selector::RegexpDisassembler do
212
216
  )
213
217
  end
214
218
 
219
+ it 'ignores negative lookaheads' do
220
+ verify_strings(
221
+ /^(?!.*\bContributing Editor\b).*$/ => %w[],
222
+ /abc(?!.*def).*/ => %w[abc],
223
+ /(?!.*def)abc/ => %w[abc],
224
+ /abc(?!.*def.*).*ghi/ => %w[abc ghi],
225
+ /abc(?!.*bcd)def/ => %w[abcdef]
226
+ )
227
+ end
228
+
215
229
  it 'handles anchors' do
216
230
  verify_strings(
217
231
  /^abc/ => %w[abc],
@@ -44,9 +44,9 @@ RSpec.describe Capybara::Result do
44
44
  end
45
45
 
46
46
  it 'can be selected' do
47
- expect(result.select do |element|
47
+ expect(result.count do |element|
48
48
  element.text.include? 't'
49
- end.length).to eq(2)
49
+ end).to eq(2)
50
50
  end
51
51
 
52
52
  it 'can be reduced' do
@@ -65,48 +65,56 @@ RSpec.describe Capybara::Result do
65
65
  end).to eq(2)
66
66
  end
67
67
 
68
+ def recalc_result
69
+ string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
70
+ end
71
+
68
72
  it 'supports all modes of []' do
69
- expect(result[1].text).to eq 'Beta'
70
- expect(result[0, 2].map(&:text)).to eq %w[Alpha Beta]
71
- expect(result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
72
- expect(result[-1].text).to eq 'Delta'
73
- expect(result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
74
- expect(result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
75
- expect(result[1...3].map(&:text)).to eq %w[Beta Gamma]
76
- expect(result[2..-1].map(&:text)).to eq %w[Gamma Delta]
77
- expect(result[2...-1].map(&:text)).to eq %w[Gamma]
78
- eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
73
+ expect(recalc_result[1].text).to eq 'Beta'
74
+ expect(recalc_result[0, 2].map(&:text)).to eq %w[Alpha Beta]
75
+ expect(recalc_result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
76
+ expect(recalc_result[-1].text).to eq 'Delta'
77
+ expect(recalc_result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
78
+ expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]
79
+ expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
80
+ expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]
81
+ expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta]
82
+ end
83
+
84
+ eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
85
+ it 'supports endless ranges' do
79
86
  expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
80
- TEST
81
- end
87
+ end
88
+ TEST
89
+
90
+ eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
91
+ it 'supports inclusive positive beginless ranges' do
92
+ expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
93
+ end
94
+
95
+ it 'supports inclusive negative beginless ranges' do
96
+ expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
97
+ expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
98
+ end
99
+
100
+ it 'supports exclusive positive beginless ranges' do
101
+ expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
102
+ end
103
+
104
+ it 'supports exclusive negative beginless ranges' do
105
+ expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
106
+ expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
107
+ end
108
+ TEST
82
109
 
83
110
  it 'works with filter blocks' do
84
111
  result = string.all('//li') { |node| node.text == 'Alpha' }
85
112
  expect(result.size).to eq 1
86
113
  end
87
114
 
88
- it 'should catch invalid element errors during filtering' do
89
- allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
90
- allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(
91
- instance_double('Capybara::Session', driver: instance_double('Capybara::Driver::Base', invalid_element_errors: [StandardError], wait?: false))
92
- )
93
- result = string.all('//li', text: 'Alpha')
94
- expect(result.size).to eq 0
95
- end
96
-
97
- it 'should return non-invalid element errors during filtering' do
98
- allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
99
- allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(
100
- instance_double('Capybara::Session', driver: instance_double('Capybara::Driver::Base', invalid_element_errors: [ArgumentError], wait?: false))
101
- )
102
- expect do
103
- string.all('//li', text: 'Alpha').to_a
104
- end.to raise_error(StandardError)
105
- end
106
-
107
115
  # Not a great test but it indirectly tests what is needed
108
116
  it 'should evaluate filters lazily for idx' do
109
- skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
117
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
110
118
  # Not processed until accessed
111
119
  expect(result.instance_variable_get('@result_cache').size).to be 0
112
120
 
@@ -127,7 +135,7 @@ RSpec.describe Capybara::Result do
127
135
  end
128
136
 
129
137
  it 'should evaluate filters lazily for range' do
130
- skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
138
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
131
139
  result[0..1]
132
140
  expect(result.instance_variable_get('@result_cache').size).to be 2
133
141
 
@@ -136,7 +144,7 @@ RSpec.describe Capybara::Result do
136
144
  end
137
145
 
138
146
  it 'should evaluate filters lazily for idx and length' do
139
- skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
147
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
140
148
  result[1, 2]
141
149
  expect(result.instance_variable_get('@result_cache').size).to be 3
142
150
 
@@ -145,7 +153,7 @@ RSpec.describe Capybara::Result do
145
153
  end
146
154
 
147
155
  it 'should only need to evaluate one result for any?' do
148
- skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
156
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
149
157
  result.any?
150
158
  expect(result.instance_variable_get('@result_cache').size).to be 1
151
159
  end
@@ -156,9 +164,9 @@ RSpec.describe Capybara::Result do
156
164
  expect(result.instance_variable_get('@result_cache').size).to eq 4
157
165
  end
158
166
 
159
- context '#each' do
167
+ describe '#each' do
160
168
  it 'lazily evaluates' do
161
- skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
169
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
162
170
  results = []
163
171
  result.each do |el|
164
172
  results << el
@@ -174,7 +182,7 @@ RSpec.describe Capybara::Result do
174
182
  end
175
183
 
176
184
  it 'lazily evaluates' do
177
- skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
185
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
178
186
  result.each.with_index do |_el, idx|
179
187
  expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
180
188
  end
@@ -182,19 +190,7 @@ RSpec.describe Capybara::Result do
182
190
  end
183
191
  end
184
192
 
185
- context 'lazy select' do
186
- it 'is compatible' do
187
- # This test will let us know when JRuby fixes lazy select so we can re-enable it in Result
188
- pending 'JRuby has an issue with lazy enumberator evaluation' if RUBY_PLATFORM == 'java'
189
- eval_count = 0
190
- enum = %w[Text1 Text2 Text3].lazy.select do
191
- eval_count += 1
192
- true
193
- end
194
- expect(eval_count).to eq 0
195
- enum.next
196
- sleep 1
197
- expect(eval_count).to eq 1
198
- end
193
+ def jruby_lazy_enumerator_workaround?
194
+ RUBY_PLATFORM == 'java'
199
195
  end
200
196
  end
@@ -81,6 +81,7 @@ xfeature 'if xfeature aliases to pending then' do
81
81
  scenario "this should be 'temporarily disabled with xfeature'" do
82
82
  # dummy
83
83
  end
84
+
84
85
  scenario "this also should be 'temporarily disabled with xfeature'" do
85
86
  # dummy
86
87
  end
@@ -89,29 +89,29 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
89
89
 
90
90
  context 'on a page or node' do
91
91
  before do
92
- visit('/with_html')
92
+ session.visit('/with_html')
93
93
  end
94
94
 
95
95
  context 'with should' do
96
96
  it 'passes if has_css? returns true' do
97
- expect(page).to have_css('h1')
97
+ expect(session).to have_css('h1')
98
98
  end
99
99
 
100
100
  it 'fails if has_css? returns false' do
101
101
  expect do
102
- expect(page).to have_css('h1#doesnotexist')
102
+ expect(session).to have_css('h1#doesnotexist')
103
103
  end.to raise_error(/expected to find css "h1#doesnotexist" but there were no matches/)
104
104
  end
105
105
  end
106
106
 
107
107
  context 'with should_not' do
108
108
  it 'passes if has_no_css? returns true' do
109
- expect(page).not_to have_css('h1#doesnotexist')
109
+ expect(session).not_to have_css('h1#doesnotexist')
110
110
  end
111
111
 
112
112
  it 'fails if has_no_css? returns false' do
113
113
  expect do
114
- expect(page).not_to have_css('h1')
114
+ expect(session).not_to have_css('h1')
115
115
  end.to raise_error(/expected not to find visible css "h1"/)
116
116
  end
117
117
  end
@@ -158,29 +158,29 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
158
158
 
159
159
  context 'on a page or node' do
160
160
  before do
161
- visit('/with_html')
161
+ session.visit('/with_html')
162
162
  end
163
163
 
164
164
  context 'with should' do
165
165
  it 'passes if has_xpath? returns true' do
166
- expect(page).to have_xpath('//h1')
166
+ expect(session).to have_xpath('//h1')
167
167
  end
168
168
 
169
169
  it 'fails if has_xpath? returns false' do
170
170
  expect do
171
- expect(page).to have_xpath("//h1[@id='doesnotexist']")
171
+ expect(session).to have_xpath("//h1[@id='doesnotexist']")
172
172
  end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
173
173
  end
174
174
  end
175
175
 
176
176
  context 'with should_not' do
177
177
  it 'passes if has_no_xpath? returns true' do
178
- expect(page).not_to have_xpath('//h1[@id="doesnotexist"]')
178
+ expect(session).not_to have_xpath('//h1[@id="doesnotexist"]')
179
179
  end
180
180
 
181
181
  it 'fails if has_no_xpath? returns false' do
182
182
  expect do
183
- expect(page).not_to have_xpath('//h1')
183
+ expect(session).not_to have_xpath('//h1')
184
184
  end.to raise_error(%r{expected not to find visible xpath "//h1"})
185
185
  end
186
186
  end
@@ -222,35 +222,35 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
222
222
 
223
223
  context 'on a page or node' do
224
224
  before do
225
- visit('/with_html')
225
+ session.visit('/with_html')
226
226
  end
227
227
 
228
228
  context 'with should' do
229
229
  it 'passes if has_selector? returns true' do
230
- expect(page).to have_selector('//h1', text: 'test')
230
+ expect(session).to have_selector('//h1', text: 'test')
231
231
  end
232
232
 
233
233
  it 'fails if has_selector? returns false' do
234
234
  expect do
235
- expect(page).to have_selector("//h1[@id='doesnotexist']")
235
+ expect(session).to have_selector("//h1[@id='doesnotexist']")
236
236
  end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
237
237
  end
238
238
 
239
239
  it 'includes text in error message' do
240
240
  expect do
241
- expect(page).to have_selector('//h1', text: 'wrong text')
241
+ expect(session).to have_selector('//h1', text: 'wrong text')
242
242
  end.to raise_error(%r{expected to find visible xpath "//h1" with text "wrong text" but there were no matches})
243
243
  end
244
244
  end
245
245
 
246
246
  context 'with should_not' do
247
247
  it 'passes if has_no_css? returns true' do
248
- expect(page).not_to have_selector(:css, 'h1#doesnotexist')
248
+ expect(session).not_to have_selector(:css, 'h1#doesnotexist')
249
249
  end
250
250
 
251
251
  it 'fails if has_no_selector? returns false' do
252
252
  expect do
253
- expect(page).not_to have_selector(:css, 'h1', text: 'test')
253
+ expect(session).not_to have_selector(:css, 'h1', text: 'test')
254
254
  end.to raise_error(/expected not to find visible css "h1" with text "test"/)
255
255
  end
256
256
  end
@@ -265,7 +265,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
265
265
 
266
266
  describe 'have_content matcher' do
267
267
  it 'gives proper description' do
268
- expect(have_content('Text').description).to eq('text "Text"')
268
+ expect(have_content('Text').description).to eq('have text "Text"')
269
269
  end
270
270
 
271
271
  context 'on a string' do
@@ -304,21 +304,21 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
304
304
 
305
305
  context 'on a page or node' do
306
306
  before do
307
- visit('/with_html')
307
+ session.visit('/with_html')
308
308
  end
309
309
 
310
310
  context 'with should' do
311
311
  it 'passes if has_content? returns true' do
312
- expect(page).to have_content('This is a test')
312
+ expect(session).to have_content('This is a test')
313
313
  end
314
314
 
315
315
  it 'passes if has_content? returns true using regexp' do
316
- expect(page).to have_content(/test/)
316
+ expect(session).to have_content(/test/)
317
317
  end
318
318
 
319
319
  it 'fails if has_content? returns false' do
320
320
  expect do
321
- expect(page).to have_content('No such Text')
321
+ expect(session).to have_content('No such Text')
322
322
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
323
323
  end
324
324
 
@@ -329,7 +329,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
329
329
 
330
330
  it 'fails if has_content? returns false' do
331
331
  expect do
332
- expect(page).to have_content('No such Text')
332
+ expect(session).to have_content('No such Text')
333
333
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
334
334
  end
335
335
  end
@@ -337,14 +337,26 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
337
337
 
338
338
  context 'with should_not' do
339
339
  it 'passes if has_no_content? returns true' do
340
- expect(page).not_to have_content('No such Text')
340
+ expect(session).not_to have_content('No such Text')
341
341
  end
342
342
 
343
343
  it 'fails if has_no_content? returns false' do
344
344
  expect do
345
- expect(page).not_to have_content('This is a test')
345
+ expect(session).not_to have_content('This is a test')
346
346
  end.to raise_error(/expected not to find text "This is a test"/)
347
347
  end
348
+
349
+ it 'not_to have_content behaves the same as to have_no_content' do
350
+ Capybara.using_wait_time(5) do
351
+ expect(session).to have_content('This is a test')
352
+ start = Time.now
353
+ expect(session).to have_no_content('No such Text')
354
+ to_time = Time.now
355
+ expect(session).not_to have_content('No such Text')
356
+ not_to_time = Time.now
357
+ expect(not_to_time - to_time).to be_within(0.5).of(to_time - start)
358
+ end
359
+ end
348
360
  end
349
361
  end
350
362
 
@@ -357,7 +369,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
357
369
 
358
370
  describe 'have_text matcher' do
359
371
  it 'gives proper description' do
360
- expect(have_text('Text').description).to eq('text "Text"')
372
+ expect(have_text('Text').description).to eq('have text "Text"')
361
373
  end
362
374
 
363
375
  context 'on a string' do
@@ -432,30 +444,30 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
432
444
 
433
445
  context 'on a page or node' do
434
446
  before do
435
- visit('/with_html')
447
+ session.visit('/with_html')
436
448
  end
437
449
 
438
450
  context 'with should' do
439
451
  it 'passes if has_text? returns true' do
440
- expect(page).to have_text('This is a test')
452
+ expect(session).to have_text('This is a test')
441
453
  end
442
454
 
443
455
  it 'passes if has_text? returns true using regexp' do
444
- expect(page).to have_text(/test/)
456
+ expect(session).to have_text(/test/)
445
457
  end
446
458
 
447
459
  it 'can check for all text' do
448
- expect(page).to have_text(:all, 'Some of this text is hidden!')
460
+ expect(session).to have_text(:all, 'Some of this text is hidden!')
449
461
  end
450
462
 
451
463
  it 'can check for visible text' do
452
- expect(page).to have_text(:visible, 'Some of this text is')
453
- expect(page).not_to have_text(:visible, 'Some of this text is hidden!')
464
+ expect(session).to have_text(:visible, 'Some of this text is')
465
+ expect(session).not_to have_text(:visible, 'Some of this text is hidden!')
454
466
  end
455
467
 
456
468
  it 'fails if has_text? returns false' do
457
469
  expect do
458
- expect(page).to have_text('No such Text')
470
+ expect(session).to have_text('No such Text')
459
471
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
460
472
  end
461
473
 
@@ -466,7 +478,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
466
478
 
467
479
  it 'fails if has_text? returns false' do
468
480
  expect do
469
- expect(page).to have_text('No such Text')
481
+ expect(session).to have_text('No such Text')
470
482
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
471
483
  end
472
484
  end
@@ -474,12 +486,12 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
474
486
 
475
487
  context 'with should_not' do
476
488
  it 'passes if has_no_text? returns true' do
477
- expect(page).not_to have_text('No such Text')
489
+ expect(session).not_to have_text('No such Text')
478
490
  end
479
491
 
480
492
  it 'fails if has_no_text? returns false' do
481
493
  expect do
482
- expect(page).not_to have_text('This is a test')
494
+ expect(session).not_to have_text('This is a test')
483
495
  end.to raise_error(/expected not to find text "This is a test"/)
484
496
  end
485
497
  end
@@ -542,15 +554,15 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
542
554
 
543
555
  context 'on a page or node' do
544
556
  it 'passes if there is such a title' do
545
- visit('/with_js')
546
- expect(page).to have_title('with_js')
557
+ session.visit('/with_js')
558
+ expect(session).to have_title('with_js')
547
559
  end
548
560
 
549
561
  it 'fails if there is no such title' do
550
- visit('/with_js')
562
+ session.visit('/with_js')
551
563
  expect do
552
- expect(page).to have_title('No such title')
553
- end.to raise_error('expected "with_js" to include "No such title"')
564
+ expect(session).to have_title('No such title')
565
+ end.to raise_error(/ to include "No such title"/)
554
566
  end
555
567
 
556
568
  context 'with wait' do
@@ -560,14 +572,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
560
572
 
561
573
  it 'waits if wait time is more than timeout' do
562
574
  session.click_link('Change title')
563
- using_wait_time 0 do
575
+ session.using_wait_time 0 do
564
576
  expect(session).to have_title('changed title', wait: 2)
565
577
  end
566
578
  end
567
579
 
568
580
  it "doesn't wait if wait time is less than timeout" do
569
581
  session.click_link('Change title')
570
- using_wait_time 3 do
582
+ session.using_wait_time 3 do
571
583
  expect(session).not_to have_title('changed title', wait: 0)
572
584
  end
573
585
  end
@@ -586,15 +598,15 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
586
598
 
587
599
  context 'on a page or node' do
588
600
  it 'passes if there is such a current path' do
589
- visit('/with_js')
590
- expect(page).to have_current_path('/with_js')
601
+ session.visit('/with_js')
602
+ expect(session).to have_current_path('/with_js')
591
603
  end
592
604
 
593
605
  it 'fails if there is no such current_path' do
594
606
  visit('/with_js')
595
607
  expect do
596
- expect(page).to have_current_path('/not_with_js')
597
- end.to raise_error('expected "/with_js" to equal "/not_with_js"')
608
+ expect(session).to have_current_path('/not_with_js')
609
+ end.to raise_error(%r{to equal "/not_with_js"})
598
610
  end
599
611
 
600
612
  context 'with wait' do
@@ -604,14 +616,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
604
616
 
605
617
  it 'waits if wait time is more than timeout' do
606
618
  session.click_link('Change page')
607
- using_wait_time 0 do
619
+ session.using_wait_time 0 do
608
620
  expect(session).to have_current_path('/with_html', wait: 2)
609
621
  end
610
622
  end
611
623
 
612
624
  it "doesn't wait if wait time is less than timeout" do
613
625
  session.click_link('Change page')
614
- using_wait_time 0 do
626
+ session.using_wait_time 0 do
615
627
  expect(session).not_to have_current_path('/with_html')
616
628
  end
617
629
  end
@@ -619,16 +631,20 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
619
631
  end
620
632
 
621
633
  it 'supports compounding' do
622
- visit('/with_html')
623
- expect(page).to have_current_path('/not_with_html').or have_current_path('/with_html')
634
+ session.visit('/with_html')
635
+ expect(session).to have_current_path('/not_with_html').or have_current_path('/with_html')
624
636
  end
625
637
  end
626
638
 
627
639
  describe 'have_button matcher' do
628
640
  let(:html) { '<button>A button</button><input type="submit" value="Another button"/>' }
629
641
 
630
- it 'gives proper description' do
631
- expect(have_button('A button').description).to eq('have visible button "A button"')
642
+ it 'gives proper description with no options' do
643
+ expect(have_button('A button').description).to eq('have visible button "A button" that is not disabled')
644
+ end
645
+
646
+ it 'gives proper description with disabled :any option' do
647
+ expect(have_button('A button', disabled: :all).description).to eq('have visible button "A button"')
632
648
  end
633
649
 
634
650
  it 'passes if there is such a button' do
@@ -678,12 +694,12 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
678
694
  end
679
695
 
680
696
  it 'treats a given value as a string' do
681
- class Foo
697
+ foo = Class.new do
682
698
  def to_s
683
699
  'some value'
684
700
  end
685
701
  end
686
- expect(html).to have_field('Text field', with: Foo.new)
702
+ expect(html).to have_field('Text field', with: foo.new)
687
703
  end
688
704
 
689
705
  it 'supports compounding' do
@@ -698,7 +714,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
698
714
  end
699
715
 
700
716
  it 'gives proper description' do
701
- expect(have_checked_field('it is checked').description).to eq('have visible field "it is checked" that is checked and not disabled')
717
+ expect(have_checked_field('it is checked').description).to eq('have visible field "it is checked" that is not disabled that is checked')
702
718
  end
703
719
 
704
720
  context 'with should' do
@@ -747,7 +763,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
747
763
  end
748
764
 
749
765
  it 'gives proper description' do
750
- expect(have_unchecked_field('unchecked field').description).to eq('have visible field "unchecked field" that is not checked and not disabled')
766
+ expect(have_unchecked_field('unchecked field').description).to eq('have visible field "unchecked field" that is not disabled that is not checked')
751
767
  end
752
768
 
753
769
  context 'with should' do
@@ -824,10 +840,10 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
824
840
  end
825
841
 
826
842
  it 'gives proper description when :visible option passed' do
827
- expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"')
843
+ expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"') # rubocop:disable Capybara/VisibilityMatcher
828
844
  expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
829
845
  expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
830
- expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"')
846
+ expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"') # rubocop:disable Capybara/VisibilityMatcher
831
847
  end
832
848
 
833
849
  it 'passes if there is such a table' do
@@ -853,9 +869,9 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
853
869
  session.visit('/with_js')
854
870
  end
855
871
 
856
- context '#and' do
872
+ describe '#and' do
857
873
  it "should run 'concurrently'" do
858
- Capybara.using_wait_time(2) do
874
+ session.using_wait_time(2) do
859
875
  matcher = have_text('this is not there').and have_text('neither is this')
860
876
  expect(Benchmark.realtime do
861
877
  expect do
@@ -895,14 +911,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
895
911
  end
896
912
  end
897
913
 
898
- context '#and_then' do
914
+ describe '#and_then' do
899
915
  it 'should run sequentially' do
900
916
  session.click_link('reload-link')
901
917
  expect(el).to have_text('waiting to be reloaded').and_then have_text('has been reloaded')
902
918
  end
903
919
  end
904
920
 
905
- context '#or' do
921
+ describe '#or' do
906
922
  it "should run 'concurrently'" do
907
923
  session.using_wait_time(3) do
908
924
  expect(Benchmark.realtime do