Fall back on Hpricot when Nokogiri isn't available (eg. JRuby)

This commit is contained in:
Bryan Helmkamp 2008-11-11 00:28:15 -05:00
parent 82c6be380e
commit b4bdeb5319
14 changed files with 116 additions and 117 deletions

View File

@ -13,16 +13,16 @@ module Webrat
end
end
# We need Nokogiri's CSS to XPath support, even if using REXML
# We need Nokogiri's CSS to XPath support, even if using REXML and Hpricot for parsing and searching
require "nokogiri/css"
# Require nokogiri and fall back on rexml
# Require nokogiri and fall back on rexml+Hpricot
begin
require "nokogiri"
require "webrat/core/nokogiri"
rescue LoadError => e
require "hpricot"
require "rexml/document"
warn("Standard REXML library is slow. Please consider installing nokogiri.\nUse \"sudo gem install nokogiri\"")
end
require "webrat/core"

View File

@ -1,3 +1,4 @@
require "webrat/core/xml"
require "webrat/core/nokogiri"
require "webrat/core/logging"
require "webrat/core/flunk"

View File

@ -111,7 +111,7 @@ module Webrat
end
unless id.blank?
@label_elements += @form.element.search("label[@for='#{id}']")
@label_elements += Webrat::XML.css_search(@form.element, "label[@for='#{id}']")
end
@label_elements
@ -311,8 +311,8 @@ module Webrat
protected
def default_value
selected_options = @element.search(".//option[@selected='selected']")
selected_options = @element.search(".//option[position() = 1]") if selected_options.empty?
selected_options = Webrat::XML.css_search(@element, "option[@selected='selected']")
selected_options = Webrat::XML.css_search(@element, "option:first") if selected_options.empty?
selected_options.map do |option|
return "" if option.nil?
@ -325,7 +325,7 @@ module Webrat
end
def option_elements
@element.search(".//option")
Webrat::XML.css_search(@element, "option")
end
end

View File

@ -39,7 +39,7 @@ module Webrat
def fields
return @fields if @fields
@fields = (@element.search(".//button", ".//input", ".//textarea", ".//select")).collect do |field_element|
@fields = Webrat::XML.css_search(@element, "button", "input", "textarea", "select").collect do |field_element|
Field.class_for_element(field_element).new(self, field_element)
end
end

View File

View File

@ -22,7 +22,7 @@ module Webrat
end
def matches_text?(link_text)
html = text.gsub(' ',' ')
html = text.gsub(' ',' ').gsub(' ', ' ')
if link_text.is_a?(Regexp)
matcher = link_text

View File

@ -7,15 +7,7 @@ module Webrat
end
def matches?(stringlike)
if defined?(Nokogiri::XML)
matches_nokogiri?(stringlike)
else
matches_rexml?(stringlike)
end
end
def matches_rexml?(stringlike)
@document = rexml_document(stringlike)
@document = Webrat::XML.document(stringlike)
@element = @document.inner_text
case @content
@ -26,39 +18,6 @@ module Webrat
end
end
def matches_nokogiri?(stringlike)
@document = Webrat.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
# ==== Returns
# String:: The failure message.
def failure_message

View File

@ -45,7 +45,7 @@ module Webrat
@query = query
end
@document = Webrat.nokogiri_document(stringlike)
@document = Webrat::XML.document(stringlike)
matched = @document.xpath(*@query)
matched.any? && (!@block || @block.call(matched))
end

View File

@ -166,13 +166,13 @@ module Webrat
def page_dom #:nodoc:
return @response.dom if @response.respond_to?(:dom)
dom = Webrat.nokogiri_document(@response_body)
dom = Webrat::XML.document(@response_body)
Webrat.define_dom_method(@response, dom)
return dom
end
def scoped_dom #:nodoc:
Webrat.nokogiri_document(@scope.dom.search(@selector).first.to_html)
Webrat::XML.document(@scope.dom.search(@selector).first.to_html)
end
def locate_field(field_locator, *field_types) #:nodoc:
@ -184,13 +184,13 @@ module Webrat
end
def areas #:nodoc:
dom.search("area").map do |element|
Webrat::XML.css_search(dom, "area").map do |element|
Area.new(@session, element)
end
end
def links #:nodoc:
dom.search("a[@href]").map do |link_element|
Webrat::XML.css_search(dom, "a[@href]").map do |link_element|
Link.new(@session, link_element)
end
end
@ -198,7 +198,7 @@ module Webrat
def forms #:nodoc:
return @forms if @forms
@forms = dom.search("form").map do |form_element|
@forms = Webrat::XML.css_search(dom, "form").map do |form_element|
Form.new(@session, form_element)
end
end

35
lib/webrat/core/xml.rb Normal file
View File

@ -0,0 +1,35 @@
module Webrat
module XML
def self.document(stringlike)
if defined?(Nokogiri::XML)
Webrat.nokogiri_document(stringlike)
else
return stringlike.dom if stringlike.respond_to?(:dom)
if Hpricot::Doc === stringlike
stringlike
elsif Hpricot::Elements === stringlike
stringlike
elsif StringIO === stringlike
Hpricot(stringlike.string)
elsif stringlike.respond_to?(:body)
Hpricot(stringlike.body.to_s)
else
Hpricot(stringlike.to_s)
end
end
end
def self.css_search(element, *searches)
if defined?(Nokogiri::XML)
element.css(*searches)
else
searches.map do |search|
element.search(search)
end.flatten.compact
end
end
end
end

View File

@ -1,5 +1,7 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
require "merb"
describe "selects" do
before do
@session = Webrat::TestSession.new

View File

@ -3,12 +3,12 @@ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
module Webrat
describe CheckboxField do
it "should say it is checked if it is" do
checkbox = CheckboxField.new(nil, (Webrat.nokogiri_document("<input type='checkbox' checked='checked'>")/'input').first)
checkbox = CheckboxField.new(nil, (Webrat::XML.document("<input type='checkbox' checked='checked'>").search('input')).first)
checkbox.should be_checked
end
it "should say it is not checked if it is not" do
checkbox = CheckboxField.new(nil, (Webrat.nokogiri_document("<input type='checkbox'>")/'input').first)
checkbox = CheckboxField.new(nil, (Webrat::XML.document("<input type='checkbox'>").search('input')).first)
checkbox.should_not be_checked
end
end

View File

@ -18,7 +18,7 @@ describe Webrat::Session do
"<html></html>"
end
session.current_dom.should be_an_instance_of(Nokogiri::HTML::Document)
session.current_dom.should respond_to(:search)
end
it "should open the page in the browser" do

View File

@ -1,75 +1,77 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
describe "Nokogiri Extension" do
include Webrat::Matchers
if defined?(Nokogiri::XML)
describe "Nokogiri Extension" do
include Webrat::Matchers
def fail
raise_error(Spec::Expectations::ExpectationNotMetError)
end
before(:each) do
@text_and_password = <<-HTML
<div>
<input type="text"/>
<input type="password"/>
<span type="text"/>
</div>
HTML
@text_only = <<-HTML
<div>
<input type="text" disabled="disabled" />
</div>
HTML
@password_only = <<-HTML
<div>
<input type="password"/>
<div>
HTML
end
describe ":text" do
it "passes have_selector(:text) if a node with type=text exists" do
@text_and_password.should have_selector(":text")
def fail
raise_error(Spec::Expectations::ExpectationNotMetError)
end
it "passes not have_selector(:text) if no node with text=text exists" do
@password_only.should_not have_selector(":text")
before(:each) do
@text_and_password = <<-HTML
<div>
<input type="text"/>
<input type="password"/>
<span type="text"/>
</div>
HTML
@text_only = <<-HTML
<div>
<input type="text" disabled="disabled" />
</div>
HTML
@password_only = <<-HTML
<div>
<input type="password"/>
<div>
HTML
end
it "fails have_selector(:text) if no node with type=text exists" do
lambda { @password_only.should have_selector(":text") }.should fail
describe ":text" do
it "passes have_selector(:text) if a node with type=text exists" do
@text_and_password.should have_selector(":text")
end
it "passes not have_selector(:text) if no node with text=text exists" do
@password_only.should_not have_selector(":text")
end
it "fails have_selector(:text) if no node with type=text exists" do
lambda { @password_only.should have_selector(":text") }.should fail
end
it "fails not have_selector(:text) if a node with type=text exists" do
lambda { @text_only.should_not have_selector(":text") }.should fail
end
it "works together with other selectors" do
@text_and_password.should have_selector("input:text[type*='te']")
end
end
it "fails not have_selector(:text) if a node with type=text exists" do
lambda { @text_only.should_not have_selector(":text") }.should fail
end
describe ":password" do
it "passes have_selector(:password) if a node with type=password exists" do
@text_and_password.should have_selector(":password")
end
it "works together with other selectors" do
@text_and_password.should have_selector("input:text[type*='te']")
end
end
it "passes not have_selector(:text) if no node with text=text exists" do
@text_only.should_not have_selector(":password")
end
describe ":password" do
it "passes have_selector(:password) if a node with type=password exists" do
@text_and_password.should have_selector(":password")
end
it "fails have_selector(:password) if no node with type=password exists" do
lambda { @text_only.should have_selector(":password") }.should fail
end
it "passes not have_selector(:text) if no node with text=text exists" do
@text_only.should_not have_selector(":password")
end
it "fails not have_selector(:password) if a node with type=password exists" do
lambda { @password_only.should_not have_selector(":password") }.should fail
end
it "fails have_selector(:password) if no node with type=password exists" do
lambda { @text_only.should have_selector(":password") }.should fail
end
it "fails not have_selector(:password) if a node with type=password exists" do
lambda { @password_only.should_not have_selector(":password") }.should fail
end
it "works together with other selectors" do
@text_and_password.should have_selector("input:password[type*='pa']")
it "works together with other selectors" do
@text_and_password.should have_selector("input:password[type*='pa']")
end
end
end
end