capybara 2.6.1 → 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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +47 -16
  3. data/README.md +45 -38
  4. data/lib/capybara/cucumber.rb +1 -0
  5. data/lib/capybara/driver/base.rb +5 -2
  6. data/lib/capybara/driver/node.rb +1 -0
  7. data/lib/capybara/dsl.rb +1 -0
  8. data/lib/capybara/helpers.rb +3 -2
  9. data/lib/capybara/node/actions.rb +6 -0
  10. data/lib/capybara/node/base.rb +1 -0
  11. data/lib/capybara/node/document.rb +1 -0
  12. data/lib/capybara/node/document_matchers.rb +1 -0
  13. data/lib/capybara/node/element.rb +1 -0
  14. data/lib/capybara/node/finders.rb +3 -2
  15. data/lib/capybara/node/matchers.rb +72 -2
  16. data/lib/capybara/node/simple.rb +6 -3
  17. data/lib/capybara/queries/base_query.rb +1 -0
  18. data/lib/capybara/queries/current_path_query.rb +5 -4
  19. data/lib/capybara/queries/match_query.rb +21 -0
  20. data/lib/capybara/queries/selector_query.rb +138 -0
  21. data/lib/capybara/queries/text_query.rb +1 -0
  22. data/lib/capybara/queries/title_query.rb +1 -0
  23. data/lib/capybara/query.rb +3 -131
  24. data/lib/capybara/rack_test/browser.rb +1 -0
  25. data/lib/capybara/rack_test/css_handlers.rb +1 -0
  26. data/lib/capybara/rack_test/driver.rb +6 -4
  27. data/lib/capybara/rack_test/form.rb +1 -0
  28. data/lib/capybara/rack_test/node.rb +1 -0
  29. data/lib/capybara/rails.rb +2 -1
  30. data/lib/capybara/result.rb +1 -0
  31. data/lib/capybara/rspec/features.rb +1 -0
  32. data/lib/capybara/rspec/matchers.rb +54 -3
  33. data/lib/capybara/rspec.rb +1 -0
  34. data/lib/capybara/selector/filter.rb +48 -0
  35. data/lib/capybara/selector.rb +175 -75
  36. data/lib/capybara/selenium/driver.rb +24 -7
  37. data/lib/capybara/selenium/node.rb +1 -0
  38. data/lib/capybara/server.rb +38 -6
  39. data/lib/capybara/session/matchers.rb +2 -1
  40. data/lib/capybara/session.rb +30 -14
  41. data/lib/capybara/spec/public/test.js +6 -0
  42. data/lib/capybara/spec/session/accept_alert_spec.rb +2 -1
  43. data/lib/capybara/spec/session/accept_confirm_spec.rb +2 -1
  44. data/lib/capybara/spec/session/accept_prompt_spec.rb +2 -1
  45. data/lib/capybara/spec/session/all_spec.rb +1 -0
  46. data/lib/capybara/spec/session/assert_current_path.rb +1 -0
  47. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  48. data/lib/capybara/spec/session/assert_text.rb +1 -0
  49. data/lib/capybara/spec/session/assert_title.rb +1 -0
  50. data/lib/capybara/spec/session/attach_file_spec.rb +1 -0
  51. data/lib/capybara/spec/session/body_spec.rb +1 -0
  52. data/lib/capybara/spec/session/check_spec.rb +1 -0
  53. data/lib/capybara/spec/session/choose_spec.rb +1 -0
  54. data/lib/capybara/spec/session/click_button_spec.rb +1 -0
  55. data/lib/capybara/spec/session/click_link_or_button_spec.rb +1 -0
  56. data/lib/capybara/spec/session/click_link_spec.rb +1 -0
  57. data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
  58. data/lib/capybara/spec/session/current_url_spec.rb +1 -0
  59. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +2 -1
  60. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -1
  61. data/lib/capybara/spec/session/element/assert_match_selector.rb +31 -0
  62. data/lib/capybara/spec/session/element/match_css_spec.rb +17 -0
  63. data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
  64. data/lib/capybara/spec/session/element/matches_selector_spec.rb +63 -0
  65. data/lib/capybara/spec/session/evaluate_script_spec.rb +1 -0
  66. data/lib/capybara/spec/session/execute_script_spec.rb +1 -0
  67. data/lib/capybara/spec/session/fill_in_spec.rb +1 -0
  68. data/lib/capybara/spec/session/find_button_spec.rb +1 -0
  69. data/lib/capybara/spec/session/find_by_id_spec.rb +1 -0
  70. data/lib/capybara/spec/session/find_field_spec.rb +1 -0
  71. data/lib/capybara/spec/session/find_link_spec.rb +1 -0
  72. data/lib/capybara/spec/session/find_spec.rb +1 -0
  73. data/lib/capybara/spec/session/first_spec.rb +1 -0
  74. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  75. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  76. data/lib/capybara/spec/session/has_button_spec.rb +1 -0
  77. data/lib/capybara/spec/session/has_css_spec.rb +1 -0
  78. data/lib/capybara/spec/session/has_current_path_spec.rb +1 -0
  79. data/lib/capybara/spec/session/has_field_spec.rb +13 -0
  80. data/lib/capybara/spec/session/has_link_spec.rb +1 -0
  81. data/lib/capybara/spec/session/has_select_spec.rb +19 -0
  82. data/lib/capybara/spec/session/has_selector_spec.rb +6 -0
  83. data/lib/capybara/spec/session/has_table_spec.rb +1 -0
  84. data/lib/capybara/spec/session/has_text_spec.rb +1 -0
  85. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  86. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  87. data/lib/capybara/spec/session/headers.rb +1 -0
  88. data/lib/capybara/spec/session/html_spec.rb +1 -0
  89. data/lib/capybara/spec/session/node_spec.rb +29 -0
  90. data/lib/capybara/spec/session/reset_session_spec.rb +35 -1
  91. data/lib/capybara/spec/session/response_code.rb +1 -0
  92. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  93. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +3 -2
  94. data/lib/capybara/spec/session/save_page_spec.rb +34 -2
  95. data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
  96. data/lib/capybara/spec/session/screenshot_spec.rb +3 -1
  97. data/lib/capybara/spec/session/select_spec.rb +1 -0
  98. data/lib/capybara/spec/session/selectors_spec.rb +35 -0
  99. data/lib/capybara/spec/session/text_spec.rb +1 -0
  100. data/lib/capybara/spec/session/title_spec.rb +2 -1
  101. data/lib/capybara/spec/session/uncheck_spec.rb +1 -0
  102. data/lib/capybara/spec/session/unselect_spec.rb +1 -0
  103. data/lib/capybara/spec/session/visit_spec.rb +1 -0
  104. data/lib/capybara/spec/session/window/become_closed_spec.rb +1 -0
  105. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  106. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  107. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -0
  108. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -0
  109. data/lib/capybara/spec/session/window/window_spec.rb +1 -8
  110. data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
  111. data/lib/capybara/spec/session/window/within_window_spec.rb +2 -3
  112. data/lib/capybara/spec/session/within_frame_spec.rb +1 -0
  113. data/lib/capybara/spec/session/within_spec.rb +1 -0
  114. data/lib/capybara/spec/spec_helper.rb +2 -0
  115. data/lib/capybara/spec/test_app.rb +1 -0
  116. data/lib/capybara/spec/views/buttons.erb +1 -0
  117. data/lib/capybara/spec/views/fieldsets.erb +2 -1
  118. data/lib/capybara/spec/views/form.erb +24 -0
  119. data/lib/capybara/spec/views/frame_child.erb +2 -1
  120. data/lib/capybara/spec/views/frame_one.erb +2 -1
  121. data/lib/capybara/spec/views/frame_parent.erb +2 -1
  122. data/lib/capybara/spec/views/frame_two.erb +2 -1
  123. data/lib/capybara/spec/views/header_links.erb +1 -0
  124. data/lib/capybara/spec/views/host_links.erb +1 -0
  125. data/lib/capybara/spec/views/path.erb +1 -0
  126. data/lib/capybara/spec/views/popup_one.erb +1 -0
  127. data/lib/capybara/spec/views/popup_two.erb +1 -0
  128. data/lib/capybara/spec/views/postback.erb +2 -1
  129. data/lib/capybara/spec/views/tables.erb +1 -0
  130. data/lib/capybara/spec/views/with_base_tag.erb +1 -0
  131. data/lib/capybara/spec/views/with_count.erb +2 -1
  132. data/lib/capybara/spec/views/with_hover.erb +2 -1
  133. data/lib/capybara/spec/views/with_html.erb +3 -0
  134. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  135. data/lib/capybara/spec/views/with_js.erb +5 -0
  136. data/lib/capybara/spec/views/with_scope.erb +1 -0
  137. data/lib/capybara/spec/views/with_simple_html.erb +2 -1
  138. data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
  139. data/lib/capybara/spec/views/with_title.erb +2 -1
  140. data/lib/capybara/spec/views/with_unload_alert.erb +12 -0
  141. data/lib/capybara/spec/views/with_windows.erb +1 -0
  142. data/lib/capybara/spec/views/within_frames.erb +2 -1
  143. data/lib/capybara/version.rb +2 -1
  144. data/lib/capybara/window.rb +1 -0
  145. data/lib/capybara.rb +86 -10
  146. data/spec/basic_node_spec.rb +1 -0
  147. data/spec/capybara_spec.rb +28 -1
  148. data/spec/dsl_spec.rb +1 -0
  149. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -0
  150. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -0
  151. data/spec/rack_test_spec.rb +1 -0
  152. data/spec/result_spec.rb +1 -0
  153. data/spec/rspec/features_spec.rb +1 -0
  154. data/spec/rspec/matchers_spec.rb +1 -0
  155. data/spec/rspec/scenarios_spec.rb +1 -0
  156. data/spec/rspec/views_spec.rb +1 -0
  157. data/spec/rspec_spec.rb +1 -0
  158. data/spec/selector_spec.rb +55 -1
  159. data/spec/selenium_spec.rb +6 -2
  160. data/spec/selenium_spec_chrome.rb +1 -0
  161. data/spec/server_spec.rb +101 -13
  162. data/spec/spec_helper.rb +1 -0
  163. 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::Query.new(*args)
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::Query.new(*args)
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.
@@ -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[:checked]
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[:disabled]
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[:selected]
140
+ native.has_attribute?('selected')
138
141
  end
139
142
 
140
143
  def synchronize(seconds=nil)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Capybara
2
3
  # @api private
3
4
  module Queries
@@ -1,4 +1,5 @@
1
- require 'addressable'
1
+ # frozen_string_literal: true
2
+ require 'addressable/uri'
2
3
 
3
4
  module Capybara
4
5
  # @api private
@@ -17,16 +18,16 @@ module Capybara
17
18
  session.current_url
18
19
  else
19
20
  if options[:only_path]
20
- Addressable::URI.parse(session.current_url).path
21
+ ::Addressable::URI.parse(session.current_url).path
21
22
  else
22
- Addressable::URI.parse(session.current_url).request_uri
23
+ ::Addressable::URI.parse(session.current_url).request_uri
23
24
  end
24
25
  end
25
26
 
26
27
  if @expected_path.is_a? Regexp
27
28
  @actual_path.match(@expected_path)
28
29
  else
29
- Addressable::URI.parse(@expected_path) == Addressable::URI.parse(@actual_path)
30
+ ::Addressable::URI.parse(@expected_path) == Addressable::URI.parse(@actual_path)
30
31
  end
31
32
  end
32
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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Capybara
2
3
  # @api private
3
4
  module Queries
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Capybara
2
3
  # @api private
3
4
  module Queries
@@ -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
- class Query < 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[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
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Capybara::RackTest::CSSHandlers < BasicObject
2
3
  include ::Kernel
3
4
 
@@ -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
@@ -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.
@@ -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)
@@ -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.save_and_open_page_path = Rails.root.join('tmp/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|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'forwardable'
2
3
 
3
4
  module Capybara
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  if RSpec::Core::Version::STRING.to_f >= 3.0
2
3
  RSpec.shared_context "Capybara Features", :capybara_feature => true do
3
4
  instance_eval do
@@ -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.to_f >= 3.0
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::Query.new(*@args)
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::Query.new(options).wait
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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'capybara/dsl'
2
3
  require 'rspec/core'
3
4
  require 'capybara/rspec/matchers'