capybara 2.6.2 → 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 +40 -15
- data/README.md +45 -38
- data/lib/capybara.rb +86 -10
- 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 +1 -0
- 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.rb +1 -0
- data/lib/capybara/rspec/features.rb +1 -0
- data/lib/capybara/rspec/matchers.rb +54 -3
- data/lib/capybara/selector.rb +175 -75
- data/lib/capybara/selector/filter.rb +48 -0
- 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.rb +30 -14
- data/lib/capybara/session/matchers.rb +2 -1
- 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/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
data/lib/capybara/cucumber.rb
CHANGED
data/lib/capybara/driver/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Capybara::Driver::Base
|
2
3
|
def current_url
|
3
4
|
raise NotImplementedError
|
@@ -90,8 +91,8 @@ class Capybara::Driver::Base
|
|
90
91
|
def no_such_window_error
|
91
92
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#no_such_window_error'
|
92
93
|
end
|
93
|
-
|
94
|
-
|
94
|
+
|
95
|
+
|
95
96
|
##
|
96
97
|
#
|
97
98
|
# Execute the block, and then accept the modal opened.
|
@@ -134,7 +135,9 @@ class Capybara::Driver::Base
|
|
134
135
|
false
|
135
136
|
end
|
136
137
|
|
138
|
+
# @deprecated This method is being removed
|
137
139
|
def browser_initialized?
|
140
|
+
warn "DEPRECATED: #browser_initialized? is deprecated and will be removed in the next version of Capybara"
|
138
141
|
true
|
139
142
|
end
|
140
143
|
end
|
data/lib/capybara/driver/node.rb
CHANGED
data/lib/capybara/dsl.rb
CHANGED
data/lib/capybara/helpers.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Capybara
|
4
5
|
|
@@ -96,7 +97,7 @@ module Capybara
|
|
96
97
|
# @option [Integer] minimum Count should have been larger than or equal to this value
|
97
98
|
#
|
98
99
|
def failure_message(description, options={})
|
99
|
-
message = "expected to find #{description}"
|
100
|
+
message = String.new("expected to find #{description}")
|
100
101
|
if options[:count]
|
101
102
|
message << " #{options[:count]} #{declension('time', 'times', options[:count])}"
|
102
103
|
elsif options[:between]
|
@@ -129,7 +130,7 @@ module Capybara
|
|
129
130
|
|
130
131
|
if defined?(Process::CLOCK_MONOTONIC)
|
131
132
|
def monotonic_time
|
132
|
-
|
133
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
133
134
|
end
|
134
135
|
else
|
135
136
|
def monotonic_time
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Capybara
|
2
3
|
module Node
|
3
4
|
module Actions
|
@@ -150,6 +151,11 @@ module Capybara
|
|
150
151
|
# @param [String] locator Which field to attach the file to
|
151
152
|
# @param [String] path The path of the file that will be attached, or an array of paths
|
152
153
|
#
|
154
|
+
# @option options [Symbol] match (Capybara.match) The matching strategy to use (:one, :first, :prefer_exact, :smart).
|
155
|
+
# @option options [Boolean] exact (Capybara.exact) Match the exact label name/contents or accept a partial match.
|
156
|
+
# @option options [Fixnum] wait (Capybara.default_max_wait_time) If using a Javascript driver, maximum number of seconds during which the element will be searched for.
|
157
|
+
# @option options [Boolean] multiple Match field which allows multiple file selection
|
158
|
+
#
|
153
159
|
def attach_file(locator, path, options={})
|
154
160
|
Array(path).each do |p|
|
155
161
|
raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s)
|
data/lib/capybara/node/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Capybara
|
2
3
|
module Node
|
3
4
|
module Finders
|
@@ -28,7 +29,7 @@ module Capybara
|
|
28
29
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
29
30
|
#
|
30
31
|
def find(*args)
|
31
|
-
query = Capybara::
|
32
|
+
query = Capybara::Queries::SelectorQuery.new(*args)
|
32
33
|
synchronize(query.wait) do
|
33
34
|
if query.match == :smart or query.match == :prefer_exact
|
34
35
|
result = query.resolve_for(self, true)
|
@@ -177,7 +178,7 @@ module Capybara
|
|
177
178
|
# @return [Capybara::Result] A collection of found elements
|
178
179
|
#
|
179
180
|
def all(*args)
|
180
|
-
query = Capybara::
|
181
|
+
query = Capybara::Queries::SelectorQuery.new(*args)
|
181
182
|
synchronize(query.wait) do
|
182
183
|
result = query.resolve_for(self)
|
183
184
|
raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count?
|
@@ -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)
|
@@ -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
|