capybara 2.6.0 → 2.7.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/History.md +52 -15
- data/README.md +45 -38
- data/lib/capybara/cucumber.rb +1 -0
- data/lib/capybara/driver/base.rb +5 -2
- data/lib/capybara/driver/node.rb +1 -0
- data/lib/capybara/dsl.rb +1 -0
- data/lib/capybara/helpers.rb +3 -2
- data/lib/capybara/node/actions.rb +6 -0
- data/lib/capybara/node/base.rb +1 -0
- data/lib/capybara/node/document.rb +1 -0
- data/lib/capybara/node/document_matchers.rb +1 -0
- data/lib/capybara/node/element.rb +1 -0
- data/lib/capybara/node/finders.rb +3 -2
- data/lib/capybara/node/matchers.rb +72 -2
- data/lib/capybara/node/simple.rb +6 -3
- data/lib/capybara/queries/base_query.rb +1 -0
- data/lib/capybara/queries/current_path_query.rb +6 -3
- data/lib/capybara/queries/match_query.rb +21 -0
- data/lib/capybara/queries/selector_query.rb +138 -0
- data/lib/capybara/queries/text_query.rb +1 -0
- data/lib/capybara/queries/title_query.rb +1 -0
- data/lib/capybara/query.rb +3 -131
- data/lib/capybara/rack_test/browser.rb +1 -0
- data/lib/capybara/rack_test/css_handlers.rb +1 -0
- data/lib/capybara/rack_test/driver.rb +6 -4
- data/lib/capybara/rack_test/form.rb +1 -0
- data/lib/capybara/rack_test/node.rb +1 -0
- data/lib/capybara/rails.rb +2 -1
- data/lib/capybara/result.rb +1 -0
- data/lib/capybara/rspec/features.rb +1 -0
- data/lib/capybara/rspec/matchers.rb +54 -3
- data/lib/capybara/rspec.rb +1 -0
- data/lib/capybara/selector/filter.rb +48 -0
- data/lib/capybara/selector.rb +175 -75
- data/lib/capybara/selenium/driver.rb +24 -7
- data/lib/capybara/selenium/node.rb +1 -0
- data/lib/capybara/server.rb +38 -6
- data/lib/capybara/session/matchers.rb +2 -1
- data/lib/capybara/session.rb +30 -14
- data/lib/capybara/spec/public/test.js +6 -0
- data/lib/capybara/spec/session/accept_alert_spec.rb +2 -1
- data/lib/capybara/spec/session/accept_confirm_spec.rb +2 -1
- data/lib/capybara/spec/session/accept_prompt_spec.rb +2 -1
- data/lib/capybara/spec/session/all_spec.rb +1 -0
- data/lib/capybara/spec/session/assert_current_path.rb +1 -0
- data/lib/capybara/spec/session/assert_selector.rb +1 -0
- data/lib/capybara/spec/session/assert_text.rb +1 -0
- data/lib/capybara/spec/session/assert_title.rb +1 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +1 -0
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +1 -0
- data/lib/capybara/spec/session/choose_spec.rb +1 -0
- data/lib/capybara/spec/session/click_button_spec.rb +1 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +1 -0
- data/lib/capybara/spec/session/click_link_spec.rb +1 -0
- data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
- data/lib/capybara/spec/session/current_url_spec.rb +1 -0
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +2 -1
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -1
- data/lib/capybara/spec/session/element/assert_match_selector.rb +31 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +17 -0
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +63 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +1 -0
- data/lib/capybara/spec/session/execute_script_spec.rb +1 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +1 -0
- data/lib/capybara/spec/session/find_button_spec.rb +1 -0
- data/lib/capybara/spec/session/find_by_id_spec.rb +1 -0
- data/lib/capybara/spec/session/find_field_spec.rb +1 -0
- data/lib/capybara/spec/session/find_link_spec.rb +1 -0
- data/lib/capybara/spec/session/find_spec.rb +1 -0
- data/lib/capybara/spec/session/first_spec.rb +1 -0
- data/lib/capybara/spec/session/go_back_spec.rb +1 -0
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
- data/lib/capybara/spec/session/has_button_spec.rb +1 -0
- data/lib/capybara/spec/session/has_css_spec.rb +1 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +1 -0
- data/lib/capybara/spec/session/has_field_spec.rb +13 -0
- data/lib/capybara/spec/session/has_link_spec.rb +1 -0
- data/lib/capybara/spec/session/has_select_spec.rb +19 -0
- data/lib/capybara/spec/session/has_selector_spec.rb +6 -0
- data/lib/capybara/spec/session/has_table_spec.rb +1 -0
- data/lib/capybara/spec/session/has_text_spec.rb +1 -0
- data/lib/capybara/spec/session/has_title_spec.rb +1 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
- data/lib/capybara/spec/session/headers.rb +1 -0
- data/lib/capybara/spec/session/html_spec.rb +1 -0
- data/lib/capybara/spec/session/node_spec.rb +29 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +35 -1
- data/lib/capybara/spec/session/response_code.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +3 -2
- 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 +3 -1
- data/lib/capybara/spec/session/select_spec.rb +1 -0
- data/lib/capybara/spec/session/selectors_spec.rb +35 -0
- data/lib/capybara/spec/session/text_spec.rb +1 -0
- data/lib/capybara/spec/session/title_spec.rb +2 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +1 -0
- data/lib/capybara/spec/session/unselect_spec.rb +1 -0
- data/lib/capybara/spec/session/visit_spec.rb +1 -0
- data/lib/capybara/spec/session/window/become_closed_spec.rb +1 -0
- 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 +1 -0
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -0
- data/lib/capybara/spec/session/window/window_spec.rb +1 -8
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +2 -3
- data/lib/capybara/spec/session/within_frame_spec.rb +1 -0
- data/lib/capybara/spec/session/within_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +2 -0
- data/lib/capybara/spec/test_app.rb +1 -0
- 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 +24 -0
- data/lib/capybara/spec/views/frame_child.erb +2 -1
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +2 -1
- 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/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_hover.erb +2 -1
- data/lib/capybara/spec/views/with_html.erb +3 -0
- data/lib/capybara/spec/views/with_html_entities.erb +1 -0
- data/lib/capybara/spec/views/with_js.erb +5 -0
- 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 +12 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -0
- data/lib/capybara/spec/views/within_frames.erb +2 -1
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +1 -0
- data/lib/capybara.rb +86 -10
- data/spec/basic_node_spec.rb +1 -0
- data/spec/capybara_spec.rb +28 -1
- data/spec/dsl_spec.rb +1 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -0
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -0
- data/spec/rack_test_spec.rb +1 -0
- data/spec/result_spec.rb +1 -0
- data/spec/rspec/features_spec.rb +1 -0
- data/spec/rspec/matchers_spec.rb +1 -0
- data/spec/rspec/scenarios_spec.rb +1 -0
- data/spec/rspec/views_spec.rb +1 -0
- data/spec/rspec_spec.rb +1 -0
- data/spec/selector_spec.rb +55 -1
- data/spec/selenium_spec.rb +6 -2
- data/spec/selenium_spec_chrome.rb +1 -0
- data/spec/server_spec.rb +101 -13
- data/spec/spec_helper.rb +1 -0
- metadata +16 -6
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
module Matchers
|
|
@@ -55,6 +56,36 @@ module Capybara
|
|
|
55
56
|
return false
|
|
56
57
|
end
|
|
57
58
|
|
|
59
|
+
##
|
|
60
|
+
#
|
|
61
|
+
# Checks if the current node matches given selector
|
|
62
|
+
# Usage is identical to Capybara::Node::Matchers#has_selector?
|
|
63
|
+
#
|
|
64
|
+
# @param (see Capybara::Node::Finders#has_selector?)
|
|
65
|
+
# @return [Boolean]
|
|
66
|
+
#
|
|
67
|
+
def matches_selector?(*args)
|
|
68
|
+
assert_matches_selector(*args)
|
|
69
|
+
rescue Capybara::ExpectationNotMet
|
|
70
|
+
return false
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
#
|
|
76
|
+
# Checks if the current node does not match given selector
|
|
77
|
+
# Usage is identical to Capybara::Node::Matchers#has_selector?
|
|
78
|
+
#
|
|
79
|
+
# @param (see Capybara::Node::Finders#has_selector?)
|
|
80
|
+
# @return [Boolean]
|
|
81
|
+
#
|
|
82
|
+
def not_matches_selector?(*args)
|
|
83
|
+
assert_not_matches_selector(*args)
|
|
84
|
+
rescue Capybara::ExpectationNotMet
|
|
85
|
+
return false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
58
89
|
##
|
|
59
90
|
#
|
|
60
91
|
# Asserts that a given selector is on the page or current node.
|
|
@@ -89,7 +120,7 @@ module Capybara
|
|
|
89
120
|
# @raise [Capybara::ExpectationNotMet] If the selector does not exist
|
|
90
121
|
#
|
|
91
122
|
def assert_selector(*args)
|
|
92
|
-
query = Capybara::
|
|
123
|
+
query = Capybara::Queries::SelectorQuery.new(*args)
|
|
93
124
|
synchronize(query.wait) do
|
|
94
125
|
result = query.resolve_for(self)
|
|
95
126
|
matches_count = Capybara::Helpers.matches_count?(result.size, query.options)
|
|
@@ -117,7 +148,7 @@ module Capybara
|
|
|
117
148
|
# @raise [Capybara::ExpectationNotMet] If the selector exists
|
|
118
149
|
#
|
|
119
150
|
def assert_no_selector(*args)
|
|
120
|
-
query = Capybara::
|
|
151
|
+
query = Capybara::Queries::SelectorQuery.new(*args)
|
|
121
152
|
synchronize(query.wait) do
|
|
122
153
|
result = query.resolve_for(self)
|
|
123
154
|
matches_count = Capybara::Helpers.matches_count?(result.size, query.options)
|
|
@@ -129,6 +160,45 @@ module Capybara
|
|
|
129
160
|
end
|
|
130
161
|
alias_method :refute_selector, :assert_no_selector
|
|
131
162
|
|
|
163
|
+
##
|
|
164
|
+
#
|
|
165
|
+
# Asserts that the current_node matches a given selector
|
|
166
|
+
#
|
|
167
|
+
# node.assert_matches_selector('p#foo')
|
|
168
|
+
# node.assert_matches_selector(:xpath, '//p[@id="foo"]')
|
|
169
|
+
# node.assert_matches_selector(:foo)
|
|
170
|
+
#
|
|
171
|
+
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
|
|
172
|
+
# such as :text and :visible.
|
|
173
|
+
#
|
|
174
|
+
# node.assert_matches_selector('li', :text => 'Horse', :visible => true)
|
|
175
|
+
#
|
|
176
|
+
# @param (see Capybara::Node::Finders#all)
|
|
177
|
+
# @raise [Capybara::ExpectationNotMet] If the selector does not match
|
|
178
|
+
#
|
|
179
|
+
def assert_matches_selector(*args)
|
|
180
|
+
query = Capybara::Queries::MatchQuery.new(*args)
|
|
181
|
+
synchronize(query.wait) do
|
|
182
|
+
result = query.resolve_for(self.parent)
|
|
183
|
+
unless result.include? self
|
|
184
|
+
raise Capybara::ExpectationNotMet, "Item does not match the provided selector"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
return true
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def assert_not_matches_selector(*args)
|
|
191
|
+
query = Capybara::Queries::MatchQuery.new(*args)
|
|
192
|
+
synchronize(query.wait) do
|
|
193
|
+
result = query.resolve_for(self.parent)
|
|
194
|
+
if result.include? self
|
|
195
|
+
raise Capybara::ExpectationNotMet, 'Item matched the provided selector'
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
return true
|
|
199
|
+
end
|
|
200
|
+
alias_method :refute_matches_selector, :assert_not_matches_selector
|
|
201
|
+
|
|
132
202
|
##
|
|
133
203
|
#
|
|
134
204
|
# Checks if a given XPath expression is on the page or current node.
|
data/lib/capybara/node/simple.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
|
|
@@ -99,6 +100,8 @@ module Capybara
|
|
|
99
100
|
# @return [Boolean] Whether the element is visible
|
|
100
101
|
#
|
|
101
102
|
def visible?(check_ancestors = true)
|
|
103
|
+
return false if (tag_name == 'input') && (native[:type]=="hidden")
|
|
104
|
+
|
|
102
105
|
if check_ancestors
|
|
103
106
|
#check size because oldest supported nokogiri doesnt support xpath boolean() function
|
|
104
107
|
native.xpath("./ancestor-or-self::*[contains(@style, 'display:none') or contains(@style, 'display: none') or @hidden or name()='script' or name()='head']").size() == 0
|
|
@@ -115,7 +118,7 @@ module Capybara
|
|
|
115
118
|
# @return [Boolean] Whether the element is checked
|
|
116
119
|
#
|
|
117
120
|
def checked?
|
|
118
|
-
native
|
|
121
|
+
native.has_attribute?('checked')
|
|
119
122
|
end
|
|
120
123
|
|
|
121
124
|
##
|
|
@@ -124,7 +127,7 @@ module Capybara
|
|
|
124
127
|
#
|
|
125
128
|
# @return [Boolean] Whether the element is disabled
|
|
126
129
|
def disabled?
|
|
127
|
-
native
|
|
130
|
+
native.has_attribute?('disabled')
|
|
128
131
|
end
|
|
129
132
|
|
|
130
133
|
##
|
|
@@ -134,7 +137,7 @@ module Capybara
|
|
|
134
137
|
# @return [Boolean] Whether the element is selected
|
|
135
138
|
#
|
|
136
139
|
def selected?
|
|
137
|
-
native
|
|
140
|
+
native.has_attribute?('selected')
|
|
138
141
|
end
|
|
139
142
|
|
|
140
143
|
def synchronize(seconds=nil)
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'addressable/uri'
|
|
3
|
+
|
|
1
4
|
module Capybara
|
|
2
5
|
# @api private
|
|
3
6
|
module Queries
|
|
@@ -15,16 +18,16 @@ module Capybara
|
|
|
15
18
|
session.current_url
|
|
16
19
|
else
|
|
17
20
|
if options[:only_path]
|
|
18
|
-
Addressable::URI.parse(session.current_url).path
|
|
21
|
+
::Addressable::URI.parse(session.current_url).path
|
|
19
22
|
else
|
|
20
|
-
Addressable::URI.parse(session.current_url).request_uri
|
|
23
|
+
::Addressable::URI.parse(session.current_url).request_uri
|
|
21
24
|
end
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
if @expected_path.is_a? Regexp
|
|
25
28
|
@actual_path.match(@expected_path)
|
|
26
29
|
else
|
|
27
|
-
Addressable::URI.parse(@expected_path) == Addressable::URI.parse(@actual_path)
|
|
30
|
+
::Addressable::URI.parse(@expected_path) == Addressable::URI.parse(@actual_path)
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Capybara
|
|
2
|
+
module Queries
|
|
3
|
+
class MatchQuery < Capybara::Queries::SelectorQuery
|
|
4
|
+
VALID_KEYS = [:text, :visible, :exact, :wait]
|
|
5
|
+
|
|
6
|
+
def visible
|
|
7
|
+
if options.has_key?(:visible)
|
|
8
|
+
super
|
|
9
|
+
else
|
|
10
|
+
:all
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def valid_keys
|
|
17
|
+
VALID_KEYS + @selector.custom_filters.keys
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Capybara
|
|
3
|
+
module Queries
|
|
4
|
+
class SelectorQuery < Queries::BaseQuery
|
|
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.shift]
|
|
15
|
+
@locator = args.shift
|
|
16
|
+
else
|
|
17
|
+
@selector = Selector.all.values.find { |s| s.match?(args[0]) }
|
|
18
|
+
@locator = args.shift
|
|
19
|
+
end
|
|
20
|
+
@selector ||= Selector.all[Capybara.default_selector]
|
|
21
|
+
|
|
22
|
+
warn "Unused parameters passed to #{self.class.name} : #{args.to_s}" unless args.empty?
|
|
23
|
+
|
|
24
|
+
# for compatibility with Capybara 2.0
|
|
25
|
+
if Capybara.exact_options and @selector == Selector.all[:option]
|
|
26
|
+
@options[:exact] = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@expression = @selector.call(@locator)
|
|
30
|
+
assert_valid_keys
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def name; selector.name; end
|
|
34
|
+
def label; selector.label or selector.name; end
|
|
35
|
+
|
|
36
|
+
def description
|
|
37
|
+
@description = String.new("#{label} #{locator.inspect}")
|
|
38
|
+
@description << " with text #{options[:text].inspect}" if options[:text]
|
|
39
|
+
@description << selector.description(options)
|
|
40
|
+
@description
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def matches_filters?(node)
|
|
44
|
+
if options[:text]
|
|
45
|
+
regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
|
|
46
|
+
return false if not node.text(visible).match(regexp)
|
|
47
|
+
end
|
|
48
|
+
case visible
|
|
49
|
+
when :visible then return false unless node.visible?
|
|
50
|
+
when :hidden then return false if node.visible?
|
|
51
|
+
end
|
|
52
|
+
selector.custom_filters.each do |name, filter|
|
|
53
|
+
if options.has_key?(name)
|
|
54
|
+
return false unless filter.matches?(node, options[name])
|
|
55
|
+
elsif filter.default?
|
|
56
|
+
return false unless filter.matches?(node, filter.default)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def visible
|
|
62
|
+
if options.has_key?(:visible)
|
|
63
|
+
case @options[:visible]
|
|
64
|
+
when true then :visible
|
|
65
|
+
when false then :all
|
|
66
|
+
else @options[:visible]
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
if Capybara.ignore_hidden_elements
|
|
70
|
+
:visible
|
|
71
|
+
else
|
|
72
|
+
:all
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def exact?
|
|
78
|
+
if options.has_key?(:exact)
|
|
79
|
+
@options[:exact]
|
|
80
|
+
else
|
|
81
|
+
Capybara.exact
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def match
|
|
86
|
+
if options.has_key?(:match)
|
|
87
|
+
@options[:match]
|
|
88
|
+
else
|
|
89
|
+
Capybara.match
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def xpath(exact=nil)
|
|
94
|
+
exact = self.exact? if exact == nil
|
|
95
|
+
if @expression.respond_to?(:to_xpath) and exact
|
|
96
|
+
@expression.to_xpath(:exact)
|
|
97
|
+
else
|
|
98
|
+
@expression.to_s
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def css
|
|
103
|
+
@expression
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @api private
|
|
107
|
+
def resolve_for(node, exact = nil)
|
|
108
|
+
node.synchronize do
|
|
109
|
+
children = if selector.format == :css
|
|
110
|
+
node.find_css(self.css)
|
|
111
|
+
else
|
|
112
|
+
node.find_xpath(self.xpath(exact))
|
|
113
|
+
end.map do |child|
|
|
114
|
+
if node.is_a?(Capybara::Node::Base)
|
|
115
|
+
Capybara::Node::Element.new(node.session, child, node, self)
|
|
116
|
+
else
|
|
117
|
+
Capybara::Node::Simple.new(child)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
Capybara::Result.new(children, self)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
def valid_keys
|
|
127
|
+
COUNT_KEYS + [:text, :visible, :exact, :match, :wait] + @selector.custom_filters.keys
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def assert_valid_keys
|
|
131
|
+
super
|
|
132
|
+
unless VALID_MATCH.include?(match)
|
|
133
|
+
raise ArgumentError, "invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(", ")}"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
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
|
require 'rack/test'
|
|
2
3
|
require 'rack/utils'
|
|
3
4
|
require 'mime/types'
|
|
@@ -65,11 +66,11 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
65
66
|
def find_xpath(selector)
|
|
66
67
|
browser.find(:xpath, selector)
|
|
67
68
|
end
|
|
68
|
-
|
|
69
|
+
|
|
69
70
|
def find_css(selector)
|
|
70
71
|
browser.find(:css,selector)
|
|
71
72
|
end
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
def html
|
|
74
75
|
browser.html
|
|
75
76
|
end
|
|
@@ -77,7 +78,7 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
77
78
|
def dom
|
|
78
79
|
browser.dom
|
|
79
80
|
end
|
|
80
|
-
|
|
81
|
+
|
|
81
82
|
def title
|
|
82
83
|
browser.title
|
|
83
84
|
end
|
|
@@ -86,8 +87,9 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
|
86
87
|
@browser = nil
|
|
87
88
|
end
|
|
88
89
|
|
|
90
|
+
# @deprecated This method is being removed
|
|
89
91
|
def browser_initialized?
|
|
90
|
-
!@browser.nil?
|
|
92
|
+
super && !@browser.nil?
|
|
91
93
|
end
|
|
92
94
|
|
|
93
95
|
def get(*args, &block); browser.get(*args, &block); end
|
data/lib/capybara/rails.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'capybara/dsl'
|
|
2
3
|
|
|
3
4
|
Capybara.app = Rack::Builder.new do
|
|
@@ -11,7 +12,7 @@ Capybara.app = Rack::Builder.new do
|
|
|
11
12
|
end
|
|
12
13
|
end.to_app
|
|
13
14
|
|
|
14
|
-
Capybara.
|
|
15
|
+
Capybara.save_path = Rails.root.join('tmp/capybara')
|
|
15
16
|
|
|
16
17
|
# Override default rack_test driver to respect data-method attributes.
|
|
17
18
|
Capybara.register_driver :rack_test do |app|
|
data/lib/capybara/result.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module RSpecMatchers
|
|
3
4
|
class Matcher
|
|
4
|
-
include ::RSpec::Matchers::Composable if defined?(::RSpec::Expectations::Version) && RSpec::Expectations::Version::STRING
|
|
5
|
+
include ::RSpec::Matchers::Composable if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.0'))
|
|
5
6
|
|
|
6
7
|
def wrap(actual)
|
|
7
8
|
if actual.respond_to?("has_selector?")
|
|
@@ -38,7 +39,7 @@ module Capybara
|
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
def query
|
|
41
|
-
@query ||= Capybara::
|
|
42
|
+
@query ||= Capybara::Queries::SelectorQuery.new(*@args)
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
# RSpec 2 compatibility:
|
|
@@ -160,7 +161,7 @@ module Capybara
|
|
|
160
161
|
|
|
161
162
|
class BecomeClosed
|
|
162
163
|
def initialize(options)
|
|
163
|
-
@wait_time = Capybara::
|
|
164
|
+
@wait_time = Capybara::Queries::SelectorQuery.new(options).wait
|
|
164
165
|
end
|
|
165
166
|
|
|
166
167
|
def matches?(window)
|
|
@@ -186,18 +187,68 @@ module Capybara
|
|
|
186
187
|
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
187
188
|
end
|
|
188
189
|
|
|
190
|
+
class MatchSelector < Matcher
|
|
191
|
+
attr_reader :failure_message, :failure_message_when_negated
|
|
192
|
+
|
|
193
|
+
def initialize(*args)
|
|
194
|
+
@args = args
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def matches?(actual)
|
|
198
|
+
actual.assert_matches_selector(*@args)
|
|
199
|
+
rescue Capybara::ExpectationNotMet => e
|
|
200
|
+
@failure_message = e.message
|
|
201
|
+
return false
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def does_not_match?(actual)
|
|
205
|
+
actual.assert_not_matches_selector(*@args)
|
|
206
|
+
rescue Capybara::ExpectationNotMet => e
|
|
207
|
+
@failure_message_when_negated = e.message
|
|
208
|
+
return false
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def description
|
|
212
|
+
"match #{query.description}"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def query
|
|
216
|
+
@query ||= Capybara::Queries::MatchQuery.new(*@args)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# RSpec 2 compatibility:
|
|
220
|
+
alias_method :failure_message_for_should, :failure_message
|
|
221
|
+
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
222
|
+
end
|
|
223
|
+
|
|
189
224
|
def have_selector(*args)
|
|
190
225
|
HaveSelector.new(*args)
|
|
191
226
|
end
|
|
192
227
|
|
|
228
|
+
def match_selector(*args)
|
|
229
|
+
MatchSelector.new(*args)
|
|
230
|
+
end
|
|
231
|
+
# defined_negated_matcher was added in RSpec 3.1 - it's syntactic sugar only since a user can do
|
|
232
|
+
# expect(page).not_to match_selector, so not sure we really need to support not_match_selector for prior to RSpec 3.1
|
|
233
|
+
::RSpec::Matchers.define_negated_matcher :not_match_selector, :match_selector if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.1'))
|
|
234
|
+
|
|
235
|
+
|
|
193
236
|
def have_xpath(xpath, options={})
|
|
194
237
|
HaveSelector.new(:xpath, xpath, options)
|
|
195
238
|
end
|
|
196
239
|
|
|
240
|
+
def match_xpath(xpath, options={})
|
|
241
|
+
MatchSelector.new(:xpath, xpath, options)
|
|
242
|
+
end
|
|
243
|
+
|
|
197
244
|
def have_css(css, options={})
|
|
198
245
|
HaveSelector.new(:css, css, options)
|
|
199
246
|
end
|
|
200
247
|
|
|
248
|
+
def match_css(css, options={})
|
|
249
|
+
MatchSelector.new(:css, css, options)
|
|
250
|
+
end
|
|
251
|
+
|
|
201
252
|
def have_text(*args)
|
|
202
253
|
HaveText.new(*args)
|
|
203
254
|
end
|
data/lib/capybara/rspec.rb
CHANGED