Restore support for nested have_xpath, etc. with blocks

This commit is contained in:
Bryan Helmkamp 2008-11-08 21:34:46 -05:00
parent 055bd568f5
commit 0aad32d38a
5 changed files with 119 additions and 25 deletions

View File

@ -30,8 +30,8 @@ module Webrat
# HaveSelector:: A new have selector matcher.
# ---
# @api public
def have_selector(expected)
HaveSelector.new(expected)
def have_selector(expected, &block)
HaveSelector.new(expected, &block)
end
alias_method :match_selector, :have_selector

View File

@ -49,8 +49,8 @@ module Webrat
end
def have_tag(name, attributes = {})
HaveTag.new([name, attributes])
def have_tag(name, attributes = {}, &block)
HaveTag.new([name, attributes], &block)
end
alias_method :match_tag, :have_tag

View File

@ -16,17 +16,31 @@ module Webrat
end
def matches_rexml?(stringlike)
@query = query
@document = rexml_document(stringlike)
query.all? do |q|
matched = REXML::XPath.match(@document, q)
matched.any? && (!block_given? || matched.all?(&@block))
end
matched = @query.map do |q|
if @document.is_a?(Array)
@document.map { |d| REXML::XPath.match(d, q) }
else
REXML::XPath.match(@document, q)
end
end.flatten.compact
matched.any? && (!@block || @block.call(matched))
end
def matches_nokogiri?(stringlike)
if Nokogiri::XML::NodeSet === stringlike
@query = query.map { |q| q.gsub(%r'//', './') }
else
@query = query
end
@document = Webrat.nokogiri_document(stringlike)
@document.xpath(*query).any?
matched = @document.xpath(*@query)
matched.any? && (!@block || @block.call(matched))
end
def rexml_document(stringlike)
@ -35,9 +49,10 @@ module Webrat
case stringlike
when REXML::Document
stringlike.root
when REXML::Node
when REXML::Node, Array
@query = query.map { |q| q.gsub(%r'//', './') }
stringlike
when StringIO, String
else
begin
REXML::Document.new(stringlike.to_s).root
rescue REXML::ParseException => e
@ -76,8 +91,8 @@ module Webrat
# HaveXpath:: A new have xpath matcher.
# ---
# @api public
def have_xpath(expected)
HaveXpath.new(expected)
def have_xpath(expected, &block)
HaveXpath.new(expected, &block)
end
alias_method :match_xpath, :have_xpath

View File

@ -5,9 +5,11 @@ module Webrat
def self.nokogiri_document(stringlike) #:nodoc:
return stringlike.dom if stringlike.respond_to?(:dom)
if stringlike === Nokogiri::HTML::Document || stringlike === Nokogiri::XML::NodeSet
if Nokogiri::HTML::Document === stringlike
stringlike
elsif stringlike === StringIO
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif StringIO === stringlike
Nokogiri::HTML(stringlike.string)
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)

View File

@ -8,10 +8,50 @@ describe Webrat::Matchers do
@body = <<-EOF
<div id='main'>
<div class='inner'>hello, world!</div>
<ul>
<li>First</li>
<li>Second</li>
</ul>
</div>
EOF
end
describe "#have_xpath" do
it "should be able to match an XPATH" do
@body.should have_xpath("//div")
end
it "should not match a XPATH that does not exist" do
@body.should_not have_xpath("//p")
end
it "should be able to loop over all the matched elements" do
@body.should have_xpath("//div") { |node| node.first.name.should == "div" }
end
it "should not match of any of the matchers in the block fail" do
lambda {
@body.should have_xpath("//div") { |node| node.first.name.should == "p" }
}.should raise_error(Spec::Expectations::ExpectationNotMetError)
end
it "should be able to use #have_xpath in the block" do
@body.should have_xpath("//div[@id='main']") { |node| node.should have_xpath("./div[@class='inner']") }
end
it "should convert absolute paths to relative in the block" do
@body.should have_xpath("//div[@id='main']") { |node| node.should have_xpath("//div[@class='inner']") }
end
it "should not match any parent tags in the block" do
lambda {
@body.should have_xpath("//div[@class='inner']") { |node| node.should have_xpath("//div[@id='main']") }
}.should raise_error(Spec::Expectations::ExpectationNotMetError)
end
end
describe "#have_selector" do
it "should be able to match a CSS selector" do
@ -23,12 +63,22 @@ describe Webrat::Matchers do
end
it "should be able to loop over all the matched elements" do
@body.should have_selector("div") { |node| node.name.should == "div" }
@body.should have_selector("div") { |node| node.first.name.should == "div" }
end
it "should not match of any of the matchers in the block fail" do
lambda {
@body.should_not have_selector("div") { |node| node.name.should == "p" }
@body.should have_selector("div") { |node| node.first.name.should == "p" }
}.should raise_error(Spec::Expectations::ExpectationNotMetError)
end
it "should be able to use #have_selector in the block" do
@body.should have_selector("#main") { |node| node.should have_selector(".inner") }
end
it "should not match any parent tags in the block" do
lambda {
@body.should have_selector(".inner") { |node| node.should have_selector("#main") }
}.should raise_error(Spec::Expectations::ExpectationNotMetError)
end
@ -52,11 +102,38 @@ describe Webrat::Matchers do
@body.should have_tag("div", :class => "inner")
end
it "should be able to loop over all the matched elements" do
@body.should have_tag("div") { |node| node.first.name.should == "div" }
end
it "should not match of any of the matchers in the block fail" do
lambda {
@body.should have_tag("div") { |node| node.first.name.should == "p" }
}.should raise_error(Spec::Expectations::ExpectationNotMetError)
end
it "should be able to use #have_tag in the block" do
@body.should have_tag("div", :id => "main") { |node| node.should have_tag("div", :class => "inner") }
end
it "should not match any parent tags in the block" do
lambda {
@body.should have_tag("div", :class => "inner") { |node| node.should have_tag("div", :id => "main") }
}.should raise_error(Spec::Expectations::ExpectationNotMetError)
end
it "should work with items that have multiple child nodes" do
@body.should have_tag("ul") { |n|
n.should have_tag("li", :content => "First")
n.should have_tag("li", :content => "Second")
}
end
end
describe Webrat::Matchers::HasContent do
include Webrat::Matchers
before(:each) do
@body = <<-EOF
<div id='main'>
@ -66,26 +143,26 @@ describe Webrat::Matchers do
end
describe "#matches?" do
it "should call element#include? when the argument is a string" do
it "should call element#contains? when the argument is a string" do
@body.should contain("hello, world!")
end
it "should call element#match when the argument is a regular expression" do
it "should call element#matches? when the argument is a regular expression" do
@body.should contain(/hello, world/)
end
end
describe "#failure_message" do
it "should include the content string" do
hc = Webrat::Matchers::HasContent.new("hello, world!")
hc.matches?(@element)
hc.matches?(@body)
hc.failure_message.should include("\"hello, world!\"")
end
it "should include the content regular expresson" do
hc = Webrat::Matchers::HasContent.new(/hello,\sworld!/)
hc.matches?(@element)
hc.matches?(@body)
hc.failure_message.should include("/hello,\\sworld!/")
end