capybara 3.3.1 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +16 -0
  3. data/README.md +5 -7
  4. data/lib/capybara.rb +7 -6
  5. data/lib/capybara/config.rb +1 -1
  6. data/lib/capybara/dsl.rb +2 -2
  7. data/lib/capybara/helpers.rb +3 -3
  8. data/lib/capybara/minitest/spec.rb +3 -3
  9. data/lib/capybara/node/actions.rb +18 -18
  10. data/lib/capybara/node/base.rb +1 -1
  11. data/lib/capybara/node/element.rb +2 -2
  12. data/lib/capybara/node/finders.rb +6 -6
  13. data/lib/capybara/node/matchers.rb +5 -5
  14. data/lib/capybara/node/simple.rb +2 -2
  15. data/lib/capybara/queries/ancestor_query.rb +1 -1
  16. data/lib/capybara/queries/base_query.rb +12 -11
  17. data/lib/capybara/queries/current_path_query.rb +1 -1
  18. data/lib/capybara/queries/selector_query.rb +39 -15
  19. data/lib/capybara/queries/sibling_query.rb +1 -1
  20. data/lib/capybara/queries/text_query.rb +1 -1
  21. data/lib/capybara/rack_test/browser.rb +7 -7
  22. data/lib/capybara/rack_test/driver.rb +1 -1
  23. data/lib/capybara/rack_test/form.rb +7 -7
  24. data/lib/capybara/rack_test/node.rb +16 -16
  25. data/lib/capybara/rails.rb +1 -1
  26. data/lib/capybara/result.rb +8 -4
  27. data/lib/capybara/rspec/features.rb +4 -4
  28. data/lib/capybara/rspec/matchers.rb +6 -6
  29. data/lib/capybara/selector.rb +106 -90
  30. data/lib/capybara/selector/css.rb +4 -4
  31. data/lib/capybara/selector/filter_set.rb +52 -8
  32. data/lib/capybara/selector/selector.rb +39 -15
  33. data/lib/capybara/selenium/driver.rb +10 -10
  34. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +8 -0
  35. data/lib/capybara/selenium/node.rb +9 -10
  36. data/lib/capybara/selenium/nodes/chrome_node.rb +18 -0
  37. data/lib/capybara/selenium/nodes/marionette_node.rb +32 -7
  38. data/lib/capybara/server.rb +3 -3
  39. data/lib/capybara/server/animation_disabler.rb +1 -1
  40. data/lib/capybara/server/middleware.rb +1 -1
  41. data/lib/capybara/session.rb +23 -19
  42. data/lib/capybara/session/config.rb +18 -3
  43. data/lib/capybara/spec/public/test.js +1 -1
  44. data/lib/capybara/spec/session/accept_alert_spec.rb +10 -10
  45. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  46. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  47. data/lib/capybara/spec/session/all_spec.rb +33 -32
  48. data/lib/capybara/spec/session/ancestor_spec.rb +19 -19
  49. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +38 -38
  50. data/lib/capybara/spec/session/assert_current_path_spec.rb +16 -16
  51. data/lib/capybara/spec/session/assert_selector_spec.rb +53 -53
  52. data/lib/capybara/spec/session/assert_style_spec.rb +3 -3
  53. data/lib/capybara/spec/session/assert_text_spec.rb +31 -30
  54. data/lib/capybara/spec/session/assert_title_spec.rb +12 -12
  55. data/lib/capybara/spec/session/attach_file_spec.rb +51 -52
  56. data/lib/capybara/spec/session/body_spec.rb +6 -6
  57. data/lib/capybara/spec/session/check_spec.rb +52 -47
  58. data/lib/capybara/spec/session/choose_spec.rb +32 -32
  59. data/lib/capybara/spec/session/click_button_spec.rb +103 -103
  60. data/lib/capybara/spec/session/click_link_or_button_spec.rb +24 -23
  61. data/lib/capybara/spec/session/click_link_spec.rb +49 -48
  62. data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
  63. data/lib/capybara/spec/session/current_url_spec.rb +26 -27
  64. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  65. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  66. data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +8 -8
  67. data/lib/capybara/spec/session/element/match_css_spec.rb +10 -10
  68. data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
  69. data/lib/capybara/spec/session/element/matches_selector_spec.rb +51 -51
  70. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  71. data/lib/capybara/spec/session/evaluate_script_spec.rb +15 -8
  72. data/lib/capybara/spec/session/execute_script_spec.rb +7 -7
  73. data/lib/capybara/spec/session/fill_in_spec.rb +43 -42
  74. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  75. data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
  76. data/lib/capybara/spec/session/find_field_spec.rb +32 -30
  77. data/lib/capybara/spec/session/find_link_spec.rb +21 -21
  78. data/lib/capybara/spec/session/find_spec.rb +153 -135
  79. data/lib/capybara/spec/session/first_spec.rb +41 -41
  80. data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
  81. data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
  82. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +17 -17
  83. data/lib/capybara/spec/session/frame/within_frame_spec.rb +31 -17
  84. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  85. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  86. data/lib/capybara/spec/session/has_all_selectors_spec.rb +17 -17
  87. data/lib/capybara/spec/session/has_button_spec.rb +13 -13
  88. data/lib/capybara/spec/session/has_css_spec.rb +133 -131
  89. data/lib/capybara/spec/session/has_current_path_spec.rb +29 -29
  90. data/lib/capybara/spec/session/has_field_spec.rb +58 -58
  91. data/lib/capybara/spec/session/has_link_spec.rb +4 -4
  92. data/lib/capybara/spec/session/has_none_selectors_spec.rb +24 -24
  93. data/lib/capybara/spec/session/has_select_spec.rb +43 -43
  94. data/lib/capybara/spec/session/has_selector_spec.rb +71 -71
  95. data/lib/capybara/spec/session/has_style_spec.rb +3 -3
  96. data/lib/capybara/spec/session/has_table_spec.rb +4 -4
  97. data/lib/capybara/spec/session/has_text_spec.rb +53 -52
  98. data/lib/capybara/spec/session/has_title_spec.rb +14 -14
  99. data/lib/capybara/spec/session/has_xpath_spec.rb +39 -38
  100. data/lib/capybara/spec/session/headers_spec.rb +1 -1
  101. data/lib/capybara/spec/session/html_spec.rb +6 -6
  102. data/lib/capybara/spec/session/node_spec.rb +129 -123
  103. data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
  104. data/lib/capybara/spec/session/refresh_spec.rb +4 -7
  105. data/lib/capybara/spec/session/reset_session_spec.rb +28 -28
  106. data/lib/capybara/spec/session/response_code_spec.rb +1 -1
  107. data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
  108. data/lib/capybara/spec/session/save_page_spec.rb +37 -37
  109. data/lib/capybara/spec/session/save_screenshot_spec.rb +6 -6
  110. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  111. data/lib/capybara/spec/session/select_spec.rb +81 -81
  112. data/lib/capybara/spec/session/selectors_spec.rb +17 -17
  113. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  114. data/lib/capybara/spec/session/text_spec.rb +23 -23
  115. data/lib/capybara/spec/session/title_spec.rb +5 -5
  116. data/lib/capybara/spec/session/uncheck_spec.rb +24 -20
  117. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  118. data/lib/capybara/spec/session/visit_spec.rb +48 -49
  119. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
  120. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +16 -16
  121. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -2
  122. data/lib/capybara/spec/session/window/window_spec.rb +4 -4
  123. data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
  124. data/lib/capybara/spec/session/within_spec.rb +41 -41
  125. data/lib/capybara/spec/spec_helper.rb +11 -9
  126. data/lib/capybara/spec/test_app.rb +18 -17
  127. data/lib/capybara/spec/views/form.erb +29 -31
  128. data/lib/capybara/spec/views/with_html.erb +2 -2
  129. data/lib/capybara/version.rb +1 -1
  130. data/spec/basic_node_spec.rb +23 -23
  131. data/spec/capybara_spec.rb +20 -20
  132. data/spec/css_splitter_spec.rb +7 -7
  133. data/spec/dsl_spec.rb +37 -32
  134. data/spec/filter_set_spec.rb +4 -4
  135. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  136. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  137. data/spec/minitest_spec.rb +4 -4
  138. data/spec/minitest_spec_spec.rb +23 -23
  139. data/spec/per_session_config_spec.rb +5 -5
  140. data/spec/rack_test_spec.rb +44 -44
  141. data/spec/result_spec.rb +14 -14
  142. data/spec/rspec/features_spec.rb +13 -13
  143. data/spec/rspec/scenarios_spec.rb +4 -4
  144. data/spec/rspec/shared_spec_matchers.rb +282 -281
  145. data/spec/rspec/views_spec.rb +3 -3
  146. data/spec/rspec_matchers_spec.rb +10 -10
  147. data/spec/rspec_spec.rb +29 -29
  148. data/spec/selector_spec.rb +64 -64
  149. data/spec/selenium_spec_chrome.rb +14 -22
  150. data/spec/selenium_spec_chrome_remote.rb +28 -8
  151. data/spec/selenium_spec_edge.rb +9 -4
  152. data/spec/selenium_spec_firefox_remote.rb +87 -0
  153. data/spec/selenium_spec_ie.rb +9 -4
  154. data/spec/selenium_spec_marionette.rb +42 -18
  155. data/spec/server_spec.rb +29 -27
  156. data/spec/session_spec.rb +17 -17
  157. data/spec/shared_selenium_session.rb +70 -52
  158. data/spec/spec_helper.rb +1 -1
  159. metadata +4 -2
@@ -10,7 +10,7 @@ module Capybara
10
10
  super(options)
11
11
  @expected_path = expected_path
12
12
  @options = {
13
- url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path || "").hostname.nil?,
13
+ url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path || '').hostname.nil?,
14
14
  ignore_query: false
15
15
  }.merge(options)
16
16
  assert_valid_keys
@@ -8,7 +8,12 @@ module Capybara
8
8
  VALID_KEYS = COUNT_KEYS + %i[text id class visible exact exact_text match wait filter_set]
9
9
  VALID_MATCH = %i[first smart prefer_exact one].freeze
10
10
 
11
- def initialize(*args, session_options:, **options, &filter_block)
11
+ def initialize(*args,
12
+ session_options:,
13
+ enable_aria_label: session_options.enable_aria_label,
14
+ test_id: session_options.test_id,
15
+ **options,
16
+ &filter_block)
12
17
  @resolved_node = nil
13
18
  @options = options.dup
14
19
  super(@options)
@@ -20,7 +25,7 @@ module Capybara
20
25
 
21
26
  raise ArgumentError, "Unused parameters passed to #{self.class.name} : #{args}" unless args.empty?
22
27
 
23
- @expression = @selector.call(@locator, @options.merge(enable_aria_label: session_options.enable_aria_label))
28
+ @expression = @selector.call(@locator, @options.merge(selector_config: { enable_aria_label: enable_aria_label, test_id: test_id }))
24
29
 
25
30
  warn_exact_usage
26
31
 
@@ -30,22 +35,31 @@ module Capybara
30
35
  def name; selector.name; end
31
36
  def label; selector.label || selector.name; end
32
37
 
33
- def description
34
- @description = +""
35
- @description << "visible " if visible == :visible
36
- @description << "non-visible " if visible == :hidden
38
+ def description(applied = false)
39
+ @description = +''
40
+ if !applied || @applied_filters
41
+ @description << 'visible ' if visible == :visible
42
+ @description << 'non-visible ' if visible == :hidden
43
+ end
37
44
  @description << "#{label} #{locator.inspect}"
38
- @description << " with#{' exact' if exact_text == true} text #{options[:text].inspect}" if options[:text]
39
- @description << " with exact text #{exact_text}" if exact_text.is_a?(String)
45
+ if !applied || @applied_filters
46
+ @description << " with#{' exact' if exact_text == true} text #{options[:text].inspect}" if options[:text]
47
+ @description << " with exact text #{exact_text}" if exact_text.is_a?(String)
48
+ end
40
49
  @description << " with id #{options[:id]}" if options[:id]
41
50
  @description << " with classes [#{Array(options[:class]).join(',')}]" if options[:class]
42
- @description << selector.description(options)
43
- @description << " that also matches the custom filter block" if @filter_block
51
+ @description << selector.description(node_filters: !applied || (@applied_filters == :node), **options)
52
+ @description << ' that also matches the custom filter block' if @filter_block && (!applied || (@applied_filters == :node))
44
53
  @description << " within #{@resolved_node.inspect}" if describe_within?
45
54
  @description
46
55
  end
47
56
 
57
+ def applied_description
58
+ description(true)
59
+ end
60
+
48
61
  def matches_filters?(node)
62
+ @applied_filters ||= :system
49
63
  return false if options[:text] && !matches_text_filter(node, options[:text])
50
64
  return false if exact_text.is_a?(String) && !matches_exact_text_filter(node, exact_text)
51
65
 
@@ -54,6 +68,7 @@ module Capybara
54
68
  when :hidden then return false if node.visible?
55
69
  end
56
70
 
71
+ @applied_filters = :node
57
72
  matches_node_filters?(node) && matches_filter_block?(node)
58
73
  rescue *(node.respond_to?(:session) ? node.session.driver.invalid_element_errors : [])
59
74
  false
@@ -88,6 +103,7 @@ module Capybara
88
103
 
89
104
  # @api private
90
105
  def resolve_for(node, exact = nil)
106
+ @applied_filters = false
91
107
  @resolved_node = node
92
108
  node.synchronize do
93
109
  children = if selector.format == :css
@@ -110,6 +126,14 @@ module Capybara
110
126
  @expression.respond_to? :to_xpath
111
127
  end
112
128
 
129
+ def failure_message
130
+ +"expected to find #{applied_description}" << count_message
131
+ end
132
+
133
+ def negative_failure_message
134
+ +"expected not to find #{applied_description}" << count_message
135
+ end
136
+
113
137
  private
114
138
 
115
139
  def find_selector(locator)
@@ -184,8 +208,8 @@ module Capybara
184
208
  end
185
209
 
186
210
  return if unhandled_options.empty?
187
- invalid_names = unhandled_options.map(&:inspect).join(", ")
188
- valid_names = valid_keys.map(&:inspect).join(", ")
211
+ invalid_names = unhandled_options.map(&:inspect).join(', ')
212
+ valid_names = valid_keys.map(&:inspect).join(', ')
189
213
  raise ArgumentError, "invalid keys #{invalid_names}, should be one of #{valid_names}"
190
214
  end
191
215
 
@@ -219,10 +243,10 @@ module Capybara
219
243
  process_class = options.key?(:class) && !custom_keys.include?(:class)
220
244
 
221
245
  if process_id && options[:id].is_a?(XPath::Expression)
222
- raise ArgumentError, "XPath expressions are not supported for the :id filter with CSS based selectors"
246
+ raise ArgumentError, 'XPath expressions are not supported for the :id filter with CSS based selectors'
223
247
  end
224
248
  if process_class && options[:class].is_a?(XPath::Expression)
225
- raise ArgumentError, "XPath expressions are not supported for the :class filter with CSS based selectors"
249
+ raise ArgumentError, 'XPath expressions are not supported for the :class filter with CSS based selectors'
226
250
  end
227
251
 
228
252
  if process_id || process_class
@@ -230,7 +254,7 @@ module Capybara
230
254
  sel += "##{::Capybara::Selector::CSS.escape(options[:id])}" if process_id
231
255
  sel += css_from_classes(Array(options[:class])) if process_class
232
256
  sel
233
- end.join(", ")
257
+ end.join(', ')
234
258
  end
235
259
 
236
260
  expr
@@ -14,7 +14,7 @@ module Capybara
14
14
  end
15
15
  end
16
16
 
17
- def description
17
+ def description(applied = false)
18
18
  desc = super
19
19
  sibling_query = @sibling_node&.instance_variable_get(:@query)
20
20
  desc += " that is a sibling of #{sibling_query.description}" if sibling_query
@@ -50,7 +50,7 @@ module Capybara
50
50
  end
51
51
 
52
52
  def build_message(report_on_invisible)
53
- message = +""
53
+ message = +''
54
54
  unless (COUNT_KEYS & @options.keys).empty?
55
55
  message << " but found #{@count} #{Capybara::Helpers.declension('time', 'times', @count)}"
56
56
  end
@@ -46,9 +46,9 @@ class Capybara::RackTest::Browser
46
46
  driver.redirect_limit.times do
47
47
  if last_response.redirect?
48
48
  if [307, 308].include? last_response.status
49
- process(last_request.request_method, last_response["Location"], last_request.params, env)
49
+ process(last_request.request_method, last_response['Location'], last_request.params, env)
50
50
  else
51
- process(:get, last_response["Location"], {}, env)
51
+ process(:get, last_response['Location'], {}, env)
52
52
  end
53
53
  end
54
54
  end
@@ -61,8 +61,8 @@ class Capybara::RackTest::Browser
61
61
  if path.empty?
62
62
  new_uri.path = request_path
63
63
  else
64
- new_uri.path = request_path if path.start_with?("?")
65
- new_uri.path = "/" if new_uri.path.empty?
64
+ new_uri.path = request_path if path.start_with?('?')
65
+ new_uri.path = '/' if new_uri.path.empty?
66
66
  new_uri.path = request_path.sub(%r{/[^/]*$}, '/') + new_uri.path unless new_uri.path.start_with?('/')
67
67
  end
68
68
  new_uri.scheme ||= @current_scheme
@@ -78,7 +78,7 @@ class Capybara::RackTest::Browser
78
78
  def current_url
79
79
  last_request.url
80
80
  rescue Rack::Test::Error
81
- ""
81
+ ''
82
82
  end
83
83
 
84
84
  def reset_host!
@@ -105,7 +105,7 @@ class Capybara::RackTest::Browser
105
105
  def html
106
106
  last_response.body
107
107
  rescue Rack::Test::Error
108
- ""
108
+ ''
109
109
  end
110
110
 
111
111
  def title
@@ -122,7 +122,7 @@ protected
122
122
  def request_path
123
123
  last_request.path
124
124
  rescue Rack::Test::Error
125
- "/"
125
+ '/'
126
126
  end
127
127
 
128
128
  private
@@ -15,7 +15,7 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
15
15
  attr_reader :app, :options
16
16
 
17
17
  def initialize(app, **options)
18
- raise ArgumentError, "rack-test requires a rack application, but none was given" unless app
18
+ raise ArgumentError, 'rack-test requires a rack application, but none was given' unless app
19
19
  @session = nil
20
20
  @app = app
21
21
  @options = DEFAULT_OPTIONS.merge(options)
@@ -7,15 +7,15 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
7
7
  # which should probably be provided to Rack::Test in its non-GET request methods.
8
8
  class NilUploadedFile < Rack::Test::UploadedFile
9
9
  def initialize
10
- @empty_file = Tempfile.new("nil_uploaded_file")
10
+ @empty_file = Tempfile.new('nil_uploaded_file')
11
11
  @empty_file.close
12
12
  end
13
13
 
14
- def original_filename; ""; end
15
- def content_type; "application/octet-stream"; end
14
+ def original_filename; ''; end
15
+ def content_type; 'application/octet-stream'; end
16
16
  def path; @empty_file.path; end
17
17
  def size; 0; end
18
- def read; ""; end
18
+ def read; ''; end
19
19
  end
20
20
 
21
21
  def params(button)
@@ -35,7 +35,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
35
35
  when 'textarea' then add_textarea_param(field, params)
36
36
  end
37
37
  end
38
- merge_param!(params, button[:name], button[:value] || "") if button[:name]
38
+ merge_param!(params, button[:name], button[:value] || '') if button[:name]
39
39
 
40
40
  params.to_params_hash
41
41
  end
@@ -47,7 +47,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
47
47
  end
48
48
 
49
49
  def multipart?
50
- self[:enctype] == "multipart/form-data"
50
+ self[:enctype] == 'multipart/form-data'
51
51
  end
52
52
 
53
53
  private
@@ -107,7 +107,7 @@ private
107
107
 
108
108
  def add_select_param(field, params)
109
109
  if field.has_attribute?('multiple')
110
- field.xpath(".//option[@selected]").each do |option|
110
+ field.xpath('.//option[@selected]').each do |option|
111
111
  merge_param!(params, field['name'], (option['value'] || option.text).to_s)
112
112
  end
113
113
  else
@@ -7,16 +7,16 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
7
7
  native.text
8
8
  .gsub(/[\u200b\u200e\u200f]/, '')
9
9
  .gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
10
- .gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
11
- .gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
10
+ .gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
11
+ .gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
12
12
  .tr("\u00a0", ' ')
13
13
  end
14
14
 
15
15
  def visible_text
16
16
  displayed_text.gsub(/\ +/, ' ')
17
17
  .gsub(/[\ \n]*\n[\ \n]*/, "\n")
18
- .gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
19
- .gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
18
+ .gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
19
+ .gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
20
20
  .tr("\u00a0", ' ')
21
21
  end
22
22
 
@@ -25,7 +25,7 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
25
25
  end
26
26
 
27
27
  def style(_styles)
28
- raise NotImplementedError, "The rack_test driver does not process CSS"
28
+ raise NotImplementedError, 'The rack_test driver does not process CSS'
29
29
  end
30
30
 
31
31
  def value
@@ -51,16 +51,16 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
51
51
  def select_option
52
52
  return if disabled?
53
53
  deselect_options unless select_node.multiple?
54
- native["selected"] = 'selected'
54
+ native['selected'] = 'selected'
55
55
  end
56
56
 
57
57
  def unselect_option
58
- raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box." unless select_node.multiple?
58
+ raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select_node.multiple?
59
59
  native.remove_attribute('selected')
60
60
  end
61
61
 
62
62
  def click(keys = [], **offset)
63
- raise ArgumentError, "The RackTest driver does not support click options" unless keys.empty? && offset.empty?
63
+ raise ArgumentError, 'The RackTest driver does not support click options' unless keys.empty? && offset.empty?
64
64
 
65
65
  if link?
66
66
  follow_link
@@ -94,9 +94,9 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
94
94
  return true if string_node.disabled?
95
95
 
96
96
  if %w[option optgroup].include? tag_name
97
- find_xpath("parent::*[self::optgroup or self::select or self::datalist]")[0].disabled?
97
+ find_xpath('parent::*[self::optgroup or self::select or self::datalist]')[0].disabled?
98
98
  else
99
- !find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
99
+ !find_xpath('parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]').empty?
100
100
  end
101
101
  end
102
102
 
@@ -140,7 +140,7 @@ protected
140
140
  private
141
141
 
142
142
  def deselect_options
143
- select_node.find_xpath(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
143
+ select_node.find_xpath('.//option[@selected]').each { |node| node.native.remove_attribute('selected') }
144
144
  end
145
145
 
146
146
  def string_node
@@ -166,7 +166,7 @@ private
166
166
 
167
167
  def set_radio(_value) # rubocop:disable Naming/AccessorMethodName
168
168
  other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name) == self[:name]] }.to_s
169
- driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") }
169
+ driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute('checked') }
170
170
  native['checked'] = 'checked'
171
171
  end
172
172
 
@@ -202,7 +202,7 @@ private
202
202
  end
203
203
 
204
204
  def follow_link
205
- method = self["data-method"] if driver.options[:respect_data_method]
205
+ method = self['data-method'] if driver.options[:respect_data_method]
206
206
  method ||= :get
207
207
  driver.follow(method, self[:href].to_s)
208
208
  end
@@ -211,7 +211,7 @@ private
211
211
  labelled_control = if native[:for]
212
212
  find_xpath("//input[@id='#{native[:for]}']")
213
213
  else
214
- find_xpath(".//input")
214
+ find_xpath('.//input')
215
215
  end.first
216
216
 
217
217
  labelled_control.set(!labelled_control.checked?) if checkbox_or_radio?(labelled_control)
@@ -222,7 +222,7 @@ private
222
222
  end
223
223
 
224
224
  def submits?
225
- (tag_name == 'input' && %w[submit image].include?(type)) || (tag_name == 'button' && [nil, "submit"].include?(type))
225
+ (tag_name == 'input' && %w[submit image].include?(type)) || (tag_name == 'button' && [nil, 'submit'].include?(type))
226
226
  end
227
227
 
228
228
  def checkable?
@@ -252,6 +252,6 @@ protected
252
252
  end
253
253
 
254
254
  def textarea?
255
- tag_name == "textarea"
255
+ tag_name == 'textarea'
256
256
  end
257
257
  end
@@ -3,7 +3,7 @@
3
3
  require 'capybara/dsl'
4
4
 
5
5
  Capybara.app = Rack::Builder.new do
6
- map "/" do
6
+ map '/' do
7
7
  run Rails.application
8
8
  end
9
9
  end.to_app
@@ -123,13 +123,13 @@ module Capybara
123
123
  def failure_message
124
124
  message = @query.failure_message
125
125
  if count.zero?
126
- message << " but there were no matches"
126
+ message << ' but there were no matches'
127
127
  else
128
- message << ", found #{count} #{Capybara::Helpers.declension('match', 'matches', count)}: " << full_results.map(&:text).map(&:inspect).join(", ")
128
+ message << ", found #{count} #{Capybara::Helpers.declension('match', 'matches', count)}: " << full_results.map(&:text).map(&:inspect).join(', ')
129
129
  end
130
130
  unless rest.empty?
131
- elements = rest.map { |el| el.text rescue "<<ERROR>>" }.map(&:inspect).join(", ") # rubocop:disable Style/RescueModifier
132
- message << ". Also found " << elements << ", which matched the selector but not all filters."
131
+ elements = rest.map { |el| el.text rescue '<<ERROR>>' }.map(&:inspect).join(', ') # rubocop:disable Style/RescueModifier
132
+ message << '. Also found ' << elements << ', which matched the selector but not all filters.'
133
133
  end
134
134
  message
135
135
  end
@@ -138,6 +138,10 @@ module Capybara
138
138
  failure_message.sub(/(to find)/, 'not \1')
139
139
  end
140
140
 
141
+ def unfiltered_size
142
+ @elements.length
143
+ end
144
+
141
145
  private
142
146
 
143
147
  def full_results
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.shared_context "Capybara Features", capybara_feature: true do
3
+ RSpec.shared_context 'Capybara Features', capybara_feature: true do
4
4
  instance_eval do
5
5
  alias background before
6
6
  alias given let
@@ -10,14 +10,14 @@ end
10
10
 
11
11
  # ensure shared_context is included if default shared_context_metadata_behavior is changed
12
12
  RSpec.configure do |config|
13
- config.include_context "Capybara Features", capybara_feature: true if config.respond_to?(:include_context)
13
+ config.include_context 'Capybara Features', capybara_feature: true if config.respond_to?(:include_context)
14
14
  end
15
15
 
16
16
  RSpec.configure do |config|
17
17
  config.alias_example_group_to :feature, capybara_feature: true, type: :feature
18
- config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: "Temporarily disabled with xfeature"
18
+ config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: 'Temporarily disabled with xfeature'
19
19
  config.alias_example_group_to :ffeature, capybara_feature: true, type: :feature, focus: true
20
20
  config.alias_example_to :scenario
21
- config.alias_example_to :xscenario, skip: "Temporarily disabled with xscenario"
21
+ config.alias_example_to :xscenario, skip: 'Temporarily disabled with xscenario'
22
22
  config.alias_example_to :fscenario, focus: true
23
23
  end
@@ -89,11 +89,11 @@ module Capybara
89
89
  end
90
90
 
91
91
  def does_not_match?(_actual)
92
- raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
92
+ raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'
93
93
  end
94
94
 
95
95
  def description
96
- "have all selectors"
96
+ 'have all selectors'
97
97
  end
98
98
  end
99
99
 
@@ -108,11 +108,11 @@ module Capybara
108
108
  end
109
109
 
110
110
  def does_not_match?(_actual)
111
- raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
111
+ raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'
112
112
  end
113
113
 
114
114
  def description
115
- "have no selectors"
115
+ 'have no selectors'
116
116
  end
117
117
  end
118
118
 
@@ -235,11 +235,11 @@ module Capybara
235
235
  end
236
236
 
237
237
  def does_not_match?(_actual)
238
- raise ArgumentError, "The have_style matcher does not support use with not_to/should_not"
238
+ raise ArgumentError, 'The have_style matcher does not support use with not_to/should_not'
239
239
  end
240
240
 
241
241
  def description
242
- "have style"
242
+ 'have style'
243
243
  end
244
244
  end
245
245