Merge commit 'bmabey/master'

This commit is contained in:
Bryan Helmkamp 2008-11-15 19:39:03 -05:00
commit fe16731370
32 changed files with 1028 additions and 9 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ email.txt
log log
.project .project
.loadpath .loadpath
*.swp

View File

@ -1,5 +1,9 @@
== Trunk == Trunk
* Major enhancements
* Added selects_time, selects_date, and selects_datetime to API. (Ben Mabey, Ticket #36)
* Minor enhancements * Minor enhancements
* Allow clicking links by id and id regexp (gaffo) * Allow clicking links by id and id regexp (gaffo)

View File

@ -34,8 +34,16 @@ module Webrat
labels.first.text labels.first.text
end end
def id
@element["id"]
end
def matches_id?(id) def matches_id?(id)
@element["id"] == id.to_s if id.is_a?(Regexp)
@element["id"] =~ id
else
@element["id"] == id.to_s
end
end end
def matches_name?(name) def matches_name?(name)
@ -83,10 +91,6 @@ module Webrat
protected protected
def id
@element["id"]
end
def name def name
@element["name"] @element["name"]
end end

View File

@ -44,6 +44,10 @@ module Webrat
end end
end end
def labels
@labels ||= element.search("label").map { |element| Label.new(nil, element) }
end
def submit def submit
@session.request_page(form_action, form_method, params) @session.request_page(form_action, form_method, params)
end end
@ -66,6 +70,10 @@ module Webrat
matching_fields.min { |a, b| a.label_text.length <=> b.label_text.length } matching_fields.min { |a, b| a.label_text.length <=> b.label_text.length }
end end
def label_matching(label_text)
labels.detect { |label| label.matches_text?(label_text) }
end
protected protected
def fields_by_type(field_types) def fields_by_type(field_types)

View File

@ -18,5 +18,9 @@ module Webrat
str str
end end
def for_id
@element['for']
end
end end
end end

View File

@ -88,5 +88,14 @@ module Webrat
end end
end end
def find_field_id_for_label(label_text)
label = forms.detect_mapped { |form| form.label_matching(label_text) }
if label
label.for_id
else
flunk("Could not find the label with text #{label_text}")
end
end
end end
end end

View File

@ -97,6 +97,114 @@ module Webrat
alias_method :select, :selects alias_method :select, :selects
DATE_TIME_SUFFIXES = {:rails => {:year => '1i', :month => '2i', :day => '3i',
:hour => '4i', :minute => '5i'},
:full_words => {:year => 'year', :month => 'month', :day => 'day',
:hour => 'hour', :minute => 'minute'}
}
# Verifies that date elements (year, month, day) exist on the current page
# with the specified values. You can optionally restrict the search to a specific
# date's elements by assigning <tt>options[:from]</tt> the value of the date's
# label. Selects all the date elements with date provided. The date provided may
# be a string or a Date/Time object.
#
# By default Rail's convention is used for detecting the date elements, but this
# may be overriden by assinging a <tt>options[:suffix_convention]</tt> or
# <tt>options[:suffixes]</tt>. In all cases all elements are assumed to have a
# shared prefix. For example, a birthday date on a form might have the following:
# 'birthday_Year', 'birthday_Month', 'birthday_Day'. You may also specify the
# prefix by assigning <tt>options[:id_prefix]</tt>.
#
# Examples:
# selects_date "January 23, 2004"
# selects_date "April 26, 1982", :from => "Birthday"
# selects_date Date.parse("December 25, 2000"), :from => "Event"
# selects_date "April 26, 1982", :suffix_convention => :full_words
# selects_date "April 26, 1982", :id_prefix => 'birthday',
# :suffixes => {:year => 'Year', :month => 'Mon', :day => 'Day'}
def selects_date(date_to_select, options ={})
date = date_to_select.is_a?(Date) || date_to_select.is_a?(Time) ?
date_to_select : Date.parse(date_to_select)
suffixes = extract_date_time_suffixes(options)
id_prefix = locate_id_prefix(options) do
year_field = find_field_with_id(/(.*?)_#{suffixes[:year]}$/)
flunk("No date fields were found") unless year_field && year_field.id =~ /(.*?)_1i/
$1
end
selects date.year, :from => "#{id_prefix}_#{suffixes[:year]}"
selects date.strftime('%B'), :from => "#{id_prefix}_#{suffixes[:month]}"
selects date.day, :from => "#{id_prefix}_#{suffixes[:day]}"
end
alias_method :select_date, :selects_date
# Verifies that time elements (hour, minute) exist on the current page
# with the specified values. You can optionally restrict the search to a specific
# time's elements by assigning <tt>options[:from]</tt> the value of the time's
# label. Selects all the time elements with date provided. The time provided may
# be a string or a Time object.
#
# By default Rail's convention is used for detecting the time elements, but this
# may be overriden by assinging a <tt>options[:suffix_convention]</tt> or
# <tt>options[:suffixes]</tt>. In all cases all elements are assumed to have a
# shared prefix. For example, an appointment time on a form might have the
# following: 'appt_time_hour', 'appt_time_min'. You may also specify the
# prefix by assigning <tt>options[:id_prefix]</tt>.
#
# Note: Just like Rails' time_select helper this assumes the form is using
# 24 hour select boxes, and not 12 hours with AM/PM.
#
# Examples:
# selects_time "9:30"
# selects_date "3:30PM", :from => "Party Time"
# selects_date Time.parse("10:00PM"), :from => "Event"
# selects_date "8:30", :suffix_convention => :full_words
# selects_date "10:30AM", :id_prefix => 'meeting',
# :suffixes => {:hour => 'Hour', :min => 'Min'}
def selects_time(time_to_select, options ={})
time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
suffixes = extract_date_time_suffixes(options)
id_prefix = locate_id_prefix(options) do
hour_field = find_field_with_id(/(.*?)_#{suffixes[:hour]}$/)
flunk("No time fields were found") unless hour_field && hour_field.id =~ /(.*?)_4i/
$1
end
selects time.hour.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{suffixes[:hour]}"
selects time.min.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{suffixes[:minute]}"
end
alias_method :select_time, :selects_time
# Verifies and selects all the date and time elements on the current page.
# See #selects_time and #selects_date for more details and available options.
#
# Examples:
# selects_datetime "January 23, 2004 10:30AM"
# selects_datetime "April 26, 1982 7:00PM", :from => "Birthday"
# selects_datetime Time.parse("December 25, 2000 15:30"), :from => "Event"
# selects_datetime "April 26, 1982 5:50PM", :suffix_convention => :full_words
# selects_datetime "April 26, 1982 5:50PM", :id_prefix => 'birthday',
# :suffixes => {:year => 'Year', :month => 'Mon', :day => 'Day',
# :hour => 'Hour', :minute => 'Min'}
def selects_datetime(time_to_select, options ={})
time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
options[:id_prefix] ||= (options[:from] ? find_field_with_id(options[:from]) : nil)
selects_date time, options
selects_time time, options
end
alias_method :select_datetime, :selects_datetime
# Verifies that an input file field exists on the current page and sets # Verifies that an input file field exists on the current page and sets
# its value to the given +file+, so that the file will be uploaded # its value to the given +file+, so that the file will be uploaded
# along with the form. An optional <tt>content_type</tt> may be given. # along with the form. An optional <tt>content_type</tt> may be given.
@ -196,6 +304,17 @@ module Webrat
end end
end end
def locate_id_prefix(options, &location_strategy) #:nodoc:
return options[:id_prefix] if options[:id_prefix]
id_prefix = options[:from] ? find_field_id_for_label(options[:from]) : yield
end
def extract_date_time_suffixes(options) #:nodoc:
options[:suffixes] ||
DATE_TIME_SUFFIXES[options[:suffix_convention]] ||
DATE_TIME_SUFFIXES[:rails]
end
def areas #:nodoc: def areas #:nodoc:
Webrat::XML.css_search(dom, "area").map do |element| Webrat::XML.css_search(dom, "area").map do |element|
Area.new(@session, element) Area.new(@session, element)

View File

@ -184,6 +184,9 @@ module Webrat
def_delegators :current_scope, :uncheck, :unchecks def_delegators :current_scope, :uncheck, :unchecks
def_delegators :current_scope, :choose, :chooses def_delegators :current_scope, :choose, :chooses
def_delegators :current_scope, :select, :selects def_delegators :current_scope, :select, :selects
def_delegators :current_scope, :select_datetime, :selects_datetime
def_delegators :current_scope, :select_date, :selects_date
def_delegators :current_scope, :select_time, :selects_time
def_delegators :current_scope, :attach_file, :attaches_file def_delegators :current_scope, :attach_file, :attaches_file
def_delegators :current_scope, :click_area, :clicks_area def_delegators :current_scope, :click_area, :clicks_area
def_delegators :current_scope, :click_link, :clicks_link def_delegators :current_scope, :click_link, :clicks_link

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,130 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
describe "selects_date" do
before do
@session = Webrat::TestSession.new
end
it "should send the values for each individual date component" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_date">Date</label><br />
<select id="appointment_date_1i" name="appointment[date(1i)]">
<option value="2003">2003</option>
</select>
<select id="appointment_date_2i" name="appointment[date(2i)]">
<option value="12">December</option>
</select>
<select id="appointment_date_3i" name="appointment[date(3i)]">
<option value="25">25</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"date(1i)" => '2003', "date(2i)" => "12", "date(3i)" => "25"})
@session.selects_date "December 25, 2003", :from => "Date"
@session.click_button
end
it "should select the date components with the suffix convention provided" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_date">Date</label><br />
<select id="appointment_date_year" name="appointment[year]">
<option value="2003">2003</option>
</select>
<select id="appointment_date_month" name="appointment[month]">
<option value="12">December</option>
</select>
<select id="appointment_date_day" name="appointment[day]">
<option value="25">25</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"year" => '2003', "month" => "12", "day" => "25"})
@session.selects_date "December 25, 2003 9:30", :from => "Date", :suffix_convention => :full_words
@session.click_button
end
it "should select the date components with the suffixes provided" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_date">Date</label><br />
<select id="appointment_date_y" name="appointment[y]">
<option value="2003">2003</option>
</select>
<select id="appointment_date_mo" name="appointment[mo]">
<option value="12">December</option>
</select>
<select id="appointment_date_d" name="appointment[d]">
<option value="25">25</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"y" => '2003', "mo" => "12", "d" => "25"})
@session.selects_date "December 25, 2003 9:30", :from => "Date",
:suffixes => {:year => 'y', :month => 'mo', :day => 'd'}
@session.click_button
end
it "should accept a date object" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_date">date</label><br />
<select id="appointment_date_1i" name="appointment[date(1i)]">
<option value="2003">2003</option>
</select>
<select id="appointment_date_2i" name="appointment[date(2i)]">
<option value="12">December</option>
</select>
<select id="appointment_date_3i" name="appointment[date(3i)]">
<option value="25">25</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"date(1i)" => '2003', "date(2i)" => "12", "date(3i)" => "25"})
@session.selects_date Date.parse("December 25, 2003"), :from => "date"
@session.click_button
end
it "should work when no label is specified" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<select id="appointment_date_1i" name="appointment[date(1i)]">
<option value="2003">2003</option>
</select>
<select id="appointment_date_2i" name="appointment[date(2i)]">
<option value="12">December</option>
</select>
<select id="appointment_date_3i" name="appointment[date(3i)]">
<option value="25">25</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"date(1i)" => '2003', "date(2i)" => "12", "date(3i)" => "25"})
@session.selects_date "December 25, 2003"
@session.click_button
end
it "should fail if the specified label is not found" do
@session.response_body = <<-EOS
<form method="post" action="/appointments">
<select name="month"><option>January</option></select>
<input type="submit" />
</form>
EOS
lambda { @session.selects_date "December 25, 2003", :from => "date" }.should raise_error
end
end

View File

@ -0,0 +1,159 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
describe "selects_datetime" do
before do
@session = Webrat::TestSession.new
end
it "should send the values for each individual date and time components" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_1i" name="appointment[time(1i)]">
<option value="2003">2003</option>
</select>
<select id="appointment_time_2i" name="appointment[time(2i)]">
<option value="12">December</option>
</select>
<select id="appointment_time_3i" name="appointment[time(3i)]">
<option value="25">25</option>
</select>
<select id="appointment_time_4i" name="appointment[time(4i)]">
<option value="09">09</option>
</select>
: <select id="appointment_time_5i" name="appointment[time(5i)]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"time(1i)" => '2003', "time(2i)" => "12", "time(3i)" => "25", "time(4i)" => "09", "time(5i)" => "30"})
@session.selects_datetime "December 25, 2003 9:30", :from => "Time"
@session.click_button
end
it "should select the date and time components with the suffix convention provided" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_year" name="appointment[year]">
<option value="2003">2003</option>
</select>
<select id="appointment_time_month" name="appointment[month]">
<option value="12">December</option>
</select>
<select id="appointment_time_day" name="appointment[day]">
<option value="25">25</option>
</select>
<select id="appointment_time_hour" name="appointment[hour]">
<option value="09">09</option>
</select>
: <select id="appointment_time_minute" name="appointment[minute]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"year" => '2003', "month" => "12", "day" => "25", "hour" => "09", "minute" => "30"})
@session.selects_datetime "December 25, 2003 9:30", :from => "Time", :suffix_convention => :full_words
@session.click_button
end
it "should select the date and time components with the suffixes provided" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_y" name="appointment[y]">
<option value="2003">2003</option>
</select>
<select id="appointment_time_mo" name="appointment[mo]">
<option value="12">December</option>
</select>
<select id="appointment_time_d" name="appointment[d]">
<option value="25">25</option>
</select>
<select id="appointment_time_h" name="appointment[h]">
<option value="09">09</option>
</select>
: <select id="appointment_time_mi" name="appointment[mi]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"y" => '2003', "mo" => "12", "d" => "25", "h" => "09", "mi" => "30"})
@session.selects_datetime "December 25, 2003 9:30", :from => "Time",
:suffixes => {:year => 'y', :month => 'mo', :day => 'd', :hour => 'h', :minute => 'mi'}
@session.click_button
end
it "should accept a time object" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_1i" name="appointment[time(1i)]">
<option value="2003">2003</option>
</select>
<select id="appointment_time_2i" name="appointment[time(2i)]">
<option value="12">December</option>
</select>
<select id="appointment_time_3i" name="appointment[time(3i)]">
<option value="25">25</option>
</select>
<select id="appointment_time_4i" name="appointment[time(4i)]">
<option value="09">09</option>
</select>
: <select id="appointment_time_5i" name="appointment[time(5i)]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"time(1i)" => '2003', "time(2i)" => "12", "time(3i)" => "25", "time(4i)" => "09", "time(5i)" => "30"})
@session.select_datetime Time.parse("December 25, 2003 9:30"), :from => "Time"
@session.click_button
end
it "should work when no label is specified" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<select id="appointment_time_1i" name="appointment[time(1i)]">
<option value="2003">2003</option>
</select>
<select id="appointment_time_2i" name="appointment[time(2i)]">
<option value="12">December</option>
</select>
<select id="appointment_time_3i" name="appointment[time(3i)]">
<option value="25">25</option>
</select>
<select id="appointment_time_4i" name="appointment[time(4i)]">
<option value="09">09</option>
</select>
: <select id="appointment_time_5i" name="appointment[time(5i)]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"time(1i)" => '2003', "time(2i)" => "12", "time(3i)" => "25", "time(4i)" => "09", "time(5i)" => "30"})
@session.selects_datetime "December 25, 2003 9:30"
@session.click_button
end
it "should fail if the specified label is not found" do
@session.response_body = <<-EOS
<form method="post" action="/appointments">
<select name="month"><option>January</option></select>
<input type="submit" />
</form>
EOS
lambda { @session.selects_datetime "December 25, 2003 9:30", :from => "Time" }.should raise_error
end
end

View File

@ -0,0 +1,114 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
describe "select_time" do
before do
@session = Webrat::TestSession.new
end
it "should send the values for each individual time component" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_4i" name="appointment[time(4i)]">
<option value="09">09</option>
</select>
: <select id="appointment_time_5i" name="appointment[time(5i)]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"time(4i)" => "09", "time(5i)" => "30"})
@session.selects_time "9:30AM", :from => "Time"
@session.click_button
end
it "should select time components with the suffix convention provided" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_hour" name="appointment[hour]">
<option value="09">09</option>
</select>
: <select id="appointment_time_minute" name="appointment[minute]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"hour" => "09", "minute" => "30"})
@session.selects_time "9:30", :from => "Time", :suffix_convention => :full_words
@session.click_button
end
it "should select the time components with the suffixes provided" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_h" name="appointment[h]">
<option value="09">09</option>
</select>
: <select id="appointment_time_mi" name="appointment[mi]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"h" => "09", "mi" => "30"})
@session.selects_time "9:30", :from => "Time",
:suffixes => {:hour => 'h', :minute => 'mi'}
@session.click_button
end
it "should accept a time object" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<label for="appointment_time">Time</label><br />
<select id="appointment_time_4i" name="appointment[time(4i)]">
<option value="09">09</option>
</select>
: <select id="appointment_time_5i" name="appointment[time(5i)]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"time(4i)" => "09", "time(5i)" => "30"})
@session.select_time Time.parse("9:30AM"), :from => "Time"
@session.click_button
end
it "should work when no label is specified" do
@session.response_body = <<-EOS
<form action="/appointments" method="post">
<select id="appointment_time_4i" name="appointment[time(4i)]">
<option value="09">09</option>
</select>
: <select id="appointment_time_5i" name="appointment[time(5i)]">
<option value="30">30</option>
</select>
<input type="submit" />
</form>
EOS
@session.should_receive(:post).with("/appointments",
"appointment" => {"time(4i)" => "09", "time(5i)" => "30"})
@session.select_time "9:30"
@session.click_button
end
it "should fail if the specified label is not found" do
@session.response_body = <<-EOS
<form method="post" action="/appointments">
<select name="month"><option>January</option></select>
<input type="submit" />
</form>
EOS
lambda { @session.select_time "9:30", :from => "Time" }.should raise_error
end
end