webrat/lib/webrat/form.rb

140 lines
3.3 KiB
Ruby

module Webrat
class Form
attr_reader :element
def initialize(page, element)
@page = page
@element = element
@fields = nil
end
def find_field(id_or_name_or_label, *field_types)
possible_fields = fields_by_type(field_types)
find_field_by_id(possible_fields, id_or_name_or_label) ||
find_field_by_name(possible_fields, id_or_name_or_label) ||
find_field_by_label(possible_fields, id_or_name_or_label) ||
nil
end
def find_select_option(option_text)
select_fields = fields_by_type([SelectField])
select_fields.each do |select_field|
result = select_field.find_option(option_text)
return result if result
end
nil
end
def find_button(value = nil)
return fields_by_type([ButtonField]).first if value.nil?
possible_buttons = fields_by_type([ButtonField])
possible_buttons.each do |possible_button|
return possible_button if possible_button.matches_value?(value)
end
nil
end
def fields
return @fields if @fields
@fields = []
(@element / "input, textarea, select, button").each do |field_element|
@fields << Field.class_for_element(field_element).new(self, field_element)
end
@fields
end
def submit
Page.new(@page.session, form_action, form_method, params)
end
protected
def find_field_by_id(possible_fields, id)
possible_fields.each do |possible_field|
return possible_field if possible_field.matches_id?(id)
end
nil
end
def find_field_by_name(possible_fields, name)
possible_fields.each do |possible_field|
return possible_field if possible_field.matches_name?(name)
end
nil
end
def find_field_by_label(possible_fields, label)
matching_fields = []
possible_fields.each do |possible_field|
matching_fields << possible_field if possible_field.matches_label?(label)
end
matching_fields.sort_by { |f| f.label_text.length }.first
end
def fields_by_type(field_types)
fields.select { |f| field_types.include?(f.class) }
end
def params
all_params = {}
fields.each do |field|
next if field.to_param.nil?
merge(all_params, field.to_param)
end
all_params
end
def form_method
@element["method"].blank? ? :get : @element["method"].downcase
end
def form_action
@element["action"].blank? ? @page.url : @element["action"]
end
def merge(all_params, new_param)
new_param.each do |key, value|
case all_params[key]
when Hash, HashWithIndifferentAccess
merge_hash_values(all_params[key], value)
when Array
all_params[key] += value
else
all_params[key] = value
end
end
end
def merge_hash_values(a, b) # :nodoc:
a.keys.each do |k|
if b.has_key?(k)
case [a[k], b[k]].map(&:class)
when [Hash, Hash]
a[k] = merge_hash_values(a[k], b[k])
b.delete(k)
when [Array, Array]
a[k] += b[k]
b.delete(k)
end
end
end
a.merge!(b)
end
end
end