capybara 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +15 -0
  3. data/License.txt +1 -1
  4. data/README.md +1 -1
  5. data/lib/capybara.rb +1 -2
  6. data/lib/capybara/helpers.rb +3 -2
  7. data/lib/capybara/minitest.rb +1 -1
  8. data/lib/capybara/minitest/spec.rb +1 -0
  9. data/lib/capybara/node/finders.rb +20 -15
  10. data/lib/capybara/node/matchers.rb +43 -10
  11. data/lib/capybara/queries/current_path_query.rb +2 -2
  12. data/lib/capybara/queries/selector_query.rb +9 -2
  13. data/lib/capybara/rack_test/browser.rb +14 -13
  14. data/lib/capybara/rack_test/form.rb +32 -27
  15. data/lib/capybara/result.rb +8 -11
  16. data/lib/capybara/rspec/compound.rb +16 -26
  17. data/lib/capybara/rspec/matcher_proxies.rb +28 -11
  18. data/lib/capybara/rspec/matchers.rb +67 -45
  19. data/lib/capybara/selector.rb +22 -25
  20. data/lib/capybara/selector/builders/css_builder.rb +3 -4
  21. data/lib/capybara/selector/builders/xpath_builder.rb +4 -6
  22. data/lib/capybara/selector/regexp_disassembler.rb +43 -44
  23. data/lib/capybara/selector/selector.rb +16 -11
  24. data/lib/capybara/selenium/driver.rb +28 -21
  25. data/lib/capybara/selenium/nodes/marionette_node.rb +6 -12
  26. data/lib/capybara/server.rb +1 -3
  27. data/lib/capybara/server/animation_disabler.rb +2 -2
  28. data/lib/capybara/session.rb +1 -1
  29. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +29 -0
  30. data/lib/capybara/spec/session/click_button_spec.rb +6 -0
  31. data/lib/capybara/spec/session/click_link_spec.rb +1 -1
  32. data/lib/capybara/spec/session/has_all_selectors_spec.rb +1 -1
  33. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  34. data/lib/capybara/spec/session/html_spec.rb +7 -0
  35. data/lib/capybara/spec/session/node_spec.rb +5 -1
  36. data/lib/capybara/spec/session/refresh_spec.rb +4 -0
  37. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +4 -0
  38. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +4 -0
  39. data/lib/capybara/spec/session/window/window_spec.rb +4 -0
  40. data/lib/capybara/spec/session/window/windows_spec.rb +4 -0
  41. data/lib/capybara/spec/views/form.erb +2 -2
  42. data/lib/capybara/version.rb +1 -1
  43. data/spec/minitest_spec.rb +5 -1
  44. data/spec/minitest_spec_spec.rb +5 -1
  45. data/spec/regexp_dissassembler_spec.rb +5 -3
  46. data/spec/rspec_spec.rb +20 -0
  47. data/spec/selector_spec.rb +89 -3
  48. data/spec/selenium_spec_chrome.rb +3 -7
  49. data/spec/selenium_spec_marionette.rb +1 -4
  50. metadata +20 -6
  51. data/lib/capybara/xpath_patches.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42a9311d8f3e7670a90f5851cc9927db169022d550e1c9b2a086900145b7ad18
4
- data.tar.gz: 8159deadf9826514634c55f9744d2b8f18a910434d71f66870eb299f6c5980ff
3
+ metadata.gz: 58e17a63edc194f43995b9c63196fe91311450999a03da4ee7c2f1aa1e1e34e4
4
+ data.tar.gz: f0a20f11e8a454f62a9abd62dc4d1f18f8419460c43a0e37f250d8c603cffc60
5
5
  SHA512:
6
- metadata.gz: 8d8256a0c4bc0ca9586d65aec40d4814c060226a7902f5122271d4c9e22b63eec1568c81315d327e02873d732062beef6a0c01d0a50df9d49e14fcd0189084c0
7
- data.tar.gz: a86ce539c90c9fbaea0ac8165bbf6f1b66ee8fa4589c129c366d88730cb1881616a3260c3a710b546c0e833aa708de8791326cbaa9c5ffe5f8875ce249c779cd
6
+ metadata.gz: ee9b34f496afec3a99be65c5fcdcfebef38640eccb146a4e43ec811a55c99edf8393695e9a9d228db07d738d753feaa7f8c8090bc7cf37189ff3b192e5b15482
7
+ data.tar.gz: 002ae33fdef7b207d2cba11b8ce125c1d4ef972b10226d9f766dc41605791b8167c11c69ae1295ff229049bbd668a4b49021747eefee4861b152489ddbbe4f5d
data/History.md CHANGED
@@ -1,3 +1,18 @@
1
+ # Version 3.10.0
2
+ Release date: 2018-10-23
3
+
4
+ ### Added
5
+
6
+ * :class filter can now check for class names starting with !
7
+ * Selector `xpath`/`css` expression definitions will get filter names from block parameters if not explicitly provided
8
+ * `any_of_selectors` assertions and matchers to complement `all_of_selectors` and `none_of_selectors`
9
+
10
+ ### Fixed
11
+
12
+ * Selector `css` expression definiton declared filters now work again
13
+ * Cleaned up warnings [Yuji Yaginuma]
14
+ * Workaround installation of rspec matcher proxies under jruby by reverting to the old solution not using prepend, so jruby bugs are not hit - Issue #2115
15
+
1
16
  # Version 3.9.0
2
17
  Release date: 2018-10-03
3
18
 
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2009-2016 Jonas Nicklas
3
+ Copyright (c) 2009-2018 Thomas Walpole, Jonas Nicklas
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=capybara&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
8
8
 
9
9
  **Note** You are viewing the README for the development version of Capybara. If you are using the current release version
10
- you can find the README at https://github.com/teamcapybara/capybara/blob/3.8_stable/README.md
10
+ you can find the README at https://github.com/teamcapybara/capybara/blob/3.9_stable/README.md
11
11
 
12
12
 
13
13
  Capybara helps you test web applications by simulating how a real user would
@@ -393,7 +393,7 @@ module Capybara
393
393
  if threadsafe
394
394
  Thread.current['capybara_specified_session']
395
395
  else
396
- @specified_session
396
+ @specified_session ||= nil
397
397
  end
398
398
  end
399
399
 
@@ -414,7 +414,6 @@ module Capybara
414
414
  module RackTest; end
415
415
  module Selenium; end
416
416
 
417
- require 'capybara/xpath_patches'
418
417
  require 'capybara/helpers'
419
418
  require 'capybara/session'
420
419
  require 'capybara/window'
@@ -49,8 +49,9 @@ module Capybara
49
49
  #
50
50
  def inject_asset_host(html, host: Capybara.asset_host)
51
51
  if host && Nokogiri::HTML(html).css('base').empty?
52
- match = html.match(/<head[^<]*?>/)
53
- return html.clone.insert match.end(0), "<base href='#{host}' />" if match
52
+ html.match(/<head[^<]*?>/) do |m|
53
+ return html.clone.insert m.end(0), "<base href='#{host}' />"
54
+ end
54
55
  end
55
56
  html
56
57
  end
@@ -87,7 +87,7 @@ module Capybara
87
87
  # see {Capybara::Node::Matchers#assert_style}
88
88
 
89
89
  %w[assert_selector assert_no_selector
90
- assert_all_of_selectors assert_none_of_selectors
90
+ assert_all_of_selectors assert_none_of_selectors assert_any_of_selectors
91
91
  assert_matches_selector assert_not_matches_selector
92
92
  assert_style].each do |assertion_name|
93
93
  class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
@@ -16,6 +16,7 @@ module Capybara
16
16
  %W[refute_#{assertion} wont_have_#{assertion}]]
17
17
  end + [%w[assert_all_of_selectors must_have_all_of_selectors],
18
18
  %w[assert_none_of_selectors must_have_none_of_selectors],
19
+ %w[assert_any_of_selectors must_have_any_of_selectors],
19
20
  %w[assert_style must_have_style]] +
20
21
  %w[selector xpath css].flat_map do |assertion|
21
22
  [%W[assert_matches_#{assertion} must_match_#{assertion}],
@@ -15,15 +15,30 @@ module Capybara
15
15
  # and defaults to 2 seconds.
16
16
  # @option options [false, Numeric] wait (Capybara.default_max_wait_time) Maximum time to wait for matching element to appear.
17
17
  #
18
- # +find+ takes the same options as +all+.
19
- #
20
18
  # page.find('#foo').find('.bar')
21
19
  # page.find(:xpath, './/div[contains(., "bar")]')
22
20
  # page.find('li', text: 'Quox').click_link('Delete')
23
21
  #
24
22
  # @param (see Capybara::Node::Finders#all)
25
23
  #
26
- # @option options [Boolean] match The matching strategy to use.
24
+ # @!macro system_filters
25
+ # @option options [String, Regexp] text Only find elements which contain this text or match this regexp
26
+ # @option options [String, Boolean] exact_text (Capybara.exact_text) When String the elements contained text must match exactly, when Boolean controls whether the :text option must match exactly
27
+ # @option options [Boolean] normalize_ws (Capybara.default_normalize_ws) Whether the `text`/`exact_text` options are compared against elment text with whitespace normalized or as returned by the driver
28
+ # @option options [Boolean, Symbol] visible Only find elements with the specified visibility:
29
+ # * true - only finds visible elements.
30
+ # * false - finds invisible _and_ visible elements.
31
+ # * :all - same as false; finds visible and invisible elements.
32
+ # * :hidden - only finds invisible elements.
33
+ # * :visible - same as true; only finds visible elements.
34
+ # @option options [String, Regexp] id Only find elements with an id that matches the value passed
35
+ # @option options [String, Array<String>, Regexp] class Only find elements with matching class/classes.
36
+ # + Absence of a class can be checked by prefixing the class name with !
37
+ # + If you need to check for existence of a class name that starts with ! then prefix with !!
38
+ # + ```class:['a', '!b', '!!!c'] # limit to elements with class 'a' and '!c' but not class 'b'```
39
+ # @option options [Boolean] exact Control whether `is` expressions in the given XPath match exactly or partially
40
+ # @option options [Integer, false] wait (Capybara.default_max_wait_time) The time to wait for matching elements to become available
41
+ # @option options [Symbol] match The matching strategy to use.
27
42
  #
28
43
  # @return [Capybara::Node::Element] The found element
29
44
  # @raise [Capybara::ElementNotFound] If the element can't be found before time expires
@@ -46,7 +61,7 @@ module Capybara
46
61
  #
47
62
  # @param (see Capybara::Node::Finders#find)
48
63
  #
49
- # @!macro waiting_behavior
64
+ # @macro waiting_behavior
50
65
  #
51
66
  # @option options [Boolean] match The matching strategy to use.
52
67
  #
@@ -221,21 +236,11 @@ module Capybara
221
236
  #
222
237
  # @param [Symbol] kind Optional selector type (:css, :xpath, :field, etc.) - Defaults to Capybara.default_selector
223
238
  # @param [String] locator The locator for the specified selector
224
- # @option options [String, Regexp] text Only find elements which contain this text or match this regexp
225
- # @option options [String, Boolean] exact_text (Capybara.exact_text) When String the elements contained text must match exactly, when Boolean controls whether the :text option must match exactly
226
- # @option options [Boolean] normalize_ws (Capybara.default_normalize_ws) Whether the `text`/`exact_text` options are compared against elment text with whitespace normalized or as returned by the driver
227
- # @option options [Boolean, Symbol] visible Only find elements with the specified visibility:
228
- # * true - only finds visible elements.
229
- # * false - finds invisible _and_ visible elements.
230
- # * :all - same as false; finds visible and invisible elements.
231
- # * :hidden - only finds invisible elements.
232
- # * :visible - same as true; only finds visible elements.
239
+ # @macro system_filters
233
240
  # @option options [Integer] count Exact number of matches that are expected to be found
234
241
  # @option options [Integer] maximum Maximum number of matches that are expected to be found
235
242
  # @option options [Integer] minimum Minimum number of matches that are expected to be found
236
243
  # @option options [Range] between Number of matches found must be within the given range
237
- # @option options [Boolean] exact Control whether `is` expressions in the given XPath match exactly or partially
238
- # @option options [Integer, false] wait (Capybara.default_max_wait_time) The time to wait for matching elements to become available
239
244
  # @overload all([kind = Capybara.default_selector], locator = nil, **options)
240
245
  # @overload all([kind = Capybara.default_selector], locator = nil, **options, &filter_block)
241
246
  # @yieldparam element [Capybara::Node::Element] The element being considered for inclusion in the results
@@ -139,13 +139,9 @@ module Capybara
139
139
  #
140
140
  # @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, **options)
141
141
  #
142
- def assert_all_of_selectors(*args, wait: nil, **options, &optional_filter_block)
143
- wait = session_options.default_max_wait_time if wait.nil?
144
- selector = extract_selector(args)
145
- synchronize(wait) do
146
- args.each do |locator|
147
- assert_selector(selector, locator, options, &optional_filter_block)
148
- end
142
+ def assert_all_of_selectors(*args, **options, &optional_filter_block)
143
+ _verify_multiple(*args, options) do |selector, locator, opts|
144
+ assert_selector(selector, locator, opts, &optional_filter_block)
149
145
  end
150
146
  end
151
147
 
@@ -164,13 +160,42 @@ module Capybara
164
160
  #
165
161
  # @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, **options)
166
162
  #
167
- def assert_none_of_selectors(*args, wait: nil, **options, &optional_filter_block)
163
+ def assert_none_of_selectors(*args, **options, &optional_filter_block)
164
+ _verify_multiple(*args, options) do |selector, locator, opts|
165
+ assert_no_selector(selector, locator, opts, &optional_filter_block)
166
+ end
167
+ end
168
+
169
+ # Asserts that any of the provided selectors are present on the given page
170
+ # or descendants of the current node. If options are provided, the assertion
171
+ # will check that each locator is present with those options as well (other than :wait).
172
+ #
173
+ # page.assert_any_of_selectors(:custom, 'Tom', 'Joe', visible: all)
174
+ # page.assert_any_of_selectors(:css, '#my_div', 'a.not_clicked')
175
+ #
176
+ # It accepts all options that {Capybara::Node::Finders#all} accepts,
177
+ # such as :text and :visible.
178
+ #
179
+ # The :wait option applies to all of the selectors as a group, so any of the locators must be present
180
+ # within :wait (Defaults to Capybara.default_max_wait_time) seconds.
181
+ #
182
+ # @overload assert_any_of_selectors([kind = Capybara.default_selector], *locators, **options)
183
+ #
184
+ def assert_any_of_selectors(*args, wait: nil, **options, &optional_filter_block)
168
185
  wait = session_options.default_max_wait_time if wait.nil?
169
186
  selector = extract_selector(args)
170
187
  synchronize(wait) do
171
- args.each do |locator|
172
- assert_no_selector(selector, locator, options, &optional_filter_block)
188
+ res = args.map do |locator|
189
+ begin
190
+ assert_selector(selector, locator, options, &optional_filter_block)
191
+ break nil
192
+ rescue Capybara::ExpectationNotMet => e
193
+ e.message
194
+ end
173
195
  end
196
+ raise Capybara::ExpectationNotMet, res.join(' or ') if res
197
+
198
+ true
174
199
  end
175
200
  end
176
201
 
@@ -700,6 +725,14 @@ module Capybara
700
725
  args.first.is_a?(Symbol) ? args.shift : session_options.default_selector
701
726
  end
702
727
 
728
+ def _verify_multiple(*args, wait: nil, **options)
729
+ wait = session_options.default_max_wait_time if wait.nil?
730
+ selector = extract_selector(args)
731
+ synchronize(wait) do
732
+ args.each { |locator| yield(selector, locator, options) }
733
+ end
734
+ end
735
+
703
736
  def _verify_selector_result(query_args, optional_filter_block)
704
737
  query_args = _set_query_session_options(*query_args)
705
738
  query = Capybara::Queries::SelectorQuery.new(*query_args, &optional_filter_block)
@@ -18,8 +18,8 @@ module Capybara
18
18
 
19
19
  def resolves_for?(session)
20
20
  uri = ::Addressable::URI.parse(session.current_url)
21
- uri.query = nil if uri && options[:ignore_query]
22
- @actual_path = options[:url] ? uri.to_s : uri&.request_uri
21
+ uri&.query = nil if options[:ignore_query]
22
+ @actual_path = options[:url] ? uri&.to_s : uri&.request_uri
23
23
 
24
24
  if @expected_path.is_a? Regexp
25
25
  @actual_path.to_s.match(@expected_path)
@@ -61,8 +61,7 @@ module Capybara
61
61
  return true if (@resolved_node&.== node) && options[:allow_self]
62
62
 
63
63
  @applied_filters ||= :system
64
- return false unless matches_id_filter?(node) && matches_class_filter?(node)
65
- return false unless matches_text_filter?(node) && matches_exact_text_filter?(node) && matches_visible_filter?(node)
64
+ return false unless matches_system_filters?(node)
66
65
 
67
66
  @applied_filters = :node
68
67
  matches_node_filters?(node) && matches_filter_block?(node)
@@ -292,6 +291,14 @@ module Capybara
292
291
  node.is_a?(::Capybara::Node::Simple) && node.path == '/'
293
292
  end
294
293
 
294
+ def matches_system_filters?(node)
295
+ matches_id_filter?(node) &&
296
+ matches_class_filter?(node) &&
297
+ matches_text_filter?(node) &&
298
+ matches_exact_text_filter?(node) &&
299
+ matches_visible_filter?(node)
300
+ end
301
+
295
302
  def matches_id_filter?(node)
296
303
  return true unless use_default_id_filter? && options[:id].is_a?(Regexp)
297
304
 
@@ -57,25 +57,26 @@ class Capybara::RackTest::Browser
57
57
  end
58
58
 
59
59
  def process(method, path, attributes = {}, env = {})
60
- new_uri = URI.parse(path)
61
- method.downcase! unless method.is_a? Symbol
62
- if path.empty?
63
- new_uri.path = request_path
64
- else
65
- new_uri.path = request_path if path.start_with?('?')
66
- new_uri.path = '/' if new_uri.path.empty?
67
- new_uri.path = request_path.sub(%r{/[^/]*$}, '/') + new_uri.path unless new_uri.path.start_with?('/')
68
- end
69
- new_uri.scheme ||= @current_scheme
70
- new_uri.host ||= @current_host
71
- new_uri.port ||= @current_port unless new_uri.default_port == @current_port
72
-
60
+ method = method.downcase
61
+ new_uri = build_uri(path)
73
62
  @current_scheme, @current_host, @current_port = new_uri.select(:scheme, :host, :port)
74
63
 
75
64
  reset_cache!
76
65
  send(method, new_uri.to_s, attributes, env.merge(options[:headers] || {}))
77
66
  end
78
67
 
68
+ def build_uri(path)
69
+ URI.parse(path).tap do |uri|
70
+ uri.path = request_path if path.empty? || path.start_with?('?')
71
+ uri.path = '/' if uri.path.empty?
72
+ uri.path = request_path.sub(%r{/[^/]*$}, '/') + uri.path unless uri.path.start_with?('/')
73
+
74
+ uri.scheme ||= @current_scheme
75
+ uri.host ||= @current_host
76
+ uri.port ||= @current_port unless uri.default_port == @current_port
77
+ end
78
+ end
79
+
79
80
  def current_url
80
81
  last_request.url
81
82
  rescue Rack::Test::Error
@@ -19,25 +19,22 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
19
19
  end
20
20
 
21
21
  def params(button)
22
- params = make_params
23
-
24
- form_element_types = %i[input select textarea]
22
+ form_element_types = %i[input select textarea button]
25
23
  form_elements_xpath = XPath.generate do |xp|
26
24
  xpath = xp.descendant(*form_element_types).where(!xp.attr(:form))
27
25
  xpath += xp.anywhere(*form_element_types).where(xp.attr(:form) == native[:id]) if native[:id]
28
26
  xpath.where(!xp.attr(:disabled))
29
27
  end.to_s
30
28
 
31
- native.xpath(form_elements_xpath).map do |field|
29
+ form_elements = native.xpath(form_elements_xpath).reject { |el| submitter?(el) && (el != button.native) }
30
+
31
+ form_elements.each_with_object(make_params) do |field, params|
32
32
  case field.name
33
- when 'input' then add_input_param(field, params)
33
+ when 'input', 'button' then add_input_param(field, params)
34
34
  when 'select' then add_select_param(field, params)
35
35
  when 'textarea' then add_textarea_param(field, params)
36
36
  end
37
- end
38
- merge_param!(params, button[:name], button[:value] || '') if button[:name]
39
-
40
- params.to_params_hash
37
+ end.to_params_hash
41
38
  end
42
39
 
43
40
  def submit(button)
@@ -80,28 +77,32 @@ private
80
77
  end
81
78
 
82
79
  def add_input_param(field, params)
83
- if %w[radio checkbox].include? field['type']
84
- if field['checked']
85
- node = Capybara::RackTest::Node.new(driver, field)
86
- merge_param!(params, field['name'], node.value.to_s)
87
- end
88
- elsif %w[submit image].include? field['type']
89
- # TODO: identify the click button here (in document order, rather
90
- # than leaving until the end of the params)
91
- elsif field['type'] == 'file'
80
+ name, value = field['name'].to_s, field['value'].to_s
81
+ return if name.empty?
82
+
83
+ value = case field['type']
84
+ when 'radio', 'checkbox'
85
+ return unless field['checked']
86
+
87
+ Capybara::RackTest::Node.new(driver, field).value.to_s
88
+ when 'file'
92
89
  if multipart?
93
- file = if (value = field['value']).to_s.empty?
94
- NilUploadedFile.new
95
- else
96
- mime_info = MiniMime.lookup_by_filename(value)
97
- Rack::Test::UploadedFile.new(value, mime_info&.content_type&.to_s)
98
- end
99
- merge_param!(params, field['name'], file)
90
+ file_to_upload(value)
100
91
  else
101
- merge_param!(params, field['name'], File.basename(field['value'].to_s))
92
+ File.basename(value)
102
93
  end
103
94
  else
104
- merge_param!(params, field['name'], field['value'].to_s)
95
+ value
96
+ end
97
+ merge_param!(params, name, value)
98
+ end
99
+
100
+ def file_to_upload(filename)
101
+ if filename.empty?
102
+ NilUploadedFile.new
103
+ else
104
+ mime_info = MiniMime.lookup_by_filename(filename)
105
+ Rack::Test::UploadedFile.new(filename, mime_info&.content_type&.to_s)
105
106
  end
106
107
  end
107
108
 
@@ -119,4 +120,8 @@ private
119
120
  def add_textarea_param(field, params)
120
121
  merge_param!(params, field['name'], field['_capybara_raw_value'].to_s.gsub(/\n/, "\r\n"))
121
122
  end
123
+
124
+ def submitter?(el)
125
+ (%w[submit image].include? el['type']) || (el.name == 'button')
126
+ end
122
127
  end
@@ -32,7 +32,7 @@ module Capybara
32
32
 
33
33
  def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample
34
34
 
35
- alias :index :find_index
35
+ alias index find_index
36
36
 
37
37
  def each(&block)
38
38
  return enum_for(:each) unless block_given?
@@ -73,28 +73,25 @@ module Capybara
73
73
  end
74
74
 
75
75
  def compare_count
76
+ count, min, max, between = @query.options.values_at(:count, :minimum, :maximum, :between)
77
+
76
78
  # Only check filters for as many elements as necessary to determine result
77
- if (count = @query.options[:count])
78
- count = Integer(count)
79
+ if count && (count = Integer(count))
79
80
  return load_up_to(count + 1) <=> count
80
81
  end
81
82
 
82
- if (min = @query.options[:minimum])
83
- min = Integer(min)
83
+ if min && (min = Integer(min))
84
84
  return -1 if load_up_to(min) < min
85
85
  end
86
86
 
87
- if (max = @query.options[:maximum])
88
- max = Integer(max)
87
+ if max && (max = Integer(max))
89
88
  return 1 if load_up_to(max + 1) > max
90
89
  end
91
90
 
92
- if (between = @query.options[:between])
91
+ if between
93
92
  min, max = between.minmax
94
93
  size = load_up_to(max + 1)
95
- return 0 if between.include? size
96
-
97
- return size <=> min
94
+ return between.include?(size) ? 0 : size <=> min
98
95
  end
99
96
 
100
97
  0