def assert_select(*args, &block)
arg = args.shift
if arg.is_a?(HTML::Node)
root = arg
arg = args.shift
elsif arg == nil
raise ArgumentError, "First argument is either selector or element to select, but nil found. Perhaps you called assert_select with an element that does not exist?"
elsif @selected
root = HTML::Node.new(nil)
root.children.concat @selected
else
root = response_from_page_or_rjs
end
case arg
when String
selector = HTML::Selector.new(arg, args)
when Array
selector = HTML::Selector.new(*arg)
when HTML::Selector
selector = arg
else raise ArgumentError, "Expecting a selector as the first argument"
end
equals = {}
case arg = args.shift
when Hash
equals = arg
when String, Regexp
equals[:text] = arg
when Integer
equals[:count] = arg
when Range
equals[:minimum] = arg.begin
equals[:maximum] = arg.end
when FalseClass
equals[:count] = 0
when NilClass, TrueClass
equals[:minimum] = 1
else raise ArgumentError, "I don't understand what you're trying to match"
end
if equals[:count]
equals[:minimum] = equals[:maximum] = equals[:count]
else
equals[:minimum] = 1 unless equals[:minimum]
end
message = args.shift
if args.shift
raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type"
end
matches = selector.select(root)
content_mismatch = nil
if match_with = equals[:text]
matches.delete_if do |match|
text = ""
stack = match.children.reverse
while node = stack.pop
if node.tag?
stack.concat node.children.reverse
else
content = node.content
text << content
end
end
text.strip! unless NO_STRIP.include?(match.name)
unless match_with.is_a?(Regexp) ? (text =~ match_with) : (text == match_with.to_s)
content_mismatch ||= build_message(message, "<?> expected but was\n<?>.", match_with, text)
true
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
message ||= content_mismatch if matches.empty?
min, max, count = equals[:minimum], equals[:maximum], equals[:count]
message = message || %(Expected #{count_description(min, max, count)} matching "#{selector.to_s}", found #{matches.size}.)
if count
assert matches.size == count, message
else
assert matches.size >= min, message if min
assert matches.size <= max, message if max
end
if block_given? && !matches.empty?
begin
in_scope, @selected = @selected, matches
yield matches
ensure
@selected = in_scope
end
end
matches
end