adding html unit spike
This commit is contained in:
parent
7c46a6fed0
commit
0800f79428
|
@ -0,0 +1,41 @@
|
|||
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
||||
|
||||
module RubyHtmlUnit
|
||||
Jars = Dir[File.dirname(__FILE__) + '/ruby_html_unit/htmlunit/*.jar']
|
||||
end
|
||||
|
||||
if RUBY_PLATFORM =~ /java/
|
||||
require 'java'
|
||||
RubyHtmlUnit::Jars.each { |jar| require(jar) }
|
||||
|
||||
module HtmlUnit
|
||||
include_package 'com.gargoylesoftware.htmlunit'
|
||||
end
|
||||
JavaString = java.lang.String
|
||||
else
|
||||
raise "RubyHtmlUnit only works on JRuby at the moment."
|
||||
end
|
||||
|
||||
|
||||
Dir[File.join(File.dirname(__FILE__), "ruby_html_unit", "*.rb")].each do |file|
|
||||
require File.expand_path(file)
|
||||
end
|
||||
|
||||
|
||||
# Deal with the test server
|
||||
if `uname`.chomp == "Darwin"
|
||||
TEST_SERVER_PORT = '3001'
|
||||
|
||||
if `ps ax`.match(/^\s*(\d*).*-e test -p #{TEST_SERVER_PORT}/)
|
||||
puts "A test server was found running on port #{TEST_SERVER_PORT} (PID #{$1})"
|
||||
else
|
||||
puts "A test server was not found running (looking for -e test -p #{TEST_SERVER_PORT})"
|
||||
puts "Please start a new test server using the command below:"
|
||||
puts
|
||||
|
||||
command_string = "ruby #{RAILS_ROOT}/script/server -e test -p #{TEST_SERVER_PORT}"
|
||||
|
||||
puts command_string
|
||||
exit
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
module RubyHtmlUnit
|
||||
|
||||
class AlertHandler
|
||||
def handleAlert(html_unit_page, alert_message)
|
||||
alert_messages << alert_message
|
||||
end
|
||||
|
||||
def alert_messages
|
||||
@alert_messages ||= []
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,119 @@
|
|||
module RubyHtmlUnit
|
||||
|
||||
class Element
|
||||
def initialize(element, page)
|
||||
@html_unit_element = element
|
||||
@page = page
|
||||
end
|
||||
|
||||
def elem_type
|
||||
@html_unit_element.node_name
|
||||
end
|
||||
|
||||
def id_attribute
|
||||
@html_unit_element.id_attribute
|
||||
end
|
||||
|
||||
def matches_text?(text)
|
||||
@html_unit_element.as_text =~ text_as_regexp(text)
|
||||
end
|
||||
|
||||
def matches_attribute?(attribute, text)
|
||||
@html_unit_element.get_attribute(attribute) =~ text_as_regexp(text)
|
||||
end
|
||||
|
||||
def ancestors
|
||||
current_element = self
|
||||
[].tap do |ancs|
|
||||
while current_element.parent && current_element.elem_type != 'html'
|
||||
ancs << current_element
|
||||
current_element = current_element.parent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def label_matches?(label_text)
|
||||
ancestors.each do |anc|
|
||||
return true if anc.elem_type == 'label' && anc.matches_text?(label_text)
|
||||
end
|
||||
|
||||
if id_attribute.blank?
|
||||
return nil
|
||||
else
|
||||
label_tag = @page.elements_by_xpath("//label[@for='#{id_attribute}']").first
|
||||
return label_tag if label_tag && label_tag.matches_text?(label_text)
|
||||
end
|
||||
end
|
||||
|
||||
def click
|
||||
@html_unit_element.click
|
||||
end
|
||||
|
||||
def fill_in_with(value)
|
||||
clear
|
||||
type_string(value)
|
||||
end
|
||||
|
||||
def clear
|
||||
case @html_unit_element.getTagName
|
||||
when 'textarea' then @html_unit_element.setText('')
|
||||
when 'input' then @html_unit_element.setValueAttribute('')
|
||||
end
|
||||
end
|
||||
|
||||
def select(option_text)
|
||||
@html_unit_element.getOptions.select { |e| e.asText =~ text_as_regexp(option_text) }.each do |option|
|
||||
option.click
|
||||
#@container.update_page(option.click)
|
||||
end
|
||||
end
|
||||
|
||||
def set(value = true)
|
||||
@html_unit_element.setChecked(value)
|
||||
#value ? @html_unit_element.click : @html_unit_element.setChecked(value)
|
||||
end
|
||||
|
||||
def includes_option?(option_text)
|
||||
!!@html_unit_element.getByXPath("//option").detect {|opt| opt.as_text =~ text_as_regexp(option_text) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
@html_unit_element.as_text
|
||||
end
|
||||
|
||||
def hidden?
|
||||
!!ancestors.detect { |elem| elem.style =~ /display\s*:[\s'"]*none/ }
|
||||
end
|
||||
|
||||
def visible?
|
||||
!hidden?
|
||||
end
|
||||
|
||||
def parent
|
||||
@html_unit_element.respond_to?(:parent_node) ? Element.new(@html_unit_element.parent_node, @page) : nil
|
||||
end
|
||||
|
||||
def class_name
|
||||
@html_unit_element.class_attribute
|
||||
end
|
||||
|
||||
def method_missing(name, *args)
|
||||
return @html_unit_element.send("#{name}_attribute") if @html_unit_element.respond_to?("#{name}_attribute")
|
||||
super
|
||||
end
|
||||
|
||||
protected
|
||||
def type_string(value)
|
||||
last_page = nil
|
||||
JavaString.new(value.to_java_bytes, @html_unit_element.getPage.getPageEncoding).toCharArray.each do |char|
|
||||
last_page = @html_unit_element.type(char)
|
||||
end
|
||||
last_page
|
||||
end
|
||||
|
||||
def text_as_regexp(text)
|
||||
Regexp.new(Regexp.escape(text), true)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,114 @@
|
|||
module RubyHtmlUnit
|
||||
|
||||
class Page
|
||||
SAVED_PAGE_DIR = File.expand_path('.')
|
||||
|
||||
def initialize(html_unit_page)
|
||||
@html_unit_page = html_unit_page
|
||||
end
|
||||
|
||||
def body
|
||||
@html_unit_page.getWebResponse.getContentAsString || ''
|
||||
end
|
||||
alias_method :html_document, :body
|
||||
|
||||
def find_link(text)
|
||||
matching_links = elements_by_tag_name('a').select{|e| e.matches_text?(text)}
|
||||
|
||||
if matching_links.any?
|
||||
matching_links.sort_by { |l| l.to_s.length }.first
|
||||
else
|
||||
flunk("Could not find link with text #{text.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
def find_button(text = nil)
|
||||
buttons = []
|
||||
field_type_xpaths = %w( //button //input[@type='submit'] //input[@type='reset'] //input[@type='image'] //input[@type='button'] )
|
||||
field_type_xpaths.each do |xpath_expr|
|
||||
buttons += elements_by_xpath(xpath_expr)
|
||||
end
|
||||
|
||||
return buttons.first if text.nil?
|
||||
|
||||
matching_buttons = buttons.select{|b| b.matches_attribute?('value', text) }
|
||||
|
||||
if matching_buttons.any?
|
||||
matching_buttons.sort_by { |b| b.to_s.length }.first
|
||||
else
|
||||
flunk("Could not find button with text #{text.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
def find_field(id_or_name_or_label, field_type)
|
||||
field_type_xpaths = case field_type
|
||||
when :text then %w( //input[@type='text'] //input[@type='hidden'] //textarea )
|
||||
when :select then %w( //select )
|
||||
when :radio then %w( //input[@type='radio'] )
|
||||
when :checkbox then %w( //input[@type='checkbox'] )
|
||||
end
|
||||
|
||||
field_type_xpaths.each do |xpath_expr|
|
||||
elements_by_xpath(xpath_expr).each do |possible_field|
|
||||
return possible_field if possible_field.id_attribute == id_or_name_or_label ||
|
||||
possible_field.name == id_or_name_or_label ||
|
||||
possible_field.label_matches?(id_or_name_or_label)
|
||||
end
|
||||
end
|
||||
|
||||
flunk("Could not find #{field_type_xpaths.inspect}: #{id_or_name_or_label.inspect}")
|
||||
end
|
||||
|
||||
def find_select_list_with_option(option_text, id_or_name_or_label = nil)
|
||||
if id_or_name_or_label
|
||||
select_tag = find_field(id_or_name_or_label, :select)
|
||||
return select_tag if select_tag && select_tag.includes_option?(option_text)
|
||||
else
|
||||
elements_by_xpath("//select").each do |sel|
|
||||
if sel.includes_option?(option_text)
|
||||
return sel
|
||||
end
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def elements_by_tag_name(tag_name)
|
||||
node_list = @html_unit_page.getElementsByTagName(tag_name)
|
||||
list_len = node_list.length
|
||||
|
||||
[].tap do |array|
|
||||
0.upto(list_len-1) { |i| array << Element.new(node_list.item(i), self)}
|
||||
end
|
||||
end
|
||||
|
||||
def elements_by_xpath(xpath_expression)
|
||||
@html_unit_page.getByXPath(xpath_expression).to_a.map{ |e| Element.new(e, self) }
|
||||
end
|
||||
|
||||
def save_and_open
|
||||
return unless File.exist?(SAVED_PAGE_DIR)
|
||||
|
||||
filename = "#{SAVED_PAGE_DIR}/webrat-#{Time.now.to_i}.html"
|
||||
|
||||
File.open(filename, "w") do |f|
|
||||
f.write rewrite_css_and_image_references(body)
|
||||
end
|
||||
|
||||
open_in_browser(filename)
|
||||
end
|
||||
|
||||
def rewrite_css_and_image_references(response_html) # :nodoc
|
||||
response_html.gsub(%r<"/(stylesheets|images)>, Session.rewrite_url('"/\1'))
|
||||
end
|
||||
|
||||
def open_in_browser(path) # :nodoc
|
||||
`open #{path}`
|
||||
end
|
||||
|
||||
def flunk(message)
|
||||
raise message
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module RubyHtmlUnit
|
||||
|
||||
class Response
|
||||
def initialize(html_unit_response)
|
||||
@html_unit_response = html_unit_response
|
||||
end
|
||||
|
||||
def success?
|
||||
@html_unit_response.status_code / 100 == 2
|
||||
end
|
||||
|
||||
def content_type
|
||||
@html_unit_response.content_type
|
||||
end
|
||||
|
||||
def body
|
||||
@html_unit_response.getContentAsString || ''
|
||||
end
|
||||
alias_method :text, :body
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
class Spec::Story::Runner::ScenarioRunner
|
||||
def initialize
|
||||
@listeners = []
|
||||
end
|
||||
end
|
||||
|
||||
module RubyHtmlUnit
|
||||
|
||||
class RspecStory
|
||||
include ::Spec::Matchers
|
||||
include ::Spec::Rails::Matchers
|
||||
|
||||
def current_session
|
||||
@current_session ||= Session.new
|
||||
end
|
||||
|
||||
def method_missing(name, *args)
|
||||
if current_session.respond_to?(name)
|
||||
current_session.send(name, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,127 @@
|
|||
module RubyHtmlUnit
|
||||
|
||||
class Session
|
||||
attr_accessor :response, :current_page, :alert_handler
|
||||
|
||||
include ActionController::UrlWriter
|
||||
include ActionController::Assertions
|
||||
include Test::Unit::Assertions
|
||||
|
||||
|
||||
class << self
|
||||
def rewrite_url(url)
|
||||
if url =~ %r{^(/.*)} || url =~ %r{^https?://www.example.com(/.*)}
|
||||
append_to_root_url($1)
|
||||
else
|
||||
url
|
||||
end
|
||||
end
|
||||
|
||||
def append_to_root_url(path)
|
||||
path = "/#{path}" unless path =~ /^\//
|
||||
"http://localhost:#{TEST_SERVER_PORT}#{path}"
|
||||
end
|
||||
end
|
||||
|
||||
def initialize()
|
||||
#java.lang.System.getProperties.put("org.apache.commons.logging.simplelog.defaultlog", opts[:log_level] ? opts[:log_level].to_s : "warn")
|
||||
java.lang.System.getProperties.put("org.apache.commons.logging.simplelog.defaultlog", "warn")
|
||||
|
||||
browser = ::HtmlUnit::BrowserVersion::FIREFOX_2
|
||||
@webclient = ::HtmlUnit::WebClient.new(browser)
|
||||
@webclient.setThrowExceptionOnScriptError(false) #unless opts[:javascript_exceptions]
|
||||
@webclient.setThrowExceptionOnFailingStatusCode(false) #unless opts[:status_code_exceptions]
|
||||
@webclient.setCssEnabled(false) #unless opts[:css]
|
||||
@webclient.setUseInsecureSSL(true) #if opts[:secure_ssl]
|
||||
|
||||
@alert_handler = AlertHandler.new
|
||||
|
||||
@webclient.setAlertHandler(@alert_handler)
|
||||
|
||||
@response = nil
|
||||
@current_page = nil
|
||||
end
|
||||
|
||||
def visits(url)
|
||||
update_page(@webclient.getPage(Session.rewrite_url(url)))
|
||||
end
|
||||
|
||||
def clicks_link(text)
|
||||
link = @current_page.find_link(text)
|
||||
update_page(link.click)
|
||||
end
|
||||
|
||||
def clicks_button(text = nil)
|
||||
button = @current_page.find_button(text)
|
||||
update_page(button.click)
|
||||
end
|
||||
|
||||
def fills_in(id_or_name_or_label, options = {})
|
||||
field = @current_page.find_field(id_or_name_or_label, :text)
|
||||
update_page(field.fill_in_with(options[:with]))
|
||||
end
|
||||
|
||||
def selects(option_text, options = {})
|
||||
id_or_name_or_label = options[:from]
|
||||
|
||||
select_tag = @current_page.find_select_list_with_option(option_text, id_or_name_or_label)
|
||||
|
||||
flunk("Could not find option #{option_text.inspect}") if select_tag.nil?
|
||||
select_tag.select(option_text)
|
||||
end
|
||||
|
||||
def chooses(label)
|
||||
field = @current_page.find_field(label, :radio)
|
||||
update_page(field.set)
|
||||
end
|
||||
|
||||
def checks(id_or_name_or_label)
|
||||
field = @current_page.find_field(id_or_name_or_label, :checkbox)
|
||||
update_page(field.set(true))
|
||||
end
|
||||
|
||||
def unchecks(id_or_name_or_label)
|
||||
field = @current_page.find_field(id_or_name_or_label, :checkbox)
|
||||
update_page(field.set(false))
|
||||
end
|
||||
|
||||
def get_element(dom_id)
|
||||
@current_page.elements_by_xpath("//*[@id='#{dom_id}']").first
|
||||
end
|
||||
alias_method :get_element_by_id, :get_element
|
||||
|
||||
def wait_for_result(wait_type)
|
||||
# No support for different types of waiting right now
|
||||
sleep(0.5)
|
||||
# if wait_type == :ajax
|
||||
# wait_for_ajax
|
||||
# elsif wait_type == :effects
|
||||
# wait_for_effects
|
||||
# else
|
||||
# wait_for_page_to_load
|
||||
# end
|
||||
end
|
||||
|
||||
def update_page(html_unit_page)
|
||||
@current_page = Page.new(html_unit_page)
|
||||
@response = Response.new(html_unit_page.getWebResponse)
|
||||
end
|
||||
|
||||
def save_and_open_page
|
||||
@current_page.save_and_open
|
||||
end
|
||||
|
||||
def respond_to?(method)
|
||||
super || @current_page.respond_to?(method)
|
||||
end
|
||||
|
||||
def method_missing(name, *args)
|
||||
if @current_page.respond_to?(name)
|
||||
@current_page.send(name, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue