Make "should contain" matcher work with inner text instead of HTML

This commit is contained in:
Bryan Helmkamp 2008-11-07 00:35:50 -05:00
parent b23dcfb213
commit 7b3e6fa118
2 changed files with 78 additions and 20 deletions

View File

@ -3,12 +3,31 @@ module Webrat
class HasContent class HasContent
def initialize(content) def initialize(content)
# Require nokogiri and fall back on rexml
begin
require "nokogiri"
require "webrat/nokogiri"
rescue LoadError => e
if require "rexml/document"
require "webrat/vendor/nokogiri/css"
warn("Standard REXML library is slow. Please consider installing nokogiri.\nUse \"sudo gem install nokogiri\"")
end
end
@content = content @content = content
end end
def matches?(element) def matches?(stringlike)
element = element.body.to_s if element.respond_to?(:body) if defined?(Nokogiri::XML)
@element = element matches_nokogiri?(stringlike)
else
matches_rexml?(stringlike)
end
end
def matches_rexml?(stringlike)
@document = rexml_document(stringlike)
@element = @document.inner_text
case @content case @content
when String when String
@ -18,16 +37,63 @@ module Webrat
end end
end end
def matches_nokogiri?(stringlike)
@document = nokogiri_document(stringlike)
@element = @document.inner_text
case @content
when String
@element.include?(@content)
when Regexp
@element.match(@content)
end
end
def rexml_document(stringlike)
stringlike = stringlike.body.to_s if stringlike.respond_to?(:body)
case stringlike
when REXML::Document
stringlike.root
when REXML::Node
stringlike
when StringIO, String
begin
REXML::Document.new(stringlike.to_s).root
rescue REXML::ParseException => e
if e.message.include?("second root element")
REXML::Document.new("<fake-root-element>#{stringlike}</fake-root-element>").root
else
raise e
end
end
end
end
def nokogiri_document(stringlike)
return stringlike.dom if stringlike.respond_to?(:dom)
stringlike = stringlike.body.to_s if stringlike.respond_to?(:body)
case stringlike
when Nokogiri::HTML::Document, Nokogiri::XML::NodeSet
stringlike
when StringIO
Nokogiri::HTML(stringlike.string)
else
Nokogiri::HTML(stringlike.to_s)
end
end
# ==== Returns # ==== Returns
# String:: The failure message. # String:: The failure message.
def failure_message def failure_message
"expected the following element's content to #{content_message}:\n#{@element.inner_text}" "expected the following element's content to #{content_message}:\n#{@element}"
end end
# ==== Returns # ==== Returns
# String:: The failure message to be displayed in negative matches. # String:: The failure message to be displayed in negative matches.
def negative_failure_message def negative_failure_message
"expected the following element's content to not #{content_message}:\n#{@element.inner_text}" "expected the following element's content to not #{content_message}:\n#{@element}"
end end
def content_message def content_message

View File

@ -58,31 +58,23 @@ describe Webrat::Matchers do
include Webrat::Matchers include Webrat::Matchers
before(:each) do before(:each) do
@element = stub(:element) @body = <<-EOF
@element.stub!(:inner_text).and_return <<-EOF
<div id='main'> <div id='main'>
<div class='inner'>hello, world!</div> <div class='inner'>hello, world!</div>
</div> </div>
EOF EOF
@element.stub!(:include?)
@element.stub!(:match)
end end
describe "#matches?" do describe "#matches?" do
it "should call element#include? when the argument is a string" do it "should call element#include? when the argument is a string" do
@element.should_receive(:include?) @body.should contain("hello, world!")
Webrat::Matchers::HasContent.new("hello, world!").matches?(@element)
end end
it "should call element#match when the argument is a regular expression" do it "should call element#match when the argument is a regular expression" do
@element.should_receive(:match) @body.should contain(/hello, world/)
Webrat::Matchers::HasContent.new(/hello, world/).matches?(@element)
end end
end end
describe "#failure_message" do describe "#failure_message" do
it "should include the content string" do it "should include the content string" do
hc = Webrat::Matchers::HasContent.new("hello, world!") hc = Webrat::Matchers::HasContent.new("hello, world!")
@ -100,9 +92,9 @@ describe Webrat::Matchers do
it "should include the element's inner content" do it "should include the element's inner content" do
hc = Webrat::Matchers::HasContent.new(/hello,\sworld!/) hc = Webrat::Matchers::HasContent.new(/hello,\sworld!/)
hc.matches?(@element) hc.matches?(@body)
hc.failure_message.should include(@element.inner_text) hc.failure_message.should include("hello, world!")
end end
end end
end end