mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Fixed that assert_select selects the wrong tag by its contents (closes #6332) [jgarber]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5240 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
717e26dd0e
commit
3c6b7a2191
2 changed files with 80 additions and 65 deletions
|
@ -8,6 +8,10 @@ require File.dirname(__FILE__) + "/../vendor/html-scanner/html/document"
|
||||||
|
|
||||||
module ActionController
|
module ActionController
|
||||||
module Assertions
|
module Assertions
|
||||||
|
unless const_defined?(:NO_STRIP)
|
||||||
|
NO_STRIP = %w{pre script style textarea}
|
||||||
|
end
|
||||||
|
|
||||||
# Adds the #assert_select method for use in Rails functional
|
# Adds the #assert_select method for use in Rails functional
|
||||||
# test cases.
|
# test cases.
|
||||||
#
|
#
|
||||||
|
@ -118,27 +122,28 @@ module ActionController
|
||||||
# === Equality Tests
|
# === Equality Tests
|
||||||
#
|
#
|
||||||
# The equality test may be one of the following:
|
# The equality test may be one of the following:
|
||||||
# * <tt>nil/true</tt> -- Assertion is true if at least one element is
|
# * <tt>true</tt> -- Assertion is true if at least one element selected.
|
||||||
# selected.
|
# * <tt>false</tt> -- Assertion is true if no element selected.
|
||||||
# * <tt>String</tt> -- Assertion is true if the text value of all
|
# * <tt>String/Regexp</tt> -- Assertion is true if the text value of at least
|
||||||
# selected elements equals to the string.
|
# one element matches the string or regular expression.
|
||||||
# * <tt>Regexp</tt> -- Assertion is true if the text value of all
|
|
||||||
# selected elements matches the regular expression.
|
|
||||||
# * <tt>false</tt> -- Assertion is true if no element is selected.
|
|
||||||
# * <tt>Integer</tt> -- Assertion is true if exactly that number of
|
# * <tt>Integer</tt> -- Assertion is true if exactly that number of
|
||||||
# elements are selected.
|
# elements are selected.
|
||||||
# * <tt>Range</tt> -- Assertion is true if the number of selected
|
# * <tt>Range</tt> -- Assertion is true if the number of selected
|
||||||
# elements fit the range.
|
# elements fit the range.
|
||||||
|
# If no equality test specified, the assertion is true if at least one
|
||||||
|
# element selected.
|
||||||
#
|
#
|
||||||
# To perform more than one equality tests, use a hash the following keys:
|
# To perform more than one equality tests, use a hash with the following keys:
|
||||||
# * <tt>:text</tt> -- Assertion is true if the text value of each
|
# * <tt>:text</tt> -- Narrow the selection to elements that have this text
|
||||||
# selected elements equals to the value (+String+ or +Regexp+).
|
# value (string or regexp).
|
||||||
# * <tt>:count</tt> -- Assertion is true if the number of matched elements
|
# * <tt>:html</tt> -- Narrow the selection to elements that have this HTML
|
||||||
# is equal to the value.
|
# content (string or regexp).
|
||||||
# * <tt>:minimum</tt> -- Assertion is true if the number of matched
|
# * <tt>:count</tt> -- Assertion is true if the number of selected elements
|
||||||
# elements is at least that value.
|
# is equal to this value.
|
||||||
# * <tt>:maximum</tt> -- Assertion is true if the number of matched
|
# * <tt>:minimum</tt> -- Assertion is true if the number of selected
|
||||||
# elements is at most that value.
|
# elements is at least this value.
|
||||||
|
# * <tt>:maximum</tt> -- Assertion is true if the number of selected
|
||||||
|
# elements is at most this value.
|
||||||
#
|
#
|
||||||
# If the method is called with a block, once all equality tests are
|
# If the method is called with a block, once all equality tests are
|
||||||
# evaluated the block is called with an array of all matched elements.
|
# evaluated the block is called with an array of all matched elements.
|
||||||
|
@ -224,15 +229,11 @@ module ActionController
|
||||||
else raise ArgumentError, "I don't understand what you're trying to match"
|
else raise ArgumentError, "I don't understand what you're trying to match"
|
||||||
end
|
end
|
||||||
|
|
||||||
# If we have a text test, by default we're looking for at least one match.
|
# By default we're looking for at least one match.
|
||||||
# Without this statement text tests pass even if nothing is selected.
|
|
||||||
# Can always override by specifying minimum or count.
|
|
||||||
if equals[:text]
|
|
||||||
equals[:minimum] ||= 1
|
|
||||||
end
|
|
||||||
# If a count is specified, it takes precedence over minimum/maximum.
|
|
||||||
if equals[:count]
|
if equals[:count]
|
||||||
equals[:minimum] = equals[:maximum] = equals.delete(:count)
|
equals[:minimum] = equals[:maximum] = equals[:count]
|
||||||
|
else
|
||||||
|
equals[:minimum] = 1 unless equals[:minimum]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Last argument is the message we use if the assertion fails.
|
# Last argument is the message we use if the assertion fails.
|
||||||
|
@ -243,49 +244,46 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
matches = selector.select(root)
|
matches = selector.select(root)
|
||||||
# Equality test.
|
# If text/html, narrow down to those elements that match it.
|
||||||
equals.each do |type, value|
|
content_mismatch = nil
|
||||||
case type
|
if match_with = equals[:text]
|
||||||
when :text
|
matches.delete_if do |match|
|
||||||
for match in matches
|
text = ""
|
||||||
text = ""
|
stack = match.children.reverse
|
||||||
stack = match.children.reverse
|
while node = stack.pop
|
||||||
while node = stack.pop
|
if node.tag?
|
||||||
if node.tag?
|
stack.concat node.children.reverse
|
||||||
stack.concat node.children.reverse
|
else
|
||||||
else
|
text << node.content
|
||||||
text << node.content
|
|
||||||
end
|
|
||||||
end
|
|
||||||
text.strip! unless match.name == "pre"
|
|
||||||
if value.is_a?(Regexp)
|
|
||||||
assert text =~ value, build_message(message, <<EOT, value, text)
|
|
||||||
<?> expected but was
|
|
||||||
<?>.
|
|
||||||
EOT
|
|
||||||
else
|
|
||||||
assert_equal value.to_s, text, message
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
when :html
|
end
|
||||||
for match in matches
|
text.strip! unless NO_STRIP.include?(match.name)
|
||||||
html = match.children.map(&:to_s).join
|
unless match_with.is_a?(Regexp) ? (text =~ match_with) : (text == match_with.to_s)
|
||||||
html.strip! unless match.name == "pre"
|
content_mismatch ||= build_message(message, "<?> expected but was\n<?>.", match_with, text)
|
||||||
if value.is_a?(Regexp)
|
true
|
||||||
assert html =~ value, build_message(message, <<EOT, value, html)
|
end
|
||||||
<?> expected but was
|
|
||||||
<?>.
|
|
||||||
EOT
|
|
||||||
else
|
|
||||||
assert_equal value.to_s, html, message
|
|
||||||
end
|
|
||||||
end
|
|
||||||
when :minimum
|
|
||||||
assert matches.size >= value, message || "Expecting at least #{value} selected elements, found #{matches.size}"
|
|
||||||
when :maximum
|
|
||||||
assert matches.size <= value, message || "Expecting at most #{value} selected elements, found #{matches.size}"
|
|
||||||
else raise ArgumentError, "I don't support the equality test #{key}"
|
|
||||||
end
|
end
|
||||||
|
elsif match_with = equals[:html]
|
||||||
|
matches.delete_if do |match|
|
||||||
|
html = match.children.map(&:to_s).join
|
||||||
|
html.strip! unless NO_STRIP.include?(match.name)
|
||||||
|
unless match_with.is_a?(Regexp) ? (html =~ match_with) : (html == match_with.to_s)
|
||||||
|
content_mismatch ||= build_message(message, "<?> expected but was\n<?>.", match_with, html)
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Expecting foo found bar element only if found zero, not if
|
||||||
|
# found one but expecting two.
|
||||||
|
message ||= content_mismatch if matches.empty?
|
||||||
|
# Test minimum/maximum occurrence.
|
||||||
|
if equals[:minimum]
|
||||||
|
assert matches.size >= equals[:minimum], message ||
|
||||||
|
"Expected at least #{equals[:minimum]} elements, found #{matches.size}."
|
||||||
|
end
|
||||||
|
if equals[:maximum]
|
||||||
|
assert matches.size <= equals[:maximum], message ||
|
||||||
|
"Expected at most #{equals[:maximum]} elements, found #{matches.size}."
|
||||||
end
|
end
|
||||||
|
|
||||||
# If a block is given call that block. Set @selected to allow
|
# If a block is given call that block. Set @selected to allow
|
||||||
|
|
|
@ -186,6 +186,23 @@ class AssertSelectTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def test_assert_select_text_match
|
||||||
|
render_html %Q{<div id="1"><span>foo</span></div><div id="2"><span>bar</span></div>}
|
||||||
|
assert_select "div" do
|
||||||
|
assert_nothing_raised { assert_select "div", "foo" }
|
||||||
|
assert_nothing_raised { assert_select "div", "bar" }
|
||||||
|
assert_nothing_raised { assert_select "div", /\w*/ }
|
||||||
|
assert_nothing_raised { assert_select "div", /\w*/, :count=>2 }
|
||||||
|
assert_raises(AssertionFailedError) { assert_select "div", :text=>"foo", :count=>2 }
|
||||||
|
assert_nothing_raised { assert_select "div", :html=>"<span>bar</span>" }
|
||||||
|
assert_nothing_raised { assert_select "div", :html=>"<span>bar</span>" }
|
||||||
|
assert_nothing_raised { assert_select "div", :html=>/\w*/ }
|
||||||
|
assert_nothing_raised { assert_select "div", :html=>/\w*/, :count=>2 }
|
||||||
|
assert_raises(AssertionFailedError) { assert_select "div", :html=>"<span>foo</span>", :count=>2 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_assert_select_from_rjs
|
def test_assert_select_from_rjs
|
||||||
render_rjs do |page|
|
render_rjs do |page|
|
||||||
page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>"
|
page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>"
|
||||||
|
|
Loading…
Reference in a new issue