capybara 3.36.0 → 3.39.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +94 -4
  3. data/README.md +24 -12
  4. data/lib/capybara/driver/node.rb +4 -0
  5. data/lib/capybara/dsl.rb +4 -10
  6. data/lib/capybara/helpers.rb +6 -2
  7. data/lib/capybara/minitest/spec.rb +2 -2
  8. data/lib/capybara/node/actions.rb +4 -4
  9. data/lib/capybara/node/base.rb +2 -1
  10. data/lib/capybara/node/element.rb +12 -1
  11. data/lib/capybara/node/finders.rb +10 -1
  12. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  13. data/lib/capybara/queries/base_query.rb +2 -2
  14. data/lib/capybara/queries/selector_query.rb +24 -9
  15. data/lib/capybara/queries/text_query.rb +1 -1
  16. data/lib/capybara/rack_test/browser.rb +63 -8
  17. data/lib/capybara/rack_test/driver.rb +4 -4
  18. data/lib/capybara/rack_test/form.rb +29 -7
  19. data/lib/capybara/rack_test/node.rb +19 -16
  20. data/lib/capybara/registration_container.rb +0 -3
  21. data/lib/capybara/registrations/drivers.rb +3 -3
  22. data/lib/capybara/registrations/servers.rb +30 -10
  23. data/lib/capybara/rspec/matcher_proxies.rb +3 -3
  24. data/lib/capybara/rspec/matchers/base.rb +8 -6
  25. data/lib/capybara/rspec/matchers/compound.rb +1 -1
  26. data/lib/capybara/rspec/matchers/have_selector.rb +4 -4
  27. data/lib/capybara/rspec/matchers.rb +14 -14
  28. data/lib/capybara/selector/definition/link.rb +2 -1
  29. data/lib/capybara/selector/definition.rb +3 -2
  30. data/lib/capybara/selector/filter_set.rb +4 -5
  31. data/lib/capybara/selector/regexp_disassembler.rb +2 -5
  32. data/lib/capybara/selector/selector.rb +5 -1
  33. data/lib/capybara/selenium/driver.rb +11 -4
  34. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +8 -4
  35. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  36. data/lib/capybara/selenium/extensions/html5_drag.rb +5 -4
  37. data/lib/capybara/selenium/logger_suppressor.rb +6 -2
  38. data/lib/capybara/selenium/node.rb +72 -25
  39. data/lib/capybara/selenium/nodes/chrome_node.rb +5 -1
  40. data/lib/capybara/selenium/nodes/edge_node.rb +24 -2
  41. data/lib/capybara/selenium/nodes/firefox_node.rb +2 -2
  42. data/lib/capybara/selenium/nodes/safari_node.rb +2 -2
  43. data/lib/capybara/selenium/patches/action_pauser.rb +3 -3
  44. data/lib/capybara/selenium/patches/atoms.rb +1 -1
  45. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
  46. data/lib/capybara/server/animation_disabler.rb +36 -25
  47. data/lib/capybara/server/middleware.rb +1 -1
  48. data/lib/capybara/session/config.rb +4 -2
  49. data/lib/capybara/session.rb +19 -30
  50. data/lib/capybara/spec/public/test.js +4 -0
  51. data/lib/capybara/spec/session/all_spec.rb +6 -8
  52. data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
  53. data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
  54. data/lib/capybara/spec/session/check_spec.rb +1 -0
  55. data/lib/capybara/spec/session/click_link_spec.rb +11 -0
  56. data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
  57. data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
  58. data/lib/capybara/spec/session/find_link_spec.rb +10 -0
  59. data/lib/capybara/spec/session/find_spec.rb +7 -1
  60. data/lib/capybara/spec/session/first_spec.rb +1 -1
  61. data/lib/capybara/spec/session/frame/within_frame_spec.rb +2 -0
  62. data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
  63. data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -2
  64. data/lib/capybara/spec/session/has_any_selectors_spec.rb +2 -2
  65. data/lib/capybara/spec/session/has_button_spec.rb +6 -0
  66. data/lib/capybara/spec/session/has_current_path_spec.rb +3 -3
  67. data/lib/capybara/spec/session/has_field_spec.rb +1 -1
  68. data/lib/capybara/spec/session/has_link_spec.rb +16 -0
  69. data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
  70. data/lib/capybara/spec/session/has_select_spec.rb +10 -4
  71. data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
  72. data/lib/capybara/spec/session/has_text_spec.rb +5 -13
  73. data/lib/capybara/spec/session/matches_style_spec.rb +2 -0
  74. data/lib/capybara/spec/session/node_spec.rb +81 -0
  75. data/lib/capybara/spec/session/reset_session_spec.rb +13 -0
  76. data/lib/capybara/spec/session/scroll_spec.rb +3 -1
  77. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  78. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  79. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  80. data/lib/capybara/spec/session/within_spec.rb +13 -0
  81. data/lib/capybara/spec/spec_helper.rb +8 -2
  82. data/lib/capybara/spec/test_app.rb +74 -6
  83. data/lib/capybara/spec/views/form.erb +17 -0
  84. data/lib/capybara/spec/views/with_html.erb +3 -3
  85. data/lib/capybara/spec/views/with_scope.erb +2 -2
  86. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  87. data/lib/capybara/version.rb +1 -1
  88. data/lib/capybara/window.rb +1 -1
  89. data/lib/capybara.rb +5 -2
  90. data/spec/capybara_spec.rb +12 -0
  91. data/spec/counter_spec.rb +35 -0
  92. data/spec/css_builder_spec.rb +1 -1
  93. data/spec/css_splitter_spec.rb +1 -1
  94. data/spec/dsl_spec.rb +4 -2
  95. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  96. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  97. data/spec/minitest_spec.rb +4 -0
  98. data/spec/minitest_spec_spec.rb +4 -0
  99. data/spec/per_session_config_spec.rb +1 -1
  100. data/spec/rack_test_spec.rb +16 -2
  101. data/spec/result_spec.rb +27 -29
  102. data/spec/rspec/features_spec.rb +2 -2
  103. data/spec/rspec/scenarios_spec.rb +2 -2
  104. data/spec/rspec/shared_spec_matchers.rb +1 -1
  105. data/spec/rspec_matchers_spec.rb +25 -0
  106. data/spec/rspec_spec.rb +2 -2
  107. data/spec/sauce_spec_chrome.rb +4 -4
  108. data/spec/selector_spec.rb +4 -4
  109. data/spec/selenium_spec_chrome.rb +8 -7
  110. data/spec/selenium_spec_chrome_remote.rb +9 -9
  111. data/spec/selenium_spec_edge.rb +12 -6
  112. data/spec/selenium_spec_firefox.rb +21 -5
  113. data/spec/selenium_spec_firefox_remote.rb +19 -4
  114. data/spec/selenium_spec_ie.rb +4 -2
  115. data/spec/selenium_spec_safari.rb +8 -2
  116. data/spec/server_spec.rb +7 -7
  117. data/spec/shared_selenium_session.rb +13 -6
  118. data/spec/spec_helper.rb +35 -2
  119. data/spec/whitespace_normalizer_spec.rb +54 -0
  120. data/spec/xpath_builder_spec.rb +1 -1
  121. metadata +9 -4
@@ -40,6 +40,7 @@ module Capybara
40
40
 
41
41
  NODE_METHODS = %i[
42
42
  all first attach_file text check choose scroll_to scroll_by
43
+ click double_click right_click
43
44
  click_link_or_button click_button click_link
44
45
  fill_in find find_all find_button find_by_id find_field find_link
45
46
  has_content? has_text? has_css? has_no_content? has_no_text?
@@ -58,7 +59,7 @@ module Capybara
58
59
  ].freeze
59
60
  SESSION_METHODS = %i[
60
61
  body html source current_url current_host current_path
61
- execute_script evaluate_script visit refresh go_back go_forward send_keys
62
+ execute_script evaluate_script evaluate_async_script visit refresh go_back go_forward send_keys
62
63
  within within_element within_fieldset within_table within_frame switch_to_frame
63
64
  current_window windows open_new_window switch_to_window within_window window_opened_by
64
65
  save_page save_and_open_page save_screenshot
@@ -129,6 +130,8 @@ module Capybara
129
130
  if @touched
130
131
  driver.reset!
131
132
  @touched = false
133
+ switch_to_frame(:top) rescue nil # rubocop:disable Style/RescueModifier
134
+ @scopes = [nil]
132
135
  end
133
136
  @server&.wait_for_pending_requests
134
137
  raise_server_error!
@@ -159,9 +162,8 @@ module Capybara
159
162
  if config.raise_server_errors
160
163
  raise CapybaraError, 'Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true'
161
164
  end
162
- rescue CapybaraError
163
- # needed to get the cause set correctly in JRuby -- otherwise we could just do raise @server.error
164
- raise @server.error, @server.error.message, @server.error.backtrace
165
+ rescue CapybaraError => capy_error # rubocop:disable Naming/RescuedExceptionsVariableName
166
+ raise @server.error, cause: capy_error
165
167
  ensure
166
168
  @server.reset_error!
167
169
  end
@@ -360,7 +362,7 @@ module Capybara
360
362
  new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args, **kw_args)
361
363
  begin
362
364
  scopes.push(new_scope)
363
- yield if block_given?
365
+ yield new_scope if block_given?
364
366
  ensure
365
367
  scopes.pop
366
368
  end
@@ -409,7 +411,7 @@ module Capybara
409
411
  scopes.push(:frame)
410
412
  when :parent
411
413
  if scopes.last != :frame
412
- raise Capybara::ScopeError, "`switch_to_frame(:parent)` cannot be called from inside a descendant frame's "\
414
+ raise Capybara::ScopeError, "`switch_to_frame(:parent)` cannot be called from inside a descendant frame's " \
413
415
  '`within` block.'
414
416
  end
415
417
  scopes.pop
@@ -419,7 +421,7 @@ module Capybara
419
421
  top_level_scopes = [:frame, nil]
420
422
  if idx
421
423
  if scopes.slice(idx..).any? { |scope| !top_level_scopes.include?(scope) }
422
- raise Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's "\
424
+ raise Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's " \
423
425
  '`within` block.'
424
426
  end
425
427
  scopes.slice!(idx..)
@@ -511,7 +513,7 @@ module Capybara
511
513
  raise ArgumentError, '`switch_to_window`: either window or block should be provided' if !window && !window_locator
512
514
 
513
515
  unless scopes.last.nil?
514
- raise Capybara::ScopeError, '`switch_to_window` is not supposed to be invoked from '\
516
+ raise Capybara::ScopeError, '`switch_to_window` is not supposed to be invoked from ' \
515
517
  '`within` or `within_frame` blocks.'
516
518
  end
517
519
 
@@ -582,7 +584,7 @@ module Capybara
582
584
  synchronize_windows(options) do
583
585
  opened_handles = (driver.window_handles - old_handles)
584
586
  if opened_handles.size != 1
585
- raise Capybara::WindowError, 'block passed to #window_opened_by '\
587
+ raise Capybara::WindowError, 'block passed to #window_opened_by ' \
586
588
  "opened #{opened_handles.size} windows instead of 1"
587
589
  end
588
590
  Window.new(self, opened_handles.first)
@@ -765,33 +767,20 @@ module Capybara
765
767
  end
766
768
 
767
769
  NODE_METHODS.each do |method|
768
- if RUBY_VERSION >= '2.7'
769
- class_eval <<~METHOD, __FILE__, __LINE__ + 1
770
- def #{method}(...)
771
- @touched = true
772
- current_scope.#{method}(...)
773
- end
774
- METHOD
775
- else
776
- define_method method do |*args, &block|
770
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
771
+ def #{method}(...)
777
772
  @touched = true
778
- current_scope.send(method, *args, &block)
773
+ current_scope.#{method}(...)
779
774
  end
780
- end
775
+ METHOD
781
776
  end
782
777
 
783
778
  DOCUMENT_METHODS.each do |method|
784
- if RUBY_VERSION >= '2.7'
785
- class_eval <<~METHOD, __FILE__, __LINE__ + 1
786
- def #{method}(...)
787
- document.#{method}(...)
788
- end
789
- METHOD
790
- else
791
- define_method method do |*args, &block|
792
- document.send(method, *args, &block)
779
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
780
+ def #{method}(...)
781
+ document.#{method}(...)
793
782
  end
794
- end
783
+ METHOD
795
784
  end
796
785
 
797
786
  def inspect
@@ -44,6 +44,10 @@ $(function() {
44
44
  $(this).after('<div class="log">DragOver with client position: ' + ev.clientX + ',' + ev.clientY)
45
45
  if ($(this).hasClass('drop')) { ev.preventDefault(); }
46
46
  });
47
+ $('#drop_html5, #drop_html5_scroll').on('dragenter', function(ev){
48
+ $(this).after('<div class="log">DragEnter')
49
+ if ($(this).hasClass('drop')) { ev.preventDefault(); }
50
+ });
47
51
  $('#drop_html5, #drop_html5_scroll').on('dragleave', function(ev){
48
52
  $(this).after('<div class="log">DragLeave with client position: ' + ev.clientX + ',' + ev.clientY)
49
53
  if ($(this).hasClass('drop')) { ev.preventDefault(); }
@@ -31,7 +31,7 @@ Capybara::SpecHelper.spec '#all' do
31
31
  it 'should accept an XPath instance', :exact_false do
32
32
  @session.visit('/form')
33
33
  @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('Name')
34
- expect(@xpath).to be_a(::XPath::Union)
34
+ expect(@xpath).to be_a(XPath::Union)
35
35
  @result = @session.all(@xpath).map(&:value)
36
36
  expect(@result).to include('Smith', 'John', 'John Smith')
37
37
  end
@@ -132,7 +132,7 @@ Capybara::SpecHelper.spec '#all' do
132
132
  it 'should use the sessions ignore_hidden_elements', psc: true do
133
133
  Capybara.ignore_hidden_elements = true
134
134
  @session.config.ignore_hidden_elements = false
135
- expect(Capybara.ignore_hidden_elements).to eq(true)
135
+ expect(Capybara.ignore_hidden_elements).to be(true)
136
136
  expect(@session.all(:css, 'a.simple').size).to eq(2)
137
137
  @session.config.ignore_hidden_elements = true
138
138
  expect(@session.all(:css, 'a.simple').size).to eq(1)
@@ -208,12 +208,10 @@ Capybara::SpecHelper.spec '#all' do
208
208
  expect { @session.all(:css, 'h1, p', between: 5..) }.to raise_error(Capybara::ExpectationNotMet)
209
209
  end
210
210
 
211
- eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
212
- it'treats a beginless range as maximum' do
213
- expect { @session.all(:css, 'h1, p', between: ..7) }.not_to raise_error
214
- expect { @session.all(:css, 'h1, p', between: ..3) }.to raise_error(Capybara::ExpectationNotMet)
215
- end
216
- TEST
211
+ it 'treats a beginless range as maximum' do
212
+ expect { @session.all(:css, 'h1, p', between: ..7) }.not_to raise_error
213
+ expect { @session.all(:css, 'h1, p', between: ..3) }.to raise_error(Capybara::ExpectationNotMet)
214
+ end
217
215
  end
218
216
 
219
217
  context 'with multiple count filters' do
@@ -3,16 +3,16 @@
3
3
  Capybara::SpecHelper.spec '#assert_text' do
4
4
  it 'should be true if the given text is on the page' do
5
5
  @session.visit('/with_html')
6
- expect(@session.assert_text('est')).to eq(true)
7
- expect(@session.assert_text('Lorem')).to eq(true)
8
- expect(@session.assert_text('Redirect')).to eq(true)
9
- expect(@session.assert_text(:Redirect)).to eq(true)
10
- expect(@session.assert_text('text with whitespace')).to eq(true)
6
+ expect(@session.assert_text('est')).to be(true)
7
+ expect(@session.assert_text('Lorem')).to be(true)
8
+ expect(@session.assert_text('Redirect')).to be(true)
9
+ expect(@session.assert_text(:Redirect)).to be(true)
10
+ expect(@session.assert_text('text with whitespace')).to be(true)
11
11
  end
12
12
 
13
13
  it 'should support collapsing whitespace' do
14
14
  @session.visit('/with_html')
15
- expect(@session.assert_text('text with whitespace', normalize_ws: true)).to eq(true)
15
+ expect(@session.assert_text('text with whitespace', normalize_ws: true)).to be(true)
16
16
  end
17
17
 
18
18
  context 'with enabled default collapsing whitespace' do
@@ -20,19 +20,19 @@ Capybara::SpecHelper.spec '#assert_text' do
20
20
 
21
21
  it 'should be true if the given unnormalized text is on the page' do
22
22
  @session.visit('/with_html')
23
- expect(@session.assert_text('text with whitespace', normalize_ws: false)).to eq(true)
23
+ expect(@session.assert_text('text with whitespace', normalize_ws: false)).to be(true)
24
24
  end
25
25
 
26
26
  it 'should support collapsing whitespace' do
27
27
  @session.visit('/with_html')
28
- expect(@session.assert_text('text with whitespace')).to eq(true)
28
+ expect(@session.assert_text('text with whitespace')).to be(true)
29
29
  end
30
30
  end
31
31
 
32
32
  it 'should take scopes into account' do
33
33
  @session.visit('/with_html')
34
34
  @session.within("//a[@title='awesome title']") do
35
- expect(@session.assert_text('labore')).to eq(true)
35
+ expect(@session.assert_text('labore')).to be(true)
36
36
  end
37
37
  end
38
38
 
@@ -47,13 +47,13 @@ Capybara::SpecHelper.spec '#assert_text' do
47
47
 
48
48
  it 'should be true if :all given and text is invisible.' do
49
49
  @session.visit('/with_html')
50
- expect(@session.assert_text(:all, 'Some of this text is hidden!')).to eq(true)
50
+ expect(@session.assert_text(:all, 'Some of this text is hidden!')).to be(true)
51
51
  end
52
52
 
53
53
  it 'should be true if `Capybara.ignore_hidden_elements = true` and text is invisible.' do
54
54
  Capybara.ignore_hidden_elements = false
55
55
  @session.visit('/with_html')
56
- expect(@session.assert_text('Some of this text is hidden!')).to eq(true)
56
+ expect(@session.assert_text('Some of this text is hidden!')).to be(true)
57
57
  end
58
58
 
59
59
  it 'should raise error with a helpful message if the requested text is present but invisible' do
@@ -88,7 +88,7 @@ Capybara::SpecHelper.spec '#assert_text' do
88
88
 
89
89
  it 'should be true if the text in the page matches given regexp' do
90
90
  @session.visit('/with_html')
91
- expect(@session.assert_text(/Lorem/)).to eq(true)
91
+ expect(@session.assert_text(/Lorem/)).to be(true)
92
92
  end
93
93
 
94
94
  it "should raise error if the text in the page doesn't match given regexp" do
@@ -109,13 +109,13 @@ Capybara::SpecHelper.spec '#assert_text' do
109
109
  Capybara.default_max_wait_time = 2
110
110
  @session.visit('/with_js')
111
111
  @session.click_link('Click me')
112
- expect(@session.assert_text('Has been clicked')).to eq(true)
112
+ expect(@session.assert_text('Has been clicked')).to be(true)
113
113
  end
114
114
 
115
115
  context 'with between' do
116
116
  it 'should be true if the text occurs within the range given' do
117
117
  @session.visit('/with_count')
118
- expect(@session.assert_text('count', between: 1..3)).to eq(true)
118
+ expect(@session.assert_text('count', between: 1..3)).to be(true)
119
119
  end
120
120
 
121
121
  it 'should be false if the text occurs more or fewer times than range' do
@@ -203,13 +203,13 @@ Capybara::SpecHelper.spec '#assert_no_text' do
203
203
  it 'should be true if scoped to an element which does not have the text' do
204
204
  @session.visit('/with_html')
205
205
  @session.within("//a[@title='awesome title']") do
206
- expect(@session.assert_no_text('monkey')).to eq(true)
206
+ expect(@session.assert_no_text('monkey')).to be(true)
207
207
  end
208
208
  end
209
209
 
210
210
  it 'should be true if the given text is on the page but not visible' do
211
211
  @session.visit('/with_html')
212
- expect(@session.assert_no_text('Inside element with hidden ancestor')).to eq(true)
212
+ expect(@session.assert_no_text('Inside element with hidden ancestor')).to be(true)
213
213
  end
214
214
 
215
215
  it 'should raise error if :all given and text is invisible.' do
@@ -236,7 +236,7 @@ Capybara::SpecHelper.spec '#assert_no_text' do
236
236
  context 'with count' do
237
237
  it 'should be true if the text occurs within the range given' do
238
238
  @session.visit('/with_count')
239
- expect(@session.assert_text('count', count: 2)).to eq(true)
239
+ expect(@session.assert_text('count', count: 2)).to be(true)
240
240
  end
241
241
 
242
242
  it 'should be false if the text occurs more or fewer times than range' do
@@ -55,6 +55,12 @@ Capybara::SpecHelper.spec '#attach_file' do
55
55
  expect(@session).to have_content('No file uploaded')
56
56
  end
57
57
 
58
+ it 'should send prior hidden field if no file submitted' do
59
+ @session.click_button('Upload Empty With Hidden')
60
+ expect(extract_results(@session)['document2']).to eq('hidden_field')
61
+ expect(extract_content_type(@session)).to start_with('multipart/form-data;')
62
+ end
63
+
58
64
  it 'should send content type text/plain when uploading a text file' do
59
65
  @session.attach_file 'Single Document', with_os_path_separators(test_file_path)
60
66
  @session.click_button 'Upload Single'
@@ -239,6 +239,7 @@ Capybara::SpecHelper.spec '#check' do
239
239
 
240
240
  context 'with allow_label_click options', requires: [:js] do
241
241
  it 'should allow offsets to click location on label' do
242
+ Capybara.w3c_click_offset = false
242
243
  expect(@session.find(:checkbox, 'form_cars_lotus', unchecked: true, visible: :hidden)).to be_truthy
243
244
  @session.check('form_cars_lotus', allow_label_click: { x: 90, y: 10 })
244
245
  @session.click_button('awesome')
@@ -131,6 +131,17 @@ Capybara::SpecHelper.spec '#click_link' do
131
131
  end
132
132
  end
133
133
 
134
+ context 'with :target option given' do
135
+ it 'should find links with valid target' do
136
+ @session.click_link('labore', target: '_self')
137
+ expect(@session).to have_content('Bar')
138
+ end
139
+
140
+ it "should raise error if link wasn't found" do
141
+ expect { @session.click_link('labore', target: '_blank') }.to raise_error(Capybara::ElementNotFound, /Unable to find link "labore"/)
142
+ end
143
+ end
144
+
134
145
  it 'should follow relative links' do
135
146
  @session.visit('/')
136
147
  @session.click_link('Relative')
@@ -7,7 +7,7 @@ Capybara::SpecHelper.spec '#current_scope' do
7
7
 
8
8
  context 'when not in a #within block' do
9
9
  it 'should return the document' do
10
- expect(@session.current_scope).to be_kind_of Capybara::Node::Document
10
+ expect(@session.current_scope).to be_a Capybara::Node::Document
11
11
  end
12
12
  end
13
13
 
@@ -98,6 +98,12 @@ Capybara::SpecHelper.spec '#fill_in' do
98
98
  expect(extract_results(@session)['description']).to eq("\r\nSome text\r\n")
99
99
  end
100
100
 
101
+ it 'should handle carriage returns with line feeds in a textarea correctly' do
102
+ @session.fill_in('form_description', with: "\r\nSome text\r\n")
103
+ @session.click_button('awesome')
104
+ expect(extract_results(@session)['description']).to eq("\r\nSome text\r\n")
105
+ end
106
+
101
107
  it 'should fill in a color field' do
102
108
  @session.fill_in('Html5 Color', with: '#112233')
103
109
  @session.click_button('html5_submit')
@@ -67,4 +67,14 @@ Capybara::SpecHelper.spec '#find_link' do
67
67
  expect { @session.find_link(download: 37) }.to raise_error ArgumentError
68
68
  end
69
69
  end
70
+
71
+ context 'with :target option' do
72
+ it 'should accept partial matches when false' do
73
+ expect(@session.find_link(target: '_self').text).to eq('labore')
74
+ end
75
+
76
+ it 'should not accept partial matches when true' do
77
+ expect { @session.find_link(target: '_blank') }.to raise_error Capybara::ElementNotFound
78
+ end
79
+ end
70
80
  end
@@ -236,7 +236,7 @@ Capybara::SpecHelper.spec '#find' do
236
236
  it 'should accept an XPath instance' do
237
237
  @session.visit('/form')
238
238
  @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')
239
- expect(@xpath).to be_a(::XPath::Union)
239
+ expect(@xpath).to be_a(XPath::Union)
240
240
  expect(@session.find(@xpath).value).to eq('John')
241
241
  end
242
242
 
@@ -528,4 +528,10 @@ Capybara::SpecHelper.spec '#find' do
528
528
  expect(@session.find(:link, 'test-foo')[:id]).to eq 'foo'
529
529
  end
530
530
  end
531
+
532
+ it 'should warn if passed count options' do
533
+ allow(Capybara::Helpers).to receive(:warn)
534
+ @session.find('//h1', count: 44)
535
+ expect(Capybara::Helpers).to have_received(:warn).with(/'find' does not support count options/)
536
+ end
531
537
  end
@@ -25,7 +25,7 @@ Capybara::SpecHelper.spec '#first' do
25
25
  it 'should accept an XPath instance' do
26
26
  @session.visit('/form')
27
27
  @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')
28
- expect(@xpath).to be_a(::XPath::Union)
28
+ expect(@xpath).to be_a(XPath::Union)
29
29
  expect(@session.first(@xpath).value).to eq('John')
30
30
  end
31
31
 
@@ -64,7 +64,9 @@ Capybara::SpecHelper.spec '#within_frame', requires: [:frames] do
64
64
  end
65
65
  expect do
66
66
  # Multiple frames in scope here
67
+ # rubocop:disable Style/Semicolon
67
68
  @session.within_frame { ; }
69
+ # rubocop:enable Style/Semicolon
68
70
  end.to raise_error Capybara::Ambiguous
69
71
  end
70
72
 
@@ -12,7 +12,7 @@ Capybara::SpecHelper.spec '#have_all_of_selectors' do
12
12
  it 'should be false if any of the given selectors are not on the page' do
13
13
  expect do
14
14
  expect(@session).to have_all_of_selectors(:css, 'p a#foo', 'h2#h2three', 'h2#h2one')
15
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
15
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
16
16
  end
17
17
 
18
18
  it 'should use default selector' do
@@ -20,7 +20,7 @@ Capybara::SpecHelper.spec '#have_all_of_selectors' do
20
20
  expect(@session).to have_all_of_selectors('p a#foo', 'h2#h2two', 'h2#h2one')
21
21
  expect do
22
22
  expect(@session).to have_all_of_selectors('p a#foo', 'h2#h2three', 'h2#h2one')
23
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
23
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
24
24
  end
25
25
 
26
26
  context 'should respect scopes' do
@@ -29,7 +29,7 @@ Capybara::SpecHelper.spec '#have_all_of_selectors' do
29
29
  expect(@session).to have_all_of_selectors(".//a[@id='foo']")
30
30
  expect do
31
31
  expect(@session).to have_all_of_selectors(".//a[@id='red']")
32
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
32
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
33
33
  end
34
34
  end
35
35
 
@@ -38,7 +38,7 @@ Capybara::SpecHelper.spec '#have_all_of_selectors' do
38
38
  expect(el).to have_all_of_selectors(".//a[@id='foo']")
39
39
  expect do
40
40
  expect(el).to have_all_of_selectors(".//a[@id='red']")
41
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
41
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
42
42
  end
43
43
  end
44
44
 
@@ -47,7 +47,7 @@ Capybara::SpecHelper.spec '#have_all_of_selectors' do
47
47
  expect(@session).to have_all_of_selectors(:field, 'normal', 'additional_newline', type: :textarea)
48
48
  expect do
49
49
  expect(@session).to have_all_of_selectors(:field, 'normal', 'test_field', 'additional_newline', type: :textarea)
50
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
50
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
51
51
  end
52
52
  end
53
53
 
@@ -39,8 +39,8 @@ Capybara::SpecHelper.spec '#have_no_ancestor' do
39
39
  it 'should assert no matching ancestor' do
40
40
  el = @session.find(:css, '#ancestor1')
41
41
  expect(el).to have_no_ancestor(:css, '#child')
42
- expect(el).to have_no_ancestor(:css, '#ancestor1_sibiling')
42
+ expect(el).to have_no_ancestor(:css, '#ancestor1_sibling')
43
43
  expect(el).not_to have_ancestor(:css, '#child')
44
- expect(el).not_to have_ancestor(:css, '#ancestor1_sibiling')
44
+ expect(el).not_to have_ancestor(:css, '#ancestor1_sibling')
45
45
  end
46
46
  end
@@ -12,7 +12,7 @@ Capybara::SpecHelper.spec '#have_any_of_selectors' do
12
12
  it 'should be false if none of the given selectors are not on the page' do
13
13
  expect do
14
14
  expect(@session).to have_any_of_selectors(:css, 'span a#foo', 'h2#h2nope', 'h2#h2one_no')
15
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
15
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
16
16
  end
17
17
 
18
18
  it 'should use default selector' do
@@ -20,7 +20,7 @@ Capybara::SpecHelper.spec '#have_any_of_selectors' do
20
20
  expect(@session).to have_any_of_selectors('p a#foo', 'h2#h2two', 'a#not_on_page')
21
21
  expect do
22
22
  expect(@session).to have_any_of_selectors('p a#blah', 'h2#h2three')
23
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
23
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
24
24
  end
25
25
 
26
26
  it 'should be negateable' do
@@ -77,6 +77,12 @@ Capybara::SpecHelper.spec '#has_button?' do
77
77
  expect(@session).to have_button('A Button', focused: false)
78
78
  end
79
79
  end
80
+
81
+ it 'should raise an error if an invalid option is passed' do
82
+ expect do
83
+ expect(@session).to have_button('A Button', invalid: true)
84
+ end.to raise_error(ArgumentError, 'Invalid option(s) :invalid, should be one of :above, :below, :left_of, :right_of, :near, :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :obscured, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :focused, :disabled, :name, :value, :title, :type')
85
+ end
80
86
  end
81
87
 
82
88
  Capybara::SpecHelper.spec '#has_no_button?' do
@@ -16,8 +16,8 @@ Capybara::SpecHelper.spec '#has_current_path?' do
16
16
 
17
17
  it 'should not raise an error when non-http' do
18
18
  @session.reset_session!
19
- expect(@session.has_current_path?(/monkey/)).to eq false
20
- expect(@session.has_current_path?('/with_js')).to eq false
19
+ expect(@session.has_current_path?(/monkey/)).to be false
20
+ expect(@session.has_current_path?('/with_js')).to be false
21
21
  end
22
22
 
23
23
  it 'should handle non-escaped query options' do
@@ -75,7 +75,7 @@ Capybara::SpecHelper.spec '#has_current_path?' do
75
75
  @session.visit('/with_js?test=test')
76
76
  expect(@session).to have_current_path('/with_js?test=test')
77
77
  expect(@session).to have_current_path('/with_js', ignore_query: true)
78
- uri = ::Addressable::URI.parse(@session.current_url)
78
+ uri = Addressable::URI.parse(@session.current_url)
79
79
  uri.query = nil
80
80
  expect(@session).to have_current_path(uri.to_s, ignore_query: true)
81
81
  end
@@ -383,7 +383,7 @@ Capybara::SpecHelper.spec '#has_no_unchecked_field?' do
383
383
  end
384
384
 
385
385
  it 'should support locator-less usage' do
386
- expect(@session.has_no_unchecked_field?(disabled: false, id: 'form_disabled_unchecked_checkbox')).to eq true
386
+ expect(@session.has_no_unchecked_field?(disabled: false, id: 'form_disabled_unchecked_checkbox')).to be true
387
387
  expect(@session).to have_no_unchecked_field(disabled: false, id: 'form_disabled_unchecked_checkbox')
388
388
  end
389
389
  end
@@ -11,12 +11,20 @@ Capybara::SpecHelper.spec '#has_link?' do
11
11
  expect(@session).to have_link('A link', href: '/with_simple_html')
12
12
  expect(@session).to have_link(:'A link', href: :'/with_simple_html')
13
13
  expect(@session).to have_link('A link', href: %r{/with_simple_html})
14
+ expect(@session).to have_link('labore', target: '_self')
14
15
  end
15
16
 
16
17
  it 'should be false if the given link is not on the page' do
17
18
  expect(@session).not_to have_link('monkey')
18
19
  expect(@session).not_to have_link('A link', href: '/nonexistent-href')
19
20
  expect(@session).not_to have_link('A link', href: /nonexistent/)
21
+ expect(@session).not_to have_link('labore', target: '_blank')
22
+ end
23
+
24
+ it 'should notify if an invalid locator is specified' do
25
+ allow(Capybara::Helpers).to receive(:warn).and_return(nil)
26
+ @session.has_link?(@session)
27
+ expect(Capybara::Helpers).to have_received(:warn).with(/Called from: .+/)
20
28
  end
21
29
 
22
30
  context 'with focused:', requires: [:active_element] do
@@ -30,6 +38,12 @@ Capybara::SpecHelper.spec '#has_link?' do
30
38
  expect(@session).to have_link('labore', focused: false)
31
39
  end
32
40
  end
41
+
42
+ it 'should raise an error if an invalid option is passed' do
43
+ expect do
44
+ expect(@session).to have_link('labore', invalid: true)
45
+ end.to raise_error(ArgumentError, 'Invalid option(s) :invalid, should be one of :above, :below, :left_of, :right_of, :near, :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :obscured, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :focused, :href, :alt, :title, :target, :download')
46
+ end
33
47
  end
34
48
 
35
49
  Capybara::SpecHelper.spec '#has_no_link?' do
@@ -41,12 +55,14 @@ Capybara::SpecHelper.spec '#has_no_link?' do
41
55
  expect(@session).not_to have_no_link('foo')
42
56
  expect(@session).not_to have_no_link('awesome title')
43
57
  expect(@session).not_to have_no_link('A link', href: '/with_simple_html')
58
+ expect(@session).not_to have_no_link('labore', target: '_self')
44
59
  end
45
60
 
46
61
  it 'should be true if the given link is not on the page' do
47
62
  expect(@session).to have_no_link('monkey')
48
63
  expect(@session).to have_no_link('A link', href: '/nonexistent-href')
49
64
  expect(@session).to have_no_link('A link', href: %r{/nonexistent-href})
65
+ expect(@session).to have_no_link('labore', target: '_blank')
50
66
  end
51
67
 
52
68
  context 'with focused:', requires: [:active_element] do
@@ -8,10 +8,10 @@ Capybara::SpecHelper.spec '#have_none_of_selectors' do
8
8
  it 'should be false if any of the given locators are on the page' do
9
9
  expect do
10
10
  expect(@session).to have_none_of_selectors(:xpath, '//p', '//a')
11
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
11
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
12
12
  expect do
13
13
  expect(@session).to have_none_of_selectors(:css, 'p a#foo')
14
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
14
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
15
15
  end
16
16
 
17
17
  it 'should be true if none of the given locators are on the page' do
@@ -24,7 +24,7 @@ Capybara::SpecHelper.spec '#have_none_of_selectors' do
24
24
  expect(@session).to have_none_of_selectors('p a#doesnotexist', 'abbr')
25
25
  expect do
26
26
  expect(@session).to have_none_of_selectors('abbr', 'p a#foo')
27
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
27
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
28
28
  end
29
29
 
30
30
  context 'should respect scopes' do
@@ -32,7 +32,7 @@ Capybara::SpecHelper.spec '#have_none_of_selectors' do
32
32
  @session.within "//p[@id='first']" do
33
33
  expect do
34
34
  expect(@session).to have_none_of_selectors(".//a[@id='foo']")
35
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
35
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
36
36
  expect(@session).to have_none_of_selectors(".//a[@id='red']")
37
37
  end
38
38
  end
@@ -41,7 +41,7 @@ Capybara::SpecHelper.spec '#have_none_of_selectors' do
41
41
  el = @session.find "//p[@id='first']"
42
42
  expect do
43
43
  expect(el).to have_none_of_selectors(".//a[@id='foo']")
44
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
44
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
45
45
  expect(el).to have_none_of_selectors(".//a[@id='red']")
46
46
  end
47
47
  end
@@ -50,14 +50,14 @@ Capybara::SpecHelper.spec '#have_none_of_selectors' do
50
50
  it 'should apply the options to all locators' do
51
51
  expect do
52
52
  expect(@session).to have_none_of_selectors('//p//a', text: 'Redirect')
53
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
53
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
54
54
  expect(@session).to have_none_of_selectors('//p', text: 'Doesnotexist')
55
55
  end
56
56
 
57
57
  it 'should discard all matches where the given regexp is matched' do
58
58
  expect do
59
59
  expect(@session).to have_none_of_selectors('//p//a', text: /re[dab]i/i, count: 1)
60
- end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
60
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
61
61
  expect(@session).to have_none_of_selectors('//p//a', text: /Red$/)
62
62
  end
63
63
  end