diff --git a/lib/webrat/core/matchers/have_content.rb b/lib/webrat/core/matchers/have_content.rb index 24ded0a..a979742 100644 --- a/lib/webrat/core/matchers/have_content.rb +++ b/lib/webrat/core/matchers/have_content.rb @@ -3,12 +3,31 @@ module Webrat class HasContent 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 end - - def matches?(element) - element = element.body.to_s if element.respond_to?(:body) - @element = element + + def matches?(stringlike) + if defined?(Nokogiri::XML) + matches_nokogiri?(stringlike) + else + matches_rexml?(stringlike) + end + end + + def matches_rexml?(stringlike) + @document = rexml_document(stringlike) + @element = @document.inner_text case @content when String @@ -18,16 +37,63 @@ module Webrat 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("#{stringlike}").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 # String:: The 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 # ==== Returns # String:: The failure message to be displayed in negative matches. 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 def content_message diff --git a/spec/api/matchers_spec.rb b/spec/api/matchers_spec.rb index e4b811e..0a3ebc8 100644 --- a/spec/api/matchers_spec.rb +++ b/spec/api/matchers_spec.rb @@ -58,31 +58,23 @@ describe Webrat::Matchers do include Webrat::Matchers before(:each) do - @element = stub(:element) - @element.stub!(:inner_text).and_return <<-EOF + @body = <<-EOF
hello, world!
EOF - - @element.stub!(:include?) - @element.stub!(:match) end describe "#matches?" do it "should call element#include? when the argument is a string" do - @element.should_receive(:include?) - - Webrat::Matchers::HasContent.new("hello, world!").matches?(@element) + @body.should contain("hello, world!") end it "should call element#match when the argument is a regular expression" do - @element.should_receive(:match) - - Webrat::Matchers::HasContent.new(/hello, world/).matches?(@element) + @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!") @@ -100,9 +92,9 @@ describe Webrat::Matchers do it "should include the element's inner content" do 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