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
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/css"
# Require nokogiri and fall back on rexml # Require nokogiri and fall back on rexml+Hpricot
begin begin
require "nokogiri" require "nokogiri"
require "webrat/core/nokogiri" require "webrat/core/nokogiri"
rescue LoadError => e rescue LoadError => e
require "hpricot"
require "rexml/document" require "rexml/document"
warn("Standard REXML library is slow. Please consider installing nokogiri.\nUse \"sudo gem install nokogiri\"")
end end
require "webrat/core" require "webrat/core"

View File

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

View File

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

View File

@ -39,7 +39,7 @@ module Webrat
def fields def fields
return @fields if @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) Field.class_for_element(field_element).new(self, field_element)
end end
end end

View File

View File

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

View File

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

View File

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

View File

@ -166,13 +166,13 @@ module Webrat
def page_dom #:nodoc: def page_dom #:nodoc:
return @response.dom if @response.respond_to?(:dom) 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) Webrat.define_dom_method(@response, dom)
return dom return dom
end end
def scoped_dom #:nodoc: 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 end
def locate_field(field_locator, *field_types) #:nodoc: def locate_field(field_locator, *field_types) #:nodoc:
@ -184,13 +184,13 @@ module Webrat
end end
def areas #:nodoc: def areas #:nodoc:
dom.search("area").map do |element| Webrat::XML.css_search(dom, "area").map do |element|
Area.new(@session, element) Area.new(@session, element)
end end
end end
def links #:nodoc: 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) Link.new(@session, link_element)
end end
end end
@ -198,7 +198,7 @@ module Webrat
def forms #:nodoc: def forms #:nodoc:
return @forms if @forms 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) Form.new(@session, form_element)
end end
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 File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
require "merb"
describe "selects" do describe "selects" do
before do before do
@session = Webrat::TestSession.new @session = Webrat::TestSession.new

View File

@ -3,12 +3,12 @@ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
module Webrat module Webrat
describe CheckboxField do describe CheckboxField do
it "should say it is checked if it is" 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 checkbox.should be_checked
end end
it "should say it is not checked if it is not" do 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 checkbox.should_not be_checked
end end
end end

View File

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

View File

@ -1,6 +1,7 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
describe "Nokogiri Extension" do if defined?(Nokogiri::XML)
describe "Nokogiri Extension" do
include Webrat::Matchers include Webrat::Matchers
def fail def fail
@ -72,4 +73,5 @@ describe "Nokogiri Extension" do
@text_and_password.should have_selector("input:password[type*='pa']") @text_and_password.should have_selector("input:password[type*='pa']")
end end
end end
end
end end