capybara 3.13.2 → 3.40.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.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/History.md +587 -16
- data/README.md +240 -90
- data/lib/capybara/config.rb +24 -11
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +8 -0
- data/lib/capybara/driver/node.rb +20 -4
- data/lib/capybara/dsl.rb +5 -3
- data/lib/capybara/helpers.rb +25 -4
- data/lib/capybara/minitest/spec.rb +174 -90
- data/lib/capybara/minitest.rb +256 -142
- data/lib/capybara/node/actions.rb +123 -77
- data/lib/capybara/node/base.rb +20 -12
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +223 -117
- data/lib/capybara/node/finders.rb +81 -71
- data/lib/capybara/node/matchers.rb +271 -134
- data/lib/capybara/node/simple.rb +18 -5
- data/lib/capybara/node/whitespace_normalizer.rb +81 -0
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +8 -9
- data/lib/capybara/queries/base_query.rb +3 -2
- data/lib/capybara/queries/current_path_query.rb +15 -5
- data/lib/capybara/queries/selector_query.rb +364 -54
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +2 -2
- data/lib/capybara/queries/text_query.rb +13 -1
- data/lib/capybara/queries/title_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +76 -11
- data/lib/capybara/rack_test/driver.rb +10 -5
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +31 -9
- data/lib/capybara/rack_test/node.rb +74 -23
- data/lib/capybara/registration_container.rb +41 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +66 -0
- data/lib/capybara/result.rb +44 -20
- data/lib/capybara/rspec/matcher_proxies.rb +13 -11
- data/lib/capybara/rspec/matchers/base.rb +31 -16
- data/lib/capybara/rspec/matchers/compound.rb +1 -1
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +21 -21
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +4 -4
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +7 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +111 -68
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/selector/builders/css_builder.rb +11 -7
- data/lib/capybara/selector/builders/xpath_builder.rb +5 -3
- data/lib/capybara/selector/css.rb +11 -9
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +55 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +280 -0
- data/lib/capybara/selector/filter_set.rb +19 -18
- data/lib/capybara/selector/filters/base.rb +11 -2
- data/lib/capybara/selector/filters/locator_filter.rb +13 -3
- data/lib/capybara/selector/regexp_disassembler.rb +11 -7
- data/lib/capybara/selector/selector.rb +50 -440
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +473 -482
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +174 -62
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +74 -18
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +37 -3
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +68 -45
- data/lib/capybara/selenium/extensions/html5_drag.rb +192 -22
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/node.rb +268 -72
- data/lib/capybara/selenium/nodes/chrome_node.rb +105 -9
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +51 -61
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +43 -21
- data/lib/capybara/server/checker.rb +6 -2
- data/lib/capybara/server/middleware.rb +25 -13
- data/lib/capybara/server.rb +20 -4
- data/lib/capybara/session/config.rb +15 -11
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/session.rb +162 -131
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +105 -6
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +89 -15
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
- data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
- data/lib/capybara/spec/session/attach_file_spec.rb +64 -31
- data/lib/capybara/spec/session/check_spec.rb +26 -4
- data/lib/capybara/spec/session/choose_spec.rb +14 -2
- data/lib/capybara/spec/session/click_button_spec.rb +109 -61
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/click_link_spec.rb +23 -1
- data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
- data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +46 -5
- data/lib/capybara/spec/session/find_link_spec.rb +10 -0
- data/lib/capybara/spec/session/find_spec.rb +80 -7
- data/lib/capybara/spec/session/first_spec.rb +2 -2
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +14 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
- data/lib/capybara/spec/session/has_button_spec.rb +81 -0
- data/lib/capybara/spec/session/has_css_spec.rb +45 -8
- data/lib/capybara/spec/session/has_current_path_spec.rb +22 -7
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +59 -1
- data/lib/capybara/spec/session/has_link_spec.rb +40 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
- data/lib/capybara/spec/session/has_select_spec.rb +42 -8
- data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +177 -0
- data/lib/capybara/spec/session/has_text_spec.rb +31 -3
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +6 -4
- data/lib/capybara/spec/session/node_spec.rb +697 -23
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +21 -7
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/scroll_spec.rb +9 -7
- data/lib/capybara/spec/session/select_spec.rb +5 -10
- data/lib/capybara/spec/session/selectors_spec.rb +24 -3
- data/lib/capybara/spec/session/uncheck_spec.rb +3 -3
- data/lib/capybara/spec/session/unselect_spec.rb +1 -1
- data/lib/capybara/spec/session/visit_spec.rb +20 -0
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +54 -57
- data/lib/capybara/spec/session/window/windows_spec.rb +2 -2
- data/lib/capybara/spec/session/within_spec.rb +36 -0
- data/lib/capybara/spec/spec_helper.rb +30 -19
- data/lib/capybara/spec/test_app.rb +122 -34
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +86 -8
- data/lib/capybara/spec/views/frame_child.erb +3 -2
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +10 -10
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +2 -1
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +67 -0
- data/lib/capybara/spec/views/with_animation.erb +39 -4
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +34 -6
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +7 -4
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +1 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +14 -18
- data/lib/capybara.rb +91 -126
- data/spec/basic_node_spec.rb +30 -16
- data/spec/capybara_spec.rb +40 -28
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +3 -1
- data/spec/css_splitter_spec.rb +1 -1
- data/spec/dsl_spec.rb +33 -22
- data/spec/filter_set_spec.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_failure.rb +3 -3
- data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
- data/spec/minitest_spec.rb +24 -2
- data/spec/minitest_spec_spec.rb +60 -45
- data/spec/per_session_config_spec.rb +1 -1
- data/spec/rack_test_spec.rb +131 -98
- data/spec/regexp_dissassembler_spec.rb +53 -39
- data/spec/result_spec.rb +68 -66
- data/spec/rspec/features_spec.rb +9 -4
- data/spec/rspec/scenarios_spec.rb +6 -2
- data/spec/rspec/shared_spec_matchers.rb +137 -98
- data/spec/rspec_matchers_spec.rb +25 -0
- data/spec/rspec_spec.rb +23 -21
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +77 -21
- data/spec/selenium_spec_chrome.rb +141 -39
- data/spec/selenium_spec_chrome_remote.rb +32 -17
- data/spec/selenium_spec_edge.rb +36 -8
- data/spec/selenium_spec_firefox.rb +110 -68
- data/spec/selenium_spec_firefox_remote.rb +22 -15
- data/spec/selenium_spec_ie.rb +29 -22
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +153 -81
- data/spec/session_spec.rb +11 -4
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +179 -74
- data/spec/spec_helper.rb +80 -5
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +3 -1
- metadata +218 -30
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Capybara.register_server :default do |app, port, _host|
|
4
|
+
Capybara.run_default_server(app, port)
|
5
|
+
end
|
6
|
+
|
7
|
+
Capybara.register_server :webrick do |app, port, host, **options|
|
8
|
+
base_class = begin
|
9
|
+
require 'rack/handler/webrick'
|
10
|
+
Rack
|
11
|
+
rescue LoadError
|
12
|
+
# Rack 3 separated out the webrick handle - no way test currently in Capybaras automated
|
13
|
+
# tests due to Sinatra not yet supporting Rack 3 - experimental
|
14
|
+
require 'rackup/handler/webrick'
|
15
|
+
Rackup
|
16
|
+
end
|
17
|
+
options = { Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log.new(nil, 0) }.merge(options)
|
18
|
+
base_class::Handler::WEBrick.run(app, **options)
|
19
|
+
end
|
20
|
+
|
21
|
+
Capybara.register_server :puma do |app, port, host, **options| # rubocop:disable Metrics/BlockLength
|
22
|
+
begin
|
23
|
+
require 'rackup'
|
24
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
25
|
+
end
|
26
|
+
begin
|
27
|
+
require 'rack/handler/puma'
|
28
|
+
rescue LoadError
|
29
|
+
raise LoadError, 'Capybara is unable to load `puma` for its server, please add `puma` to your project or specify a different server via something like `Capybara.server = :webrick`.'
|
30
|
+
end
|
31
|
+
puma_rack_handler = defined?(Rackup::Handler::Puma) ? Rackup::Handler::Puma : Rack::Handler::Puma
|
32
|
+
|
33
|
+
unless puma_rack_handler.respond_to?(:config)
|
34
|
+
raise LoadError, 'Capybara requires `puma` version 3.8.0 or higher, please upgrade `puma` or register and specify your own server block'
|
35
|
+
end
|
36
|
+
|
37
|
+
# If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.
|
38
|
+
# Therefore construct and run the Server instance ourselves.
|
39
|
+
# puma_rack_handler.run(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
40
|
+
default_options = { Host: host, Port: port, Threads: '0:4', workers: 0, daemon: false }
|
41
|
+
options = default_options.merge(options)
|
42
|
+
|
43
|
+
conf = puma_rack_handler.config(app, options)
|
44
|
+
conf.clamp
|
45
|
+
|
46
|
+
puma_ver = Gem::Version.new(Puma::Const::PUMA_VERSION)
|
47
|
+
require_relative 'patches/puma_ssl' if Gem::Requirement.new('>=4.0.0', '< 4.1.0').satisfied_by?(puma_ver)
|
48
|
+
|
49
|
+
logger = (defined?(Puma::LogWriter) ? Puma::LogWriter : Puma::Events).then do |cls|
|
50
|
+
conf.options[:Silent] ? cls.strings : cls.stdio
|
51
|
+
end
|
52
|
+
conf.options[:log_writer] = logger
|
53
|
+
|
54
|
+
logger.log 'Capybara starting Puma...'
|
55
|
+
logger.log "* Version #{Puma::Const::PUMA_VERSION}, codename: #{Puma::Const::CODE_NAME}"
|
56
|
+
logger.log "* Min threads: #{conf.options[:min_threads]}, max threads: #{conf.options[:max_threads]}"
|
57
|
+
|
58
|
+
Puma::Server.new(
|
59
|
+
conf.app,
|
60
|
+
defined?(Puma::LogWriter) ? nil : logger,
|
61
|
+
conf.options
|
62
|
+
).tap do |s|
|
63
|
+
s.binder.parse conf.options[:binds], (s.log_writer rescue s.events) # rubocop:disable Style/RescueModifier
|
64
|
+
s.min_threads, s.max_threads = conf.options[:min_threads], conf.options[:max_threads] if s.respond_to? :min_threads=
|
65
|
+
end.run.join
|
66
|
+
end
|
data/lib/capybara/result.rb
CHANGED
@@ -31,19 +31,20 @@ module Capybara
|
|
31
31
|
@filter_errors = []
|
32
32
|
@results_enum = lazy_select_elements { |node| query.matches_filters?(node, @filter_errors) }
|
33
33
|
@query = query
|
34
|
+
@allow_reload = false
|
34
35
|
end
|
35
36
|
|
36
|
-
def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample
|
37
|
+
def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample, :to_ary
|
37
38
|
|
38
39
|
alias index find_index
|
39
40
|
|
40
41
|
def each(&block)
|
41
|
-
return enum_for(:each) unless
|
42
|
+
return enum_for(:each) unless block
|
42
43
|
|
43
44
|
@result_cache.each(&block)
|
44
45
|
loop do
|
45
46
|
next_result = @results_enum.next
|
46
|
-
|
47
|
+
add_to_cache(next_result)
|
47
48
|
yield next_result
|
48
49
|
end
|
49
50
|
self
|
@@ -53,13 +54,18 @@ module Capybara
|
|
53
54
|
idx, length = args
|
54
55
|
max_idx = case idx
|
55
56
|
when Integer
|
56
|
-
if
|
57
|
-
length.nil? ? idx : idx + length - 1
|
58
|
-
else
|
57
|
+
if idx.negative?
|
59
58
|
nil
|
59
|
+
else
|
60
|
+
length.nil? ? idx : idx + length - 1
|
60
61
|
end
|
61
62
|
when Range
|
62
|
-
|
63
|
+
# idx.max is broken with beginless ranges
|
64
|
+
# idx.end && idx.max # endless range will have end == nil
|
65
|
+
max = idx.end
|
66
|
+
max = nil if max&.negative?
|
67
|
+
max -= 1 if max && idx.exclude_end?
|
68
|
+
max
|
63
69
|
end
|
64
70
|
|
65
71
|
if max_idx.nil?
|
@@ -76,6 +82,8 @@ module Capybara
|
|
76
82
|
end
|
77
83
|
|
78
84
|
def compare_count
|
85
|
+
return 0 unless @query
|
86
|
+
|
79
87
|
count, min, max, between = @query.options.values_at(:count, :minimum, :maximum, :between)
|
80
88
|
|
81
89
|
# Only check filters for as many elements as necessary to determine result
|
@@ -83,16 +91,14 @@ module Capybara
|
|
83
91
|
return load_up_to(count + 1) <=> count
|
84
92
|
end
|
85
93
|
|
86
|
-
if min && (min = Integer(min))
|
87
|
-
return -1 if load_up_to(min) < min
|
88
|
-
end
|
94
|
+
return -1 if min && (min = Integer(min)) && (load_up_to(min) < min)
|
89
95
|
|
90
|
-
if max && (max = Integer(max))
|
91
|
-
return 1 if load_up_to(max + 1) > max
|
92
|
-
end
|
96
|
+
return 1 if max && (max = Integer(max)) && (load_up_to(max + 1) > max)
|
93
97
|
|
94
98
|
if between
|
95
|
-
min, max = between.
|
99
|
+
min, max = (between.begin && between.min) || 1, between.end
|
100
|
+
max -= 1 if max && between.exclude_end?
|
101
|
+
|
96
102
|
size = load_up_to(max ? max + 1 : min)
|
97
103
|
return size <=> min unless between.include?(size)
|
98
104
|
end
|
@@ -110,7 +116,7 @@ module Capybara
|
|
110
116
|
message << ' but there were no matches'
|
111
117
|
else
|
112
118
|
message << ", found #{count} #{Capybara::Helpers.declension('match', 'matches', count)}: " \
|
113
|
-
<< full_results.map
|
119
|
+
<< full_results.map { |r| r.text.inspect }.join(', ')
|
114
120
|
end
|
115
121
|
unless rest.empty?
|
116
122
|
elements = rest.map { |el| el.text rescue '<<ERROR>>' }.map(&:inspect).join(', ') # rubocop:disable Style/RescueModifier
|
@@ -128,13 +134,26 @@ module Capybara
|
|
128
134
|
@elements.length
|
129
135
|
end
|
130
136
|
|
137
|
+
##
|
138
|
+
# @api private
|
139
|
+
#
|
140
|
+
def allow_reload!
|
141
|
+
@allow_reload = true
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
131
145
|
private
|
132
146
|
|
147
|
+
def add_to_cache(elem)
|
148
|
+
elem.allow_reload!(@result_cache.size) if @allow_reload
|
149
|
+
@result_cache << elem
|
150
|
+
end
|
151
|
+
|
133
152
|
def load_up_to(num)
|
134
153
|
loop do
|
135
154
|
break if @result_cache.size >= num
|
136
155
|
|
137
|
-
@
|
156
|
+
add_to_cache(@results_enum.next)
|
138
157
|
end
|
139
158
|
@result_cache.size
|
140
159
|
end
|
@@ -148,13 +167,18 @@ module Capybara
|
|
148
167
|
@rest ||= @elements - full_results
|
149
168
|
end
|
150
169
|
|
151
|
-
|
152
|
-
# JRuby has an issue with lazy enumerators which
|
170
|
+
if RUBY_PLATFORM == 'java'
|
171
|
+
# JRuby < 9.2.8.0 has an issue with lazy enumerators which
|
153
172
|
# causes a concurrency issue with network requests here
|
154
173
|
# https://github.com/jruby/jruby/issues/4212
|
155
|
-
|
174
|
+
# while JRuby >= 9.2.8.0 leaks threads when using lazy enumerators
|
175
|
+
# https://github.com/teamcapybara/capybara/issues/2349
|
176
|
+
# so disable the use and JRuby users will need to pay a performance penalty
|
177
|
+
def lazy_select_elements(&block)
|
156
178
|
@elements.select(&block).to_enum # non-lazy evaluation
|
157
|
-
|
179
|
+
end
|
180
|
+
else
|
181
|
+
def lazy_select_elements(&block)
|
158
182
|
@elements.lazy.select(&block)
|
159
183
|
end
|
160
184
|
end
|
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
module Capybara
|
4
4
|
module RSpecMatcherProxies
|
5
|
-
def all(*args, &block)
|
5
|
+
def all(*args, **kwargs, &block)
|
6
6
|
if defined?(::RSpec::Matchers::BuiltIn::All) && args.first.respond_to?(:matches?)
|
7
7
|
::RSpec::Matchers::BuiltIn::All.new(*args)
|
8
8
|
else
|
9
|
-
find_all(*args, &block)
|
9
|
+
find_all(*args, **kwargs, &block)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
def within(*args)
|
14
|
-
if
|
15
|
-
within_element(*args, &
|
13
|
+
def within(*args, **kwargs, &block)
|
14
|
+
if block
|
15
|
+
within_element(*args, **kwargs, &block)
|
16
16
|
else
|
17
17
|
be_within(*args)
|
18
18
|
end
|
@@ -21,8 +21,9 @@ module Capybara
|
|
21
21
|
end
|
22
22
|
|
23
23
|
if RUBY_ENGINE == 'jruby'
|
24
|
+
# :nocov:
|
24
25
|
module Capybara::DSL
|
25
|
-
class <<self
|
26
|
+
class << self
|
26
27
|
remove_method :included
|
27
28
|
|
28
29
|
def included(base)
|
@@ -35,7 +36,7 @@ if RUBY_ENGINE == 'jruby'
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
if defined?(
|
39
|
+
if defined?(RSpec::Matchers)
|
39
40
|
module ::RSpec::Matchers
|
40
41
|
def self.included(base)
|
41
42
|
base.send(:include, ::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)
|
@@ -43,6 +44,7 @@ if RUBY_ENGINE == 'jruby'
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
47
|
+
# :nocov:
|
46
48
|
else
|
47
49
|
module Capybara::DSLRSpecProxyInstaller
|
48
50
|
module ClassMethods
|
@@ -53,7 +55,7 @@ else
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def self.prepended(base)
|
56
|
-
class <<base
|
58
|
+
class << base
|
57
59
|
prepend ClassMethods
|
58
60
|
end
|
59
61
|
end
|
@@ -68,13 +70,13 @@ else
|
|
68
70
|
end
|
69
71
|
|
70
72
|
def self.prepended(base)
|
71
|
-
class <<base
|
73
|
+
class << base
|
72
74
|
prepend ClassMethods
|
73
75
|
end
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
77
|
-
Capybara::DSL.prepend
|
79
|
+
Capybara::DSL.prepend Capybara::DSLRSpecProxyInstaller
|
78
80
|
|
79
|
-
|
81
|
+
RSpec::Matchers.prepend Capybara::RSpecMatcherProxyInstaller if defined?(RSpec::Matchers)
|
80
82
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'capybara/rspec/matchers/compound'
|
4
|
+
require 'capybara/rspec/matchers/count_sugar'
|
5
|
+
require 'capybara/rspec/matchers/spatial_sugar'
|
4
6
|
|
5
7
|
module Capybara
|
6
8
|
module RSpecMatchers
|
@@ -10,22 +12,28 @@ module Capybara
|
|
10
12
|
|
11
13
|
attr_reader :failure_message, :failure_message_when_negated
|
12
14
|
|
13
|
-
def initialize(*args, &filter_block)
|
15
|
+
def initialize(*args, **kw_args, &filter_block)
|
14
16
|
@args = args.dup
|
17
|
+
@kw_args = kw_args || {}
|
15
18
|
@filter_block = filter_block
|
16
19
|
end
|
17
20
|
|
18
21
|
private
|
19
22
|
|
20
23
|
def session_query_args
|
21
|
-
if @args.last.is_a? Hash
|
22
|
-
|
23
|
-
else
|
24
|
-
|
25
|
-
end
|
24
|
+
# if @args.last.is_a? Hash
|
25
|
+
# @args.last[:session_options] = session_options
|
26
|
+
# else
|
27
|
+
# @args.push(session_options: session_options)
|
28
|
+
# end
|
26
29
|
@args
|
27
30
|
end
|
28
31
|
|
32
|
+
def session_query_options
|
33
|
+
@kw_args[:session_options] = session_options
|
34
|
+
@kw_args
|
35
|
+
end
|
36
|
+
|
29
37
|
def session_options
|
30
38
|
@context_el ||= nil
|
31
39
|
if @context_el.respond_to? :session_options
|
@@ -39,17 +47,19 @@ module Capybara
|
|
39
47
|
end
|
40
48
|
|
41
49
|
class WrappedElementMatcher < Base
|
42
|
-
def matches?(actual)
|
50
|
+
def matches?(actual, &filter_block)
|
51
|
+
@filter_block ||= filter_block
|
43
52
|
element_matches?(wrap(actual))
|
44
|
-
rescue Capybara::ExpectationNotMet =>
|
45
|
-
@failure_message =
|
53
|
+
rescue Capybara::ExpectationNotMet => e
|
54
|
+
@failure_message = e.message
|
46
55
|
false
|
47
56
|
end
|
48
57
|
|
49
|
-
def does_not_match?(actual)
|
58
|
+
def does_not_match?(actual, &filter_block)
|
59
|
+
@filter_block ||= filter_block
|
50
60
|
element_does_not_match?(wrap(actual))
|
51
|
-
rescue Capybara::ExpectationNotMet =>
|
52
|
-
@failure_message_when_negated =
|
61
|
+
rescue Capybara::ExpectationNotMet => e
|
62
|
+
@failure_message_when_negated = e.message
|
53
63
|
false
|
54
64
|
end
|
55
65
|
|
@@ -65,6 +75,11 @@ module Capybara
|
|
65
75
|
end
|
66
76
|
end
|
67
77
|
|
78
|
+
class CountableWrappedElementMatcher < WrappedElementMatcher
|
79
|
+
include ::Capybara::RSpecMatchers::CountSugar
|
80
|
+
include ::Capybara::RSpecMatchers::SpatialSugar
|
81
|
+
end
|
82
|
+
|
68
83
|
class NegatedMatcher
|
69
84
|
include ::Capybara::RSpecMatchers::Matchers::Compound if defined?(::Capybara::RSpecMatchers::Matchers::Compound)
|
70
85
|
|
@@ -73,12 +88,12 @@ module Capybara
|
|
73
88
|
@matcher = matcher
|
74
89
|
end
|
75
90
|
|
76
|
-
def matches?(actual)
|
77
|
-
@matcher.does_not_match?(actual)
|
91
|
+
def matches?(actual, &filter_block)
|
92
|
+
@matcher.does_not_match?(actual, &filter_block)
|
78
93
|
end
|
79
94
|
|
80
|
-
def does_not_match?(actual)
|
81
|
-
@matcher.matches?(actual)
|
95
|
+
def does_not_match?(actual, &filter_block)
|
96
|
+
@matcher.matches?(actual, &filter_block)
|
82
97
|
end
|
83
98
|
|
84
99
|
def description
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module RSpecMatchers
|
5
|
+
module CountSugar
|
6
|
+
def once; exactly(1); end
|
7
|
+
def twice; exactly(2); end
|
8
|
+
def thrice; exactly(3); end
|
9
|
+
|
10
|
+
def exactly(number)
|
11
|
+
options[:count] = number
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def at_most(number)
|
16
|
+
options[:maximum] = number
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def at_least(number)
|
21
|
+
options[:minimum] = number
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def times
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def options
|
32
|
+
# (@args.last.is_a?(Hash) ? @args : @args.push({})).last
|
33
|
+
@kw_args
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'capybara/rspec/matchers/base'
|
4
|
+
|
5
|
+
module Capybara
|
6
|
+
module RSpecMatchers
|
7
|
+
module Matchers
|
8
|
+
class HaveAncestor < CountableWrappedElementMatcher
|
9
|
+
def element_matches?(el)
|
10
|
+
el.assert_ancestor(*@args, **session_query_options, &@filter_block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def element_does_not_match?(el)
|
14
|
+
el.assert_no_ancestor(*@args, **session_query_options, &@filter_block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
"have ancestor #{query.description}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def query
|
22
|
+
# @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, &@filter_block)
|
23
|
+
@query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -7,11 +7,11 @@ module Capybara
|
|
7
7
|
module Matchers
|
8
8
|
class HaveCurrentPath < WrappedElementMatcher
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_current_path(
|
10
|
+
el.assert_current_path(current_path, **@kw_args, &@filter_block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_no_current_path(
|
14
|
+
el.assert_no_current_path(current_path, **@kw_args, &@filter_block)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
@@ -5,64 +5,64 @@ require 'capybara/rspec/matchers/base'
|
|
5
5
|
module Capybara
|
6
6
|
module RSpecMatchers
|
7
7
|
module Matchers
|
8
|
-
class HaveSelector <
|
8
|
+
class HaveSelector < CountableWrappedElementMatcher
|
9
|
+
def initialize(*args, **kw_args, &filter_block)
|
10
|
+
super
|
11
|
+
return unless (@args.size < 2) && @kw_args.keys.any?(String)
|
12
|
+
|
13
|
+
@args.push(@kw_args)
|
14
|
+
@kw_args = {}
|
15
|
+
end
|
16
|
+
|
9
17
|
def element_matches?(el)
|
10
|
-
el.assert_selector(*@args, &@filter_block)
|
18
|
+
el.assert_selector(*@args, **session_query_options, &@filter_block)
|
11
19
|
end
|
12
20
|
|
13
21
|
def element_does_not_match?(el)
|
14
|
-
el.assert_no_selector(*@args, &@filter_block)
|
22
|
+
el.assert_no_selector(*@args, **session_query_options, &@filter_block)
|
15
23
|
end
|
16
24
|
|
17
|
-
def description
|
18
|
-
"have #{query.description}"
|
19
|
-
end
|
25
|
+
def description = "have #{query.description}"
|
20
26
|
|
21
27
|
def query
|
22
|
-
@query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
|
28
|
+
@query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
26
32
|
class HaveAllSelectors < WrappedElementMatcher
|
27
33
|
def element_matches?(el)
|
28
|
-
el.assert_all_of_selectors(*@args, &@filter_block)
|
34
|
+
el.assert_all_of_selectors(*@args, **session_query_options, &@filter_block)
|
29
35
|
end
|
30
36
|
|
31
37
|
def does_not_match?(_actual)
|
32
38
|
raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'
|
33
39
|
end
|
34
40
|
|
35
|
-
def description
|
36
|
-
'have all selectors'
|
37
|
-
end
|
41
|
+
def description = 'have all selectors'
|
38
42
|
end
|
39
43
|
|
40
44
|
class HaveNoSelectors < WrappedElementMatcher
|
41
45
|
def element_matches?(el)
|
42
|
-
el.assert_none_of_selectors(*@args, &@filter_block)
|
46
|
+
el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
|
43
47
|
end
|
44
48
|
|
45
49
|
def does_not_match?(_actual)
|
46
50
|
raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'
|
47
51
|
end
|
48
52
|
|
49
|
-
def description
|
50
|
-
'have no selectors'
|
51
|
-
end
|
53
|
+
def description = 'have no selectors'
|
52
54
|
end
|
53
55
|
|
54
56
|
class HaveAnySelectors < WrappedElementMatcher
|
55
57
|
def element_matches?(el)
|
56
|
-
el.assert_any_of_selectors(*@args, &@filter_block)
|
58
|
+
el.assert_any_of_selectors(*@args, **session_query_options, &@filter_block)
|
57
59
|
end
|
58
60
|
|
59
|
-
def does_not_match?(
|
60
|
-
el.assert_none_of_selectors(*@args, &@filter_block)
|
61
|
+
def does_not_match?(el)
|
62
|
+
el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
|
61
63
|
end
|
62
64
|
|
63
|
-
def description
|
64
|
-
'have any selectors'
|
65
|
-
end
|
65
|
+
def description = 'have any selectors'
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'capybara/rspec/matchers/base'
|
4
|
+
|
5
|
+
module Capybara
|
6
|
+
module RSpecMatchers
|
7
|
+
module Matchers
|
8
|
+
class HaveSibling < CountableWrappedElementMatcher
|
9
|
+
def element_matches?(el)
|
10
|
+
el.assert_sibling(*@args, **session_query_options, &@filter_block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def element_does_not_match?(el)
|
14
|
+
el.assert_no_sibling(*@args, **session_query_options, &@filter_block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
"have sibling #{query.description}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def query
|
22
|
+
@query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -5,17 +5,17 @@ require 'capybara/rspec/matchers/base'
|
|
5
5
|
module Capybara
|
6
6
|
module RSpecMatchers
|
7
7
|
module Matchers
|
8
|
-
class HaveText <
|
8
|
+
class HaveText < CountableWrappedElementMatcher
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_text(*@args)
|
10
|
+
el.assert_text(*@args, **@kw_args)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_no_text(*@args)
|
14
|
+
el.assert_no_text(*@args, **@kw_args)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
18
|
-
"text #{format(text)}"
|
18
|
+
"have text #{format(text)}"
|
19
19
|
end
|
20
20
|
|
21
21
|
def format(content)
|
@@ -7,11 +7,11 @@ module Capybara
|
|
7
7
|
module Matchers
|
8
8
|
class HaveTitle < WrappedElementMatcher
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_title(*@args)
|
10
|
+
el.assert_title(*@args, **@kw_args)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_no_title(*@args)
|
14
|
+
el.assert_no_title(*@args, **@kw_args)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
@@ -7,11 +7,11 @@ module Capybara
|
|
7
7
|
module Matchers
|
8
8
|
class MatchSelector < HaveSelector
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_matches_selector(*@args, &@filter_block)
|
10
|
+
el.assert_matches_selector(*@args, **session_query_options, &@filter_block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_not_matches_selector(*@args, &@filter_block)
|
14
|
+
el.assert_not_matches_selector(*@args, **session_query_options, &@filter_block)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
@@ -19,7 +19,7 @@ module Capybara
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def query
|
22
|
-
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
|
22
|
+
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -6,8 +6,13 @@ module Capybara
|
|
6
6
|
module RSpecMatchers
|
7
7
|
module Matchers
|
8
8
|
class MatchStyle < WrappedElementMatcher
|
9
|
+
def initialize(styles = nil, **kw_args, &filter_block)
|
10
|
+
styles, kw_args = kw_args, {} if styles.nil?
|
11
|
+
super(styles, **kw_args, &filter_block)
|
12
|
+
end
|
13
|
+
|
9
14
|
def element_matches?(el)
|
10
|
-
el.assert_matches_style(*@args)
|
15
|
+
el.assert_matches_style(*@args, **@kw_args)
|
11
16
|
end
|
12
17
|
|
13
18
|
def does_not_match?(_actual)
|
@@ -28,7 +33,7 @@ module Capybara
|
|
28
33
|
##
|
29
34
|
# @deprecated
|
30
35
|
class HaveStyle < MatchStyle
|
31
|
-
def initialize(*args, &filter_block)
|
36
|
+
def initialize(*args, **kw_args, &filter_block)
|
32
37
|
warn 'HaveStyle matcher is deprecated, please use the MatchStyle matcher instead'
|
33
38
|
super
|
34
39
|
end
|