module ActionDispatch::Assertions::TagAssertions

def assert_no_tag(*opts)

:children => { :count => 1..3, :only => { :tag => "img" } }
assert_no_tag :tag => "p",
# as immediate children
# Assert that there is not a "p" tag with between 1 to 3 "img" tags

assert_no_tag :tag => "ul", :descendant => { :tag => "li" }
# Assert that an unordered list is empty

assert_no_tag :tag => "div", :descendant => { :tag => "p" }
# Assert that there is not a "div" containing a "p"
=== Examples

exist. (See +assert_tag+ for a full discussion of the syntax.)
Identical to +assert_tag+, but asserts that a matching tag does _not_
def assert_no_tag(*opts)
  opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
  tag = find_tag(opts)
  assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
end

def assert_tag(*opts)

close all of your tags to use these assertions.
that allow optional closing tags (p, li, td). You must explicitly
(like br and hr and such) but will not work correctly with tags
with well-formed XHTML. They recognize a few tags as implicitly self-closing
Please note: +assert_tag+ and +assert_no_tag+ only work

:child => /hello world/ }
:descendant => { :tag => "span",
:attributes => { :class => "enum" } },
:parent => { :tag => "li",
:ancestor => { :tag => "ul" },
assert_tag :tag => "div",
# "span" descendant that contains text matching /hello world/
# and an "li" parent (with "class" = "enum"), and containing a
# Get funky: assert that there is a "div", with an "ul" ancestor

:children => { :count => 2..4, :only => { :tag => "em" } }
assert_tag :tag => "span",
# as immediate children
# Assert that there is a "span" containing between 2 and 4 "em" tags

assert_tag :tag => "span", :descendant => { :tag => "strong" }
# "strong" tag.
# Assert that there is a "span" containing a (possibly nested)

assert_tag :tag => "span", :child => { :tag => "em" }
# Assert that there is a "span" with at least one "em" child

assert_tag :tag => "span", :ancestor => { :tag => "table" }
# Assert that there is a "span" somewhere inside a table

assert_tag :tag => "span", :parent => { :tag => "div" }
# Assert that there is a "span" inside of a "div"

assert_tag :span, :attributes => { :id => "x" }
# Assert that there is a "span" tag with id="x" using the short-hand

assert_tag :span
# Assert that there is a "span" tag using the short-hand

assert_tag :tag => "span", :attributes => { :id => "x" }
# Assert that there is a "span" tag with id="x"

assert_tag :tag => "span"
# Assert that there is a "span" tag

=== Examples

* if the condition is +false+ or +nil+, the value must be +nil+.
* if the condition is +true+, the value must not be +nil+.
* if the condition is a number, the value must match number.to_s.
* if the condition is a regexp, it must match the value.
* if the condition is a string, it must be a substring of the value.

Conditions are matched using the following algorithm:

tag--only text.
given value. This will not match HTML tags in the body of a
* :content: the textual content of the node must match the
counted.
to match on the children, and only matching children will be
* :only: another hash consisting of the keys to use
greater than this number.
* :greater_than: the number of matching children must be
than this number.
* :less_than: the number of matching children must be less
include) the number of children that match.
* :count: either a number or a range which must equal (or
the keys:
* :children: a hash, for counting children of a node. Accepts
the criteria described by the hash, and at least one sibling must match.
* :before: a hash. The node must be before any sibling meeting
the criteria described by the hash, and at least one sibling must match.
* :after: a hash. The node must be after any sibling meeting
meet the criteria described by the hash.
* :sibling: a hash. At least one of the node's siblings must
must meet the criteria described by the hash.
* :descendant: a hash. At least one of the node's descendants
meet the criteria described by the hash.
* :ancestor: a hash. At least one of the node's ancestors must
must meet the criteria described by the hash.
* :child: a hash. At least one of the node's immediate children
corresponding hash.
* :parent: a hash. The node's parent must match the
corresponding values in the hash.
* :attributes: a hash. The node's attributes must match the
* :tag: the node type must match the corresponding value

be a hash of any of the following keys (all are optional):
that meets all of the given conditions. The +conditions+ parameter must
Asserts that there is a tag/node/element in the body of the response
def assert_tag(*opts)
  opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
  tag = find_tag(opts)
  assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
end

def find_all_tag(conditions)

def find_all_tag(conditions)
  html_document.find_all(conditions)
end

def find_tag(conditions)

def find_tag(conditions)
  html_document.find(conditions)
end

def html_document

def html_document
  xml = @response.content_type =~ /xml$/
  @html_document ||= HTML::Document.new(@response.body, false, xml)
end