| 224 | | # Asserts that there is a tag/node/element in the body of the response |
|---|
| 225 | | # that meets all of the given conditions. The +conditions+ parameter must |
|---|
| 226 | | # be a hash of any of the following keys (all are optional): |
|---|
| 227 | | # |
|---|
| 228 | | # * <tt>:tag</tt>: the node type must match the corresponding value |
|---|
| 229 | | # * <tt>:attributes</tt>: a hash. The node's attributes must match the |
|---|
| 230 | | # corresponding values in the hash. |
|---|
| 231 | | # * <tt>:parent</tt>: a hash. The node's parent must match the |
|---|
| 232 | | # corresponding hash. |
|---|
| 233 | | # * <tt>:child</tt>: a hash. At least one of the node's immediate children |
|---|
| 234 | | # must meet the criteria described by the hash. |
|---|
| 235 | | # * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must |
|---|
| 236 | | # meet the criteria described by the hash. |
|---|
| 237 | | # * <tt>:descendant</tt>: a hash. At least one of the node's descendants |
|---|
| 238 | | # must meet the criteria described by the hash. |
|---|
| 239 | | # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must |
|---|
| 240 | | # meet the criteria described by the hash. |
|---|
| 241 | | # * <tt>:after</tt>: a hash. The node must be after any sibling meeting |
|---|
| 242 | | # the criteria described by the hash, and at least one sibling must match. |
|---|
| 243 | | # * <tt>:before</tt>: a hash. The node must be before any sibling meeting |
|---|
| 244 | | # the criteria described by the hash, and at least one sibling must match. |
|---|
| 245 | | # * <tt>:children</tt>: a hash, for counting children of a node. Accepts |
|---|
| 246 | | # the keys: |
|---|
| 247 | | # * <tt>:count</tt>: either a number or a range which must equal (or |
|---|
| 248 | | # include) the number of children that match. |
|---|
| 249 | | # * <tt>:less_than</tt>: the number of matching children must be less |
|---|
| 250 | | # than this number. |
|---|
| 251 | | # * <tt>:greater_than</tt>: the number of matching children must be |
|---|
| 252 | | # greater than this number. |
|---|
| 253 | | # * <tt>:only</tt>: another hash consisting of the keys to use |
|---|
| 254 | | # to match on the children, and only matching children will be |
|---|
| 255 | | # counted. |
|---|
| 256 | | # * <tt>:content</tt>: the textual content of the node must match the |
|---|
| 257 | | # given value. This will not match HTML tags in the body of a |
|---|
| 258 | | # tag--only text. |
|---|
| 259 | | # |
|---|
| 260 | | # Conditions are matched using the following algorithm: |
|---|
| 261 | | # |
|---|
| 262 | | # * if the condition is a string, it must be a substring of the value. |
|---|
| 263 | | # * if the condition is a regexp, it must match the value. |
|---|
| 264 | | # * if the condition is a number, the value must match number.to_s. |
|---|
| 265 | | # * if the condition is +true+, the value must not be +nil+. |
|---|
| 266 | | # * if the condition is +false+ or +nil+, the value must be +nil+. |
|---|
| 267 | | # |
|---|
| 268 | | # Usage: |
|---|
| 269 | | # |
|---|
| 270 | | # # assert that there is a "span" tag |
|---|
| 271 | | # assert_tag :tag => "span" |
|---|
| 272 | | # |
|---|
| 273 | | # # assert that there is a "span" tag with id="x" |
|---|
| 274 | | # assert_tag :tag => "span", :attributes => { :id => "x" } |
|---|
| 275 | | # |
|---|
| 276 | | # # assert that there is a "span" tag using the short-hand |
|---|
| 277 | | # assert_tag :span |
|---|
| 278 | | # |
|---|
| 279 | | # # assert that there is a "span" tag with id="x" using the short-hand |
|---|
| 280 | | # assert_tag :span, :attributes => { :id => "x" } |
|---|
| 281 | | # |
|---|
| 282 | | # # assert that there is a "span" inside of a "div" |
|---|
| 283 | | # assert_tag :tag => "span", :parent => { :tag => "div" } |
|---|
| 284 | | # |
|---|
| 285 | | # # assert that there is a "span" somewhere inside a table |
|---|
| 286 | | # assert_tag :tag => "span", :ancestor => { :tag => "table" } |
|---|
| 287 | | # |
|---|
| 288 | | # # assert that there is a "span" with at least one "em" child |
|---|
| 289 | | # assert_tag :tag => "span", :child => { :tag => "em" } |
|---|
| 290 | | # |
|---|
| 291 | | # # assert that there is a "span" containing a (possibly nested) |
|---|
| 292 | | # # "strong" tag. |
|---|
| 293 | | # assert_tag :tag => "span", :descendant => { :tag => "strong" } |
|---|
| 294 | | # |
|---|
| 295 | | # # assert that there is a "span" containing between 2 and 4 "em" tags |
|---|
| 296 | | # # as immediate children |
|---|
| 297 | | # assert_tag :tag => "span", |
|---|
| 298 | | # :children => { :count => 2..4, :only => { :tag => "em" } } |
|---|
| 299 | | # |
|---|
| 300 | | # # get funky: assert that there is a "div", with an "ul" ancestor |
|---|
| 301 | | # # and an "li" parent (with "class" = "enum"), and containing a |
|---|
| 302 | | # # "span" descendant that contains text matching /hello world/ |
|---|
| 303 | | # assert_tag :tag => "div", |
|---|
| 304 | | # :ancestor => { :tag => "ul" }, |
|---|
| 305 | | # :parent => { :tag => "li", |
|---|
| 306 | | # :attributes => { :class => "enum" } }, |
|---|
| 307 | | # :descendant => { :tag => "span", |
|---|
| 308 | | # :child => /hello world/ } |
|---|
| 309 | | # |
|---|
| 310 | | # <strong>Please note</strong: #assert_tag and #assert_no_tag only work |
|---|
| 311 | | # with well-formed XHTML. They recognize a few tags as implicitly self-closing |
|---|
| 312 | | # (like br and hr and such) but will not work correctly with tags |
|---|
| 313 | | # that allow optional closing tags (p, li, td). <em>You must explicitly |
|---|
| 314 | | # close all of your tags to use these assertions.</em> |
|---|
| 315 | | def assert_tag(*opts) |
|---|
| 316 | | clean_backtrace do |
|---|
| 317 | | opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first |
|---|
| 318 | | tag = find_tag(opts) |
|---|
| 319 | | assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}" |
|---|
| 320 | | end |
|---|
| 321 | | end |
|---|
| 322 | | |
|---|
| 323 | | # Identical to #assert_tag, but asserts that a matching tag does _not_ |
|---|
| 324 | | # exist. (See #assert_tag for a full discussion of the syntax.) |
|---|
| 325 | | def assert_no_tag(*opts) |
|---|
| 326 | | clean_backtrace do |
|---|
| 327 | | opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first |
|---|
| 328 | | tag = find_tag(opts) |
|---|
| 329 | | assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}" |
|---|
| 330 | | end |
|---|
| 331 | | end |
|---|
| 332 | | |
|---|