capybara 2.5.0 → 2.18.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 +5 -5
- data/.yard/templates_custom/default/class/html/selectors.erb +38 -0
- data/.yard/templates_custom/default/class/html/setup.rb +17 -0
- data/.yard/yard_extensions.rb +78 -0
- data/.yardopts +1 -0
- data/History.md +413 -10
- data/License.txt +1 -1
- data/README.md +237 -130
- data/lib/capybara/config.rb +132 -0
- data/lib/capybara/cucumber.rb +3 -1
- data/lib/capybara/driver/base.rb +27 -6
- data/lib/capybara/driver/node.rb +14 -5
- data/lib/capybara/dsl.rb +2 -3
- data/lib/capybara/helpers.rb +13 -65
- data/lib/capybara/minitest/spec.rb +177 -0
- data/lib/capybara/minitest.rb +278 -0
- data/lib/capybara/node/actions.rb +180 -24
- data/lib/capybara/node/base.rb +17 -5
- data/lib/capybara/node/document.rb +5 -0
- data/lib/capybara/node/document_matchers.rb +15 -14
- data/lib/capybara/node/element.rb +55 -7
- data/lib/capybara/node/finders.rb +179 -67
- data/lib/capybara/node/matchers.rb +301 -105
- data/lib/capybara/node/simple.rb +15 -4
- data/lib/capybara/queries/ancestor_query.rb +25 -0
- data/lib/capybara/queries/base_query.rb +69 -3
- data/lib/capybara/queries/current_path_query.rb +17 -8
- data/lib/capybara/queries/match_query.rb +19 -0
- data/lib/capybara/queries/selector_query.rb +251 -0
- data/lib/capybara/queries/sibling_query.rb +25 -0
- data/lib/capybara/queries/text_query.rb +67 -16
- data/lib/capybara/queries/title_query.rb +4 -2
- data/lib/capybara/query.rb +3 -131
- data/lib/capybara/rack_test/browser.rb +14 -5
- data/lib/capybara/rack_test/css_handlers.rb +1 -0
- data/lib/capybara/rack_test/driver.rb +15 -8
- data/lib/capybara/rack_test/form.rb +34 -12
- data/lib/capybara/rack_test/node.rb +29 -12
- data/lib/capybara/rails.rb +3 -3
- data/lib/capybara/result.rb +104 -9
- data/lib/capybara/rspec/compound.rb +95 -0
- data/lib/capybara/rspec/features.rb +17 -6
- data/lib/capybara/rspec/matcher_proxies.rb +45 -0
- data/lib/capybara/rspec/matchers.rb +199 -80
- data/lib/capybara/rspec.rb +4 -2
- data/lib/capybara/selector/css.rb +30 -0
- data/lib/capybara/selector/filter.rb +20 -0
- data/lib/capybara/selector/filter_set.rb +74 -0
- data/lib/capybara/selector/filters/base.rb +33 -0
- data/lib/capybara/selector/filters/expression_filter.rb +40 -0
- data/lib/capybara/selector/filters/node_filter.rb +27 -0
- data/lib/capybara/selector/selector.rb +276 -0
- data/lib/capybara/selector.rb +452 -157
- data/lib/capybara/selenium/driver.rb +282 -81
- data/lib/capybara/selenium/node.rb +144 -46
- data/lib/capybara/server.rb +59 -16
- data/lib/capybara/session/config.rb +114 -0
- data/lib/capybara/session/matchers.rb +29 -19
- data/lib/capybara/session.rb +378 -143
- data/lib/capybara/spec/fixtures/no_extension +1 -0
- data/lib/capybara/spec/public/jquery-ui.js +13 -791
- data/lib/capybara/spec/public/jquery.js +4 -9045
- data/lib/capybara/spec/public/test.js +45 -11
- data/lib/capybara/spec/session/accept_alert_spec.rb +30 -7
- data/lib/capybara/spec/session/accept_confirm_spec.rb +14 -2
- data/lib/capybara/spec/session/accept_prompt_spec.rb +35 -6
- data/lib/capybara/spec/session/all_spec.rb +45 -32
- data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +110 -0
- data/lib/capybara/spec/session/assert_current_path.rb +15 -2
- data/lib/capybara/spec/session/assert_selector.rb +29 -28
- data/lib/capybara/spec/session/assert_text.rb +59 -20
- data/lib/capybara/spec/session/assert_title.rb +25 -11
- data/lib/capybara/spec/session/attach_file_spec.rb +42 -4
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +90 -14
- data/lib/capybara/spec/session/choose_spec.rb +31 -5
- data/lib/capybara/spec/session/click_button_spec.rb +20 -9
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +15 -9
- data/lib/capybara/spec/session/click_link_spec.rb +39 -15
- data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
- data/lib/capybara/spec/session/current_url_spec.rb +12 -3
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +6 -5
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +4 -3
- data/lib/capybara/spec/session/element/assert_match_selector.rb +36 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +23 -0
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +106 -0
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +23 -1
- data/lib/capybara/spec/session/execute_script_spec.rb +22 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +50 -32
- data/lib/capybara/spec/session/find_button_spec.rb +43 -2
- data/lib/capybara/spec/session/find_by_id_spec.rb +3 -2
- data/lib/capybara/spec/session/find_field_spec.rb +42 -6
- data/lib/capybara/spec/session/find_link_spec.rb +22 -3
- data/lib/capybara/spec/session/find_spec.rb +103 -57
- data/lib/capybara/spec/session/first_spec.rb +34 -18
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +103 -0
- data/lib/capybara/spec/session/{within_frame_spec.rb → frame/within_frame_spec.rb} +44 -2
- data/lib/capybara/spec/session/go_back_spec.rb +2 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_button_spec.rb +17 -8
- data/lib/capybara/spec/session/has_css_spec.rb +85 -73
- data/lib/capybara/spec/session/has_current_path_spec.rb +91 -7
- data/lib/capybara/spec/session/has_field_spec.rb +93 -58
- data/lib/capybara/spec/session/has_link_spec.rb +9 -8
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
- data/lib/capybara/spec/session/has_select_spec.rb +159 -59
- data/lib/capybara/spec/session/has_selector_spec.rb +64 -28
- data/lib/capybara/spec/session/has_table_spec.rb +1 -0
- data/lib/capybara/spec/session/has_text_spec.rb +27 -12
- data/lib/capybara/spec/session/has_title_spec.rb +22 -4
- data/lib/capybara/spec/session/has_xpath_spec.rb +32 -29
- data/lib/capybara/spec/session/headers.rb +2 -1
- data/lib/capybara/spec/session/html_spec.rb +4 -3
- data/lib/capybara/spec/session/node_spec.rb +198 -38
- data/lib/capybara/spec/session/refresh_spec.rb +28 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +46 -5
- data/lib/capybara/spec/session/response_code.rb +2 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -5
- data/lib/capybara/spec/session/save_page_spec.rb +34 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
- data/lib/capybara/spec/session/screenshot_spec.rb +4 -2
- data/lib/capybara/spec/session/select_spec.rb +34 -32
- data/lib/capybara/spec/session/selectors_spec.rb +65 -0
- data/lib/capybara/spec/session/sibling_spec.rb +52 -0
- data/lib/capybara/spec/session/text_spec.rb +4 -4
- data/lib/capybara/spec/session/title_spec.rb +2 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +42 -2
- data/lib/capybara/spec/session/unselect_spec.rb +17 -16
- data/lib/capybara/spec/session/visit_spec.rb +77 -2
- data/lib/capybara/spec/session/window/become_closed_spec.rb +12 -11
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +16 -11
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +7 -4
- data/lib/capybara/spec/session/window/window_spec.rb +36 -29
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +31 -7
- data/lib/capybara/spec/session/within_spec.rb +14 -6
- data/lib/capybara/spec/spec_helper.rb +37 -4
- data/lib/capybara/spec/test_app.rb +15 -3
- data/lib/capybara/spec/views/buttons.erb +1 -0
- data/lib/capybara/spec/views/fieldsets.erb +2 -1
- data/lib/capybara/spec/views/form.erb +169 -9
- data/lib/capybara/spec/views/frame_child.erb +10 -2
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +3 -2
- data/lib/capybara/spec/views/frame_two.erb +2 -1
- data/lib/capybara/spec/views/header_links.erb +1 -0
- data/lib/capybara/spec/views/host_links.erb +1 -0
- data/lib/capybara/spec/views/initial_alert.erb +10 -0
- data/lib/capybara/spec/views/path.erb +1 -0
- data/lib/capybara/spec/views/popup_one.erb +1 -0
- data/lib/capybara/spec/views/popup_two.erb +1 -0
- data/lib/capybara/spec/views/postback.erb +2 -1
- data/lib/capybara/spec/views/tables.erb +1 -0
- data/lib/capybara/spec/views/with_base_tag.erb +1 -0
- data/lib/capybara/spec/views/with_count.erb +2 -1
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
- data/lib/capybara/spec/views/with_hover.erb +7 -1
- data/lib/capybara/spec/views/with_html.erb +40 -2
- data/lib/capybara/spec/views/with_html_entities.erb +1 -0
- data/lib/capybara/spec/views/with_js.erb +32 -1
- data/lib/capybara/spec/views/with_scope.erb +1 -0
- data/lib/capybara/spec/views/with_simple_html.erb +2 -1
- data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
- data/lib/capybara/spec/views/with_title.erb +2 -1
- data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
- data/lib/capybara/spec/views/with_windows.erb +7 -0
- data/lib/capybara/spec/views/within_frames.erb +3 -2
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +20 -3
- data/lib/capybara.rb +189 -93
- data/spec/basic_node_spec.rb +7 -6
- data/spec/capybara_spec.rb +90 -4
- data/spec/dsl_spec.rb +3 -1
- data/spec/filter_set_spec.rb +28 -0
- data/spec/fixtures/capybara.csv +1 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +5 -1
- data/spec/minitest_spec.rb +130 -0
- data/spec/minitest_spec_spec.rb +135 -0
- data/spec/per_session_config_spec.rb +67 -0
- data/spec/rack_test_spec.rb +50 -7
- data/spec/result_spec.rb +76 -0
- data/spec/rspec/features_spec.rb +21 -8
- data/spec/rspec/scenarios_spec.rb +21 -0
- data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +160 -54
- data/spec/rspec/views_spec.rb +5 -0
- data/spec/rspec_matchers_spec.rb +46 -0
- data/spec/rspec_spec.rb +79 -1
- data/spec/selector_spec.rb +199 -0
- data/spec/selenium_spec_chrome.rb +54 -9
- data/spec/selenium_spec_firefox.rb +68 -0
- data/spec/selenium_spec_marionette.rb +127 -0
- data/spec/server_spec.rb +102 -14
- data/spec/session_spec.rb +54 -0
- data/spec/shared_selenium_session.rb +215 -0
- data/spec/spec_helper.rb +7 -0
- metadata +140 -15
- data/spec/selenium_spec.rb +0 -128
data/lib/capybara/query.rb
CHANGED
|
@@ -1,135 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'capybara/queries/selector_query'
|
|
1
3
|
module Capybara
|
|
2
4
|
# @deprecated This class and its methods are not supposed to be used by users of Capybara's public API.
|
|
3
5
|
# It may be removed in future versions of Capybara.
|
|
4
|
-
|
|
5
|
-
attr_accessor :selector, :locator, :options, :expression, :find, :negative
|
|
6
|
-
|
|
7
|
-
VALID_KEYS = [:text, :visible, :between, :count, :maximum, :minimum, :exact, :match, :wait]
|
|
8
|
-
VALID_MATCH = [:first, :smart, :prefer_exact, :one]
|
|
9
|
-
|
|
10
|
-
def initialize(*args)
|
|
11
|
-
@options = if args.last.is_a?(Hash) then args.pop.dup else {} end
|
|
12
|
-
|
|
13
|
-
if args[0].is_a?(Symbol)
|
|
14
|
-
@selector = Selector.all[args[0]]
|
|
15
|
-
@locator = args[1]
|
|
16
|
-
else
|
|
17
|
-
@selector = Selector.all.values.find { |s| s.match?(args[0]) }
|
|
18
|
-
@locator = args[0]
|
|
19
|
-
end
|
|
20
|
-
@selector ||= Selector.all[Capybara.default_selector]
|
|
21
|
-
|
|
22
|
-
# for compatibility with Capybara 2.0
|
|
23
|
-
if Capybara.exact_options and @selector == Selector.all[:option]
|
|
24
|
-
@options[:exact] = true
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
@expression = @selector.call(@locator)
|
|
28
|
-
assert_valid_keys
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def name; selector.name; end
|
|
32
|
-
def label; selector.label or selector.name; end
|
|
33
|
-
|
|
34
|
-
def description
|
|
35
|
-
@description = "#{label} #{locator.inspect}"
|
|
36
|
-
@description << " with text #{options[:text].inspect}" if options[:text]
|
|
37
|
-
@description << selector.description(options)
|
|
38
|
-
@description
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def matches_filters?(node)
|
|
42
|
-
if options[:text]
|
|
43
|
-
regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
|
|
44
|
-
return false if not node.text(visible).match(regexp)
|
|
45
|
-
end
|
|
46
|
-
case visible
|
|
47
|
-
when :visible then return false unless node.visible?
|
|
48
|
-
when :hidden then return false if node.visible?
|
|
49
|
-
end
|
|
50
|
-
selector.custom_filters.each do |name, filter|
|
|
51
|
-
if options.has_key?(name)
|
|
52
|
-
return false unless filter.matches?(node, options[name])
|
|
53
|
-
elsif filter.default?
|
|
54
|
-
return false unless filter.matches?(node, filter.default)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def visible
|
|
60
|
-
if options.has_key?(:visible)
|
|
61
|
-
case @options[:visible]
|
|
62
|
-
when true then :visible
|
|
63
|
-
when false then :all
|
|
64
|
-
else @options[:visible]
|
|
65
|
-
end
|
|
66
|
-
else
|
|
67
|
-
if Capybara.ignore_hidden_elements
|
|
68
|
-
:visible
|
|
69
|
-
else
|
|
70
|
-
:all
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def exact?
|
|
76
|
-
if options.has_key?(:exact)
|
|
77
|
-
@options[:exact]
|
|
78
|
-
else
|
|
79
|
-
Capybara.exact
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def match
|
|
84
|
-
if options.has_key?(:match)
|
|
85
|
-
@options[:match]
|
|
86
|
-
else
|
|
87
|
-
Capybara.match
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def xpath(exact=nil)
|
|
92
|
-
exact = self.exact? if exact == nil
|
|
93
|
-
if @expression.respond_to?(:to_xpath) and exact
|
|
94
|
-
@expression.to_xpath(:exact)
|
|
95
|
-
else
|
|
96
|
-
@expression.to_s
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def css
|
|
101
|
-
@expression
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# @api private
|
|
105
|
-
def resolve_for(node, exact = nil)
|
|
106
|
-
node.synchronize do
|
|
107
|
-
children = if selector.format == :css
|
|
108
|
-
node.find_css(self.css)
|
|
109
|
-
else
|
|
110
|
-
node.find_xpath(self.xpath(exact))
|
|
111
|
-
end.map do |child|
|
|
112
|
-
if node.is_a?(Capybara::Node::Base)
|
|
113
|
-
Capybara::Node::Element.new(node.session, child, node, self)
|
|
114
|
-
else
|
|
115
|
-
Capybara::Node::Simple.new(child)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
Capybara::Result.new(children, self)
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
private
|
|
123
|
-
|
|
124
|
-
def valid_keys
|
|
125
|
-
COUNT_KEYS + [:text, :visible, :exact, :match, :wait] + @selector.custom_filters.keys
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def assert_valid_keys
|
|
129
|
-
super
|
|
130
|
-
unless VALID_MATCH.include?(match)
|
|
131
|
-
raise ArgumentError, "invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(", ")}"
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
6
|
+
Query = Queries::SelectorQuery
|
|
135
7
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class Capybara::RackTest::Browser
|
|
2
3
|
include ::Rack::Test::Methods
|
|
3
4
|
|
|
@@ -21,6 +22,11 @@ class Capybara::RackTest::Browser
|
|
|
21
22
|
process_and_follow_redirects(:get, path, attributes)
|
|
22
23
|
end
|
|
23
24
|
|
|
25
|
+
def refresh
|
|
26
|
+
reset_cache!
|
|
27
|
+
request(last_request.fullpath, last_request.env)
|
|
28
|
+
end
|
|
29
|
+
|
|
24
30
|
def submit(method, path, attributes)
|
|
25
31
|
path = request_path if not path or path.empty?
|
|
26
32
|
process_and_follow_redirects(method, path, attributes, {'HTTP_REFERER' => current_url})
|
|
@@ -44,10 +50,13 @@ class Capybara::RackTest::Browser
|
|
|
44
50
|
def process(method, path, attributes = {}, env = {})
|
|
45
51
|
new_uri = URI.parse(path)
|
|
46
52
|
method.downcase! unless method.is_a? Symbol
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
if path.empty?
|
|
54
|
+
new_uri.path = request_path
|
|
55
|
+
else
|
|
56
|
+
new_uri.path = request_path if path.start_with?("?")
|
|
57
|
+
new_uri.path = "/" if new_uri.path.empty?
|
|
58
|
+
new_uri.path = request_path.sub(%r(/[^/]*$), '/') + new_uri.path unless new_uri.path.start_with?('/')
|
|
59
|
+
end
|
|
51
60
|
new_uri.scheme ||= @current_scheme
|
|
52
61
|
new_uri.host ||= @current_host
|
|
53
62
|
new_uri.port ||= @current_port unless new_uri.default_port == @current_port
|
|
@@ -67,7 +76,7 @@ class Capybara::RackTest::Browser
|
|
|
67
76
|
end
|
|
68
77
|
|
|
69
78
|
def reset_host!
|
|
70
|
-
uri = URI.parse(
|
|
79
|
+
uri = URI.parse(driver.session_options.app_host || driver.session_options.default_host)
|
|
71
80
|
@current_scheme = uri.scheme
|
|
72
81
|
@current_host = uri.host
|
|
73
82
|
@current_port = uri.port
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'rack/test'
|
|
2
3
|
require 'rack/utils'
|
|
3
|
-
require '
|
|
4
|
+
require 'mini_mime'
|
|
4
5
|
require 'nokogiri'
|
|
5
6
|
require 'cgi'
|
|
6
7
|
|
|
7
8
|
class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
8
9
|
DEFAULT_OPTIONS = {
|
|
9
|
-
:
|
|
10
|
-
:
|
|
11
|
-
:
|
|
10
|
+
respect_data_method: false,
|
|
11
|
+
follow_redirects: true,
|
|
12
|
+
redirect_limit: 5
|
|
12
13
|
}
|
|
13
14
|
attr_reader :app, :options
|
|
14
15
|
|
|
15
16
|
def initialize(app, options={})
|
|
16
17
|
raise ArgumentError, "rack-test requires a rack application, but none was given" unless app
|
|
18
|
+
@session = nil
|
|
17
19
|
@app = app
|
|
18
20
|
@options = DEFAULT_OPTIONS.merge(options)
|
|
19
21
|
end
|
|
@@ -42,6 +44,10 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
42
44
|
browser.visit(path, attributes)
|
|
43
45
|
end
|
|
44
46
|
|
|
47
|
+
def refresh
|
|
48
|
+
browser.refresh
|
|
49
|
+
end
|
|
50
|
+
|
|
45
51
|
def submit(method, path, attributes)
|
|
46
52
|
browser.submit(method, path, attributes)
|
|
47
53
|
end
|
|
@@ -65,11 +71,11 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
65
71
|
def find_xpath(selector)
|
|
66
72
|
browser.find(:xpath, selector)
|
|
67
73
|
end
|
|
68
|
-
|
|
74
|
+
|
|
69
75
|
def find_css(selector)
|
|
70
76
|
browser.find(:css,selector)
|
|
71
77
|
end
|
|
72
|
-
|
|
78
|
+
|
|
73
79
|
def html
|
|
74
80
|
browser.html
|
|
75
81
|
end
|
|
@@ -77,7 +83,7 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
77
83
|
def dom
|
|
78
84
|
browser.dom
|
|
79
85
|
end
|
|
80
|
-
|
|
86
|
+
|
|
81
87
|
def title
|
|
82
88
|
browser.title
|
|
83
89
|
end
|
|
@@ -86,8 +92,9 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
86
92
|
@browser = nil
|
|
87
93
|
end
|
|
88
94
|
|
|
95
|
+
# @deprecated This method is being removed
|
|
89
96
|
def browser_initialized?
|
|
90
|
-
!@browser.nil?
|
|
97
|
+
super && !@browser.nil?
|
|
91
98
|
end
|
|
92
99
|
|
|
93
100
|
def get(*args, &block); browser.get(*args, &block); end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
2
3
|
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
|
|
3
4
|
# the class specifically when determining whether to construct the request as multipart.
|
|
@@ -12,18 +13,20 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
|
12
13
|
def original_filename; ""; end
|
|
13
14
|
def content_type; "application/octet-stream"; end
|
|
14
15
|
def path; @empty_file.path; end
|
|
16
|
+
def size; 0; end
|
|
17
|
+
def read; ""; end
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
def params(button)
|
|
18
|
-
params =
|
|
21
|
+
params = make_params
|
|
19
22
|
|
|
20
23
|
form_element_types=[:input, :select, :textarea]
|
|
21
|
-
form_elements_xpath=XPath.generate do |x|
|
|
24
|
+
form_elements_xpath=XPath.generate do |x|
|
|
22
25
|
xpath=x.descendant(*form_element_types).where(~x.attr(:form))
|
|
23
26
|
xpath=xpath.union(x.anywhere(*form_element_types).where(x.attr(:form) == native[:id])) if native[:id]
|
|
24
27
|
xpath.where(~x.attr(:disabled))
|
|
25
28
|
end.to_s
|
|
26
|
-
|
|
29
|
+
|
|
27
30
|
native.xpath(form_elements_xpath).map do |field|
|
|
28
31
|
case field.name
|
|
29
32
|
when 'input'
|
|
@@ -31,7 +34,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
|
31
34
|
if field['checked']
|
|
32
35
|
node=Capybara::RackTest::Node.new(self.driver, field)
|
|
33
36
|
merge_param!(params, field['name'].to_s, node.value.to_s)
|
|
34
|
-
end
|
|
37
|
+
end
|
|
35
38
|
elsif %w(submit image).include? field['type']
|
|
36
39
|
# TO DO identify the click button here (in document order, rather
|
|
37
40
|
# than leaving until the end of the params)
|
|
@@ -41,8 +44,8 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
|
41
44
|
if (value = field['value']).to_s.empty?
|
|
42
45
|
NilUploadedFile.new
|
|
43
46
|
else
|
|
44
|
-
|
|
45
|
-
Rack::Test::UploadedFile.new(value, content_type)
|
|
47
|
+
mime_info = MiniMime.lookup_by_filename(value)
|
|
48
|
+
Rack::Test::UploadedFile.new(value, (mime_info && mime_info.content_type).to_s)
|
|
46
49
|
end
|
|
47
50
|
merge_param!(params, field['name'].to_s, file)
|
|
48
51
|
else
|
|
@@ -63,17 +66,18 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
|
63
66
|
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
|
|
64
67
|
end
|
|
65
68
|
when 'textarea'
|
|
66
|
-
merge_param!(params, field['name'].to_s, field.
|
|
69
|
+
merge_param!(params, field['name'].to_s, field['_capybara_raw_value'].to_s.gsub(/\n/, "\r\n"))
|
|
67
70
|
end
|
|
68
71
|
end
|
|
69
72
|
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|
|
70
|
-
|
|
73
|
+
|
|
74
|
+
params.to_params_hash
|
|
71
75
|
end
|
|
72
76
|
|
|
73
77
|
def submit(button)
|
|
74
78
|
action = (button && button['formaction']) || native['action']
|
|
75
|
-
|
|
76
|
-
driver.submit(
|
|
79
|
+
method = (button && button['formmethod']) || request_method
|
|
80
|
+
driver.submit(method, action.to_s, params(button))
|
|
77
81
|
end
|
|
78
82
|
|
|
79
83
|
def multipart?
|
|
@@ -82,11 +86,29 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
|
82
86
|
|
|
83
87
|
private
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
class ParamsHash < Hash
|
|
90
|
+
def to_params_hash
|
|
91
|
+
self
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def request_method
|
|
86
96
|
self[:method] =~ /post/i ? :post : :get
|
|
87
97
|
end
|
|
88
98
|
|
|
89
99
|
def merge_param!(params, key, value)
|
|
90
|
-
Rack::Utils.
|
|
100
|
+
if Rack::Utils.respond_to?(:default_query_parser)
|
|
101
|
+
Rack::Utils.default_query_parser.normalize_params(params, key, value, Rack::Utils.param_depth_limit)
|
|
102
|
+
else
|
|
103
|
+
Rack::Utils.normalize_params(params, key, value)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def make_params
|
|
108
|
+
if Rack::Utils.respond_to?(:default_query_parser)
|
|
109
|
+
Rack::Utils.default_query_parser.make_params
|
|
110
|
+
else
|
|
111
|
+
ParamsHash.new
|
|
112
|
+
end
|
|
91
113
|
end
|
|
92
114
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
2
3
|
def all_text
|
|
3
4
|
Capybara::Helpers.normalize_whitespace(native.text)
|
|
@@ -16,8 +17,14 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def set(value)
|
|
19
|
-
if
|
|
20
|
-
|
|
20
|
+
return if disabled?
|
|
21
|
+
if readonly?
|
|
22
|
+
warn "Attempt to set readonly element with value: #{value} \n * This will raise an exception in a future version of Capybara"
|
|
23
|
+
return
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if (Array === value) && !multiple?
|
|
27
|
+
raise TypeError.new "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}"
|
|
21
28
|
end
|
|
22
29
|
|
|
23
30
|
if radio?
|
|
@@ -27,11 +34,7 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
|
27
34
|
elsif input_field?
|
|
28
35
|
set_input(value)
|
|
29
36
|
elsif textarea?
|
|
30
|
-
|
|
31
|
-
warn "Attempt to set readonly element with value: #{value} \n * This will raise an exception in a future version of Capybara"
|
|
32
|
-
else
|
|
33
|
-
native.content = value.to_s
|
|
34
|
-
end
|
|
37
|
+
native['_capybara_raw_value'] = value.to_s
|
|
35
38
|
end
|
|
36
39
|
end
|
|
37
40
|
|
|
@@ -59,6 +62,18 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
|
59
62
|
((tag_name == 'button') and type.nil? or type == "submit")
|
|
60
63
|
associated_form = form
|
|
61
64
|
Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form
|
|
65
|
+
elsif (tag_name == 'input' and %w(checkbox radio).include?(type))
|
|
66
|
+
set(!checked?)
|
|
67
|
+
elsif (tag_name == 'label')
|
|
68
|
+
labelled_control = if native[:for]
|
|
69
|
+
find_xpath("//input[@id='#{native[:for]}']").first
|
|
70
|
+
else
|
|
71
|
+
find_xpath(".//input").first
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if labelled_control && (labelled_control.checkbox? || labelled_control.radio?)
|
|
75
|
+
labelled_control.set(!labelled_control.checked?)
|
|
76
|
+
end
|
|
62
77
|
end
|
|
63
78
|
end
|
|
64
79
|
|
|
@@ -80,9 +95,9 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
|
80
95
|
|
|
81
96
|
def disabled?
|
|
82
97
|
if %w(option optgroup).include? tag_name
|
|
83
|
-
string_node.disabled? || find_xpath("parent::*")[0].disabled?
|
|
98
|
+
string_node.disabled? || find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
|
|
84
99
|
else
|
|
85
|
-
string_node.disabled?
|
|
100
|
+
string_node.disabled? || !find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
|
|
86
101
|
end
|
|
87
102
|
end
|
|
88
103
|
|
|
@@ -126,7 +141,7 @@ private
|
|
|
126
141
|
|
|
127
142
|
# a reference to the select node if this is an option node
|
|
128
143
|
def select_node
|
|
129
|
-
find_xpath('./ancestor::select').first
|
|
144
|
+
find_xpath('./ancestor::select[1]').first
|
|
130
145
|
end
|
|
131
146
|
|
|
132
147
|
def type
|
|
@@ -141,7 +156,7 @@ private
|
|
|
141
156
|
end
|
|
142
157
|
end
|
|
143
158
|
|
|
144
|
-
def set_radio(
|
|
159
|
+
def set_radio(_value)
|
|
145
160
|
other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s
|
|
146
161
|
driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") }
|
|
147
162
|
native['checked'] = 'checked'
|
|
@@ -170,7 +185,7 @@ private
|
|
|
170
185
|
end
|
|
171
186
|
native.remove
|
|
172
187
|
else
|
|
173
|
-
if
|
|
188
|
+
if readonly?
|
|
174
189
|
warn "Attempt to set readonly element with value: #{value} \n *This will raise an exception in a future version of Capybara"
|
|
175
190
|
else
|
|
176
191
|
native['value'] = value.to_s
|
|
@@ -182,6 +197,8 @@ private
|
|
|
182
197
|
self[attribute] && !self[attribute].empty?
|
|
183
198
|
end
|
|
184
199
|
|
|
200
|
+
protected
|
|
201
|
+
|
|
185
202
|
def checkbox?
|
|
186
203
|
input_field? && type == 'checkbox'
|
|
187
204
|
end
|
data/lib/capybara/rails.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
require 'capybara/dsl'
|
|
3
3
|
|
|
4
4
|
Capybara.app = Rack::Builder.new do
|
|
@@ -12,9 +12,9 @@ Capybara.app = Rack::Builder.new do
|
|
|
12
12
|
end
|
|
13
13
|
end.to_app
|
|
14
14
|
|
|
15
|
-
Capybara.
|
|
15
|
+
Capybara.save_path = Rails.root.join('tmp/capybara')
|
|
16
16
|
|
|
17
17
|
# Override default rack_test driver to respect data-method attributes.
|
|
18
18
|
Capybara.register_driver :rack_test do |app|
|
|
19
|
-
Capybara::RackTest::Driver.new(app, :
|
|
19
|
+
Capybara::RackTest::Driver.new(app, respect_data_method: true)
|
|
20
20
|
end
|
data/lib/capybara/result.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'forwardable'
|
|
2
3
|
|
|
3
4
|
module Capybara
|
|
@@ -24,27 +25,93 @@ module Capybara
|
|
|
24
25
|
|
|
25
26
|
def initialize(elements, query)
|
|
26
27
|
@elements = elements
|
|
27
|
-
@
|
|
28
|
-
@
|
|
28
|
+
@result_cache = []
|
|
29
|
+
@results_enum = lazy_select_elements { |node| query.matches_filters?(node) }
|
|
29
30
|
@query = query
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
def_delegators
|
|
33
|
-
|
|
33
|
+
def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample
|
|
34
|
+
|
|
35
|
+
alias :index :find_index
|
|
36
|
+
|
|
37
|
+
def each(&block)
|
|
38
|
+
return enum_for(:each) unless block_given?
|
|
39
|
+
|
|
40
|
+
@result_cache.each(&block)
|
|
41
|
+
loop do
|
|
42
|
+
next_result = @results_enum.next
|
|
43
|
+
@result_cache << next_result
|
|
44
|
+
block.call(next_result)
|
|
45
|
+
end
|
|
46
|
+
self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def [](*args)
|
|
50
|
+
if (args.size == 1) && ((idx = args[0]).is_a? Integer) && (idx >= 0)
|
|
51
|
+
@result_cache << @results_enum.next while @result_cache.size <= idx
|
|
52
|
+
@result_cache[idx]
|
|
53
|
+
else
|
|
54
|
+
full_results[*args]
|
|
55
|
+
end
|
|
56
|
+
rescue StopIteration
|
|
57
|
+
return nil
|
|
58
|
+
end
|
|
59
|
+
alias :at :[]
|
|
60
|
+
|
|
61
|
+
def empty?
|
|
62
|
+
!any?
|
|
63
|
+
end
|
|
34
64
|
|
|
35
65
|
def matches_count?
|
|
36
|
-
|
|
66
|
+
# Only check filters for as many elements as necessary to determine result
|
|
67
|
+
if @query.options[:count]
|
|
68
|
+
count_opt = Integer(@query.options[:count])
|
|
69
|
+
loop do
|
|
70
|
+
break if @result_cache.size > count_opt
|
|
71
|
+
@result_cache << @results_enum.next
|
|
72
|
+
end
|
|
73
|
+
return @result_cache.size == count_opt
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if @query.options[:minimum]
|
|
77
|
+
min_opt = Integer(@query.options[:minimum])
|
|
78
|
+
begin
|
|
79
|
+
@result_cache << @results_enum.next while @result_cache.size < min_opt
|
|
80
|
+
rescue StopIteration
|
|
81
|
+
return false
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if @query.options[:maximum]
|
|
86
|
+
max_opt = Integer(@query.options[:maximum])
|
|
87
|
+
begin
|
|
88
|
+
@result_cache << @results_enum.next while @result_cache.size <= max_opt
|
|
89
|
+
return false
|
|
90
|
+
rescue StopIteration
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if @query.options[:between]
|
|
95
|
+
max = Integer(@query.options[:between].max)
|
|
96
|
+
loop do
|
|
97
|
+
break if @result_cache.size > max
|
|
98
|
+
@result_cache << @results_enum.next
|
|
99
|
+
end
|
|
100
|
+
return false unless (@query.options[:between] === @result_cache.size)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
return true
|
|
37
104
|
end
|
|
38
105
|
|
|
39
106
|
def failure_message
|
|
40
|
-
message =
|
|
107
|
+
message = @query.failure_message
|
|
41
108
|
if count > 0
|
|
42
|
-
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " <<
|
|
109
|
+
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << full_results.map(&:text).map(&:inspect).join(", ")
|
|
43
110
|
else
|
|
44
111
|
message << " but there were no matches"
|
|
45
112
|
end
|
|
46
|
-
unless
|
|
47
|
-
elements =
|
|
113
|
+
unless rest.empty?
|
|
114
|
+
elements = rest.map(&:text).map(&:inspect).join(", ")
|
|
48
115
|
message << ". Also found " << elements << ", which matched the selector but not all filters."
|
|
49
116
|
end
|
|
50
117
|
message
|
|
@@ -53,5 +120,33 @@ module Capybara
|
|
|
53
120
|
def negative_failure_message
|
|
54
121
|
failure_message.sub(/(to find)/, 'not \1')
|
|
55
122
|
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
def full_results
|
|
127
|
+
loop { @result_cache << @results_enum.next }
|
|
128
|
+
@result_cache
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def rest
|
|
132
|
+
@rest ||= @elements - full_results
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def lazy_select_elements(&block)
|
|
136
|
+
# JRuby has an issue with lazy enumerators which
|
|
137
|
+
# causes a concurrency issue with network requests here
|
|
138
|
+
# https://github.com/jruby/jruby/issues/4212
|
|
139
|
+
if RUBY_PLATFORM == 'java'
|
|
140
|
+
@elements.select(&block).to_enum # non-lazy evaluation
|
|
141
|
+
elsif @elements.respond_to? :lazy #Ruby 2.0+
|
|
142
|
+
@elements.lazy.select(&block)
|
|
143
|
+
else
|
|
144
|
+
Enumerator.new do |yielder|
|
|
145
|
+
@elements.each do |val|
|
|
146
|
+
yielder.yield(val) if block.call(val)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
56
151
|
end
|
|
57
152
|
end
|