root/trunk/actionpack/lib/action_controller/assertions/tag_assertions.rb
| Revision 8300, 6.2 kB (checked in by marcel, 1 year ago) |
|---|
| Line | |
|---|---|
| 1 | require 'rexml/document' |
| 2 | require 'html/document' |
| 3 | |
| 4 | module ActionController |
| 5 | module Assertions |
| 6 | # Pair of assertions to testing elements in the HTML output of the response. |
| 7 | module TagAssertions |
| 8 | # Asserts that there is a tag/node/element in the body of the response |
| 9 | # that meets all of the given conditions. The +conditions+ parameter must |
| 10 | # be a hash of any of the following keys (all are optional): |
| 11 | # |
| 12 | # * <tt>:tag</tt>: the node type must match the corresponding value |
| 13 | # * <tt>:attributes</tt>: a hash. The node's attributes must match the |
| 14 | # corresponding values in the hash. |
| 15 | # * <tt>:parent</tt>: a hash. The node's parent must match the |
| 16 | # corresponding hash. |
| 17 | # * <tt>:child</tt>: a hash. At least one of the node's immediate children |
| 18 | # must meet the criteria described by the hash. |
| 19 | # * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must |
| 20 | # meet the criteria described by the hash. |
| 21 | # * <tt>:descendant</tt>: a hash. At least one of the node's descendants |
| 22 | # must meet the criteria described by the hash. |
| 23 | # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must |
| 24 | # meet the criteria described by the hash. |
| 25 | # * <tt>:after</tt>: a hash. The node must be after any sibling meeting |
| 26 | # the criteria described by the hash, and at least one sibling must match. |
| 27 | # * <tt>:before</tt>: a hash. The node must be before any sibling meeting |
| 28 | # the criteria described by the hash, and at least one sibling must match. |
| 29 | # * <tt>:children</tt>: a hash, for counting children of a node. Accepts |
| 30 | # the keys: |
| 31 | # * <tt>:count</tt>: either a number or a range which must equal (or |
| 32 | # include) the number of children that match. |
| 33 | # * <tt>:less_than</tt>: the number of matching children must be less |
| 34 | # than this number. |
| 35 | # * <tt>:greater_than</tt>: the number of matching children must be |
| 36 | # greater than this number. |
| 37 | # * <tt>:only</tt>: another hash consisting of the keys to use |
| 38 | # to match on the children, and only matching children will be |
| 39 | # counted. |
| 40 | # * <tt>:content</tt>: the textual content of the node must match the |
| 41 | # given value. This will not match HTML tags in the body of a |
| 42 | # tag--only text. |
| 43 | # |
| 44 | # Conditions are matched using the following algorithm: |
| 45 | # |
| 46 | # * if the condition is a string, it must be a substring of the value. |
| 47 | # * if the condition is a regexp, it must match the value. |
| 48 | # * if the condition is a number, the value must match number.to_s. |
| 49 | # * if the condition is +true+, the value must not be +nil+. |
| 50 | # * if the condition is +false+ or +nil+, the value must be +nil+. |
| 51 | # |
| 52 | # === Examples |
| 53 | # |
| 54 | # # Assert that there is a "span" tag |
| 55 | # assert_tag :tag => "span" |
| 56 | # |
| 57 | # # Assert that there is a "span" tag with id="x" |
| 58 | # assert_tag :tag => "span", :attributes => { :id => "x" } |
| 59 | # |
| 60 | # # Assert that there is a "span" tag using the short-hand |
| 61 | # assert_tag :span |
| 62 | # |
| 63 | # # Assert that there is a "span" tag with id="x" using the short-hand |
| 64 | # assert_tag :span, :attributes => { :id => "x" } |
| 65 | # |
| 66 | # # Assert that there is a "span" inside of a "div" |
| 67 | # assert_tag :tag => "span", :parent => { :tag => "div" } |
| 68 | # |
| 69 | # # Assert that there is a "span" somewhere inside a table |
| 70 | # assert_tag :tag => "span", :ancestor => { :tag => "table" } |
| 71 | # |
| 72 | # # Assert that there is a "span" with at least one "em" child |
| 73 | # assert_tag :tag => "span", :child => { :tag => "em" } |
| 74 | # |
| 75 | # # Assert that there is a "span" containing a (possibly nested) |
| 76 | # # "strong" tag. |
| 77 | # assert_tag :tag => "span", :descendant => { :tag => "strong" } |
| 78 | # |
| 79 | # # Assert that there is a "span" containing between 2 and 4 "em" tags |
| 80 | # # as immediate children |
| 81 | # assert_tag :tag => "span", |
| 82 | # :children => { :count => 2..4, :only => { :tag => "em" } } |
| 83 | # |
| 84 | # # Get funky: assert that there is a "div", with an "ul" ancestor |
| 85 | # # and an "li" parent (with "class" = "enum"), and containing a |
| 86 | # # "span" descendant that contains text matching /hello world/ |
| 87 | # assert_tag :tag => "div", |
| 88 | # :ancestor => { :tag => "ul" }, |
| 89 | # :parent => { :tag => "li", |
| 90 | # :attributes => { :class => "enum" } }, |
| 91 | # :descendant => { :tag => "span", |
| 92 | # :child => /hello world/ } |
| 93 | # |
| 94 | # <b>Please note</b>: #assert_tag and #assert_no_tag only work |
| 95 | # with well-formed XHTML. They recognize a few tags as implicitly self-closing |
| 96 | # (like br and hr and such) but will not work correctly with tags |
| 97 | # that allow optional closing tags (p, li, td). <em>You must explicitly |
| 98 | # close all of your tags to use these assertions.</em> |
| 99 | def assert_tag(*opts) |
| 100 | clean_backtrace do |
| 101 | opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first |
| 102 | tag = find_tag(opts) |
| 103 | assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}" |
| 104 | end |
| 105 | end |
| 106 | |
| 107 | # Identical to #assert_tag, but asserts that a matching tag does _not_ |
| 108 | # exist. (See #assert_tag for a full discussion of the syntax.) |
| 109 | # |
| 110 | # === Examples |
| 111 | # # Assert that there is not a "div" containing a "p" |
| 112 | # assert_no_tag :tag => "div", :descendant => { :tag => "p" } |
| 113 | # |
| 114 | # # Assert that an unordered list is empty |
| 115 | # assert_no_tag :tag => "ul", :descendant => { :tag => "li" } |
| 116 | # |
| 117 | # # Assert that there is not a "p" tag with between 1 to 3 "img" tags |
| 118 | # # as immediate children |
| 119 | # assert_no_tag :tag => "p", |
| 120 | # :children => { :count => 1..3, :only => { :tag => "img" } } |
| 121 | def assert_no_tag(*opts) |
| 122 | clean_backtrace do |
| 123 | opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first |
| 124 | tag = find_tag(opts) |
| 125 | assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}" |
| 126 | end |
| 127 | end |
| 128 | end |
| 129 | end |
| 130 | end |
Note: See TracBrowser for help on using the browser.