aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG2
-rw-r--r--actionpack/lib/action_controller/assertions.rb6
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/node.rb54
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb2
4 files changed, 59 insertions, 5 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 1630a26a2b..cc2029c2c2 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Added functionality to assert_tag, so you can now do tests on the siblings of a node, to assert that some element comes before or after the element in question, or just to assert that some element exists as a sibling #1226 [Jamis Buck]
+
* Added better error handling for regexp caching expiration
* Fixed handling of requests coming from unknown HTTP methods not to kill the server
diff --git a/actionpack/lib/action_controller/assertions.rb b/actionpack/lib/action_controller/assertions.rb
index 00388f8f59..5d1826b72a 100644
--- a/actionpack/lib/action_controller/assertions.rb
+++ b/actionpack/lib/action_controller/assertions.rb
@@ -136,6 +136,12 @@ module Test #:nodoc:
# meet the criteria described by the hash.
# * <tt>:descendant</tt>: a hash. At least one of the node's descendants
# must meet the criteria described by the hash.
+ # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must
+ # meet the criteria described by the hash.
+ # * <tt>:after</tt>: a hash. The node must be after any sibling meeting
+ # the criteria described by the hash, and at least one sibling must match.
+ # * <tt>:before</tt>: a hash. The node must be before any sibling meeting
+ # the criteria described by the hash, and at least one sibling must match.
# * <tt>:children</tt>: a hash, for counting children of a node. Accepts
# the keys:
# * <tt>:count</tt>: either a number or a range which must equal (or
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb
index b3979fa3cb..2d32962ba8 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb
@@ -13,7 +13,8 @@ module HTML#:nodoc:
# keys are valid, and require no further processing
when :attributes then
hash[k] = keys_to_strings(v)
- when :parent, :child, :ancestor, :descendant
+ when :parent, :child, :ancestor, :descendant, :sibling, :before,
+ :after
hash[k] = Conditions.new(v)
when :children
hash[k] = v = keys_to_symbols(v)
@@ -119,12 +120,20 @@ module HTML#:nodoc:
end
class <<self
- def parse(parent, line, pos, content)
+ def parse(parent, line, pos, content, strict=true)
if content !~ /^<\S/
Text.new(parent, line, pos, content)
else
scanner = StringScanner.new(content)
- scanner.skip(/</) or raise "expected <"
+
+ unless scanner.skip(/</)
+ if strict
+ raise "expected <"
+ else
+ return Text.new(parent, line, pos, content)
+ end
+ end
+
closing = ( scanner.scan(/\//) ? :close : nil )
return Text.new(parent, line, pos, content) unless name = scanner.scan(/[\w:]+/)
name.downcase!
@@ -158,7 +167,14 @@ module HTML#:nodoc:
closing = ( scanner.scan(/\//) ? :self : nil )
end
- scanner.scan(/\s*>/) or raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})"
+ unless scanner.scan(/\s*>/)
+ if strict
+ raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})"
+ else
+ # throw away all text until we find what we're looking for
+ scanner.skip_until(/>/) or scanner.terminate
+ end
+ end
Tag.new(parent, line, pos, name, attributes, closing)
end
@@ -296,6 +312,12 @@ module HTML#:nodoc:
# meet the criteria described by the hash.
# * <tt>:descendant</tt>: a hash. At least one of the node's descendants
# must meet the criteria described by the hash.
+ # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must
+ # meet the criteria described by the hash.
+ # * <tt>:after</tt>: a hash. The node must be after any sibling meeting
+ # the criteria described by the hash, and at least one sibling must match.
+ # * <tt>:before</tt>: a hash. The node must be before any sibling meeting
+ # the criteria described by the hash, and at least one sibling must match.
# * <tt>:children</tt>: a hash, for counting children of a node. Accepts the
# keys:
# ** <tt>:count</tt>: either a number or a range which must equal (or
@@ -404,6 +426,30 @@ module HTML#:nodoc:
end
end
end
+
+ # test siblings
+ if conditions[:sibling] || conditions[:before] || conditions[:after]
+ siblings = parent ? parent.children : []
+ self_index = siblings.index(self)
+
+ if conditions[:sibling]
+ return false unless siblings.detect do |s|
+ s != self && s.match(conditions[:sibling])
+ end
+ end
+
+ if conditions[:before]
+ return false unless siblings[self_index+1..-1].detect do |s|
+ s != self && s.match(conditions[:before])
+ end
+ end
+
+ if conditions[:after]
+ return false unless siblings[0,self_index].detect do |s|
+ s != self && s.match(conditions[:after])
+ end
+ end
+ end
true
end
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb
index 2c3ee922d9..45066319f5 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/tokenizer.rb
@@ -92,4 +92,4 @@ module HTML#:nodoc:
end
end
-end \ No newline at end of file
+end