Module: HoneyDo

Included in:
Selenium::SeleniumDriver
Defined in:
lib/honey_do.rb

Overview

Just give it a list!

set_form_values provides a simple, consistent interface to any collection of HTML form elements.

  • Set one or many values and click one or many controls with one call

  • No element type or “action” command is ever needed

  • List can be a Ruby string, array, hash, or symbol

  • Freely mix name/value pairs with just names, at your convenience

  • Event handlers are fired normally, and Ajax calls just seem to work

get_form_values and other methods provide simple, consistent means of reading all form data at once

user-extensions.js

  • class Form_ enables passing collections to and from HTML forms.

  • class Table_ provides a couple of HTML table readers, which return collections of cell values. Non-form HTML is not at all generic so this isn’t fleshed out for the release version. It’s included mostly for demo purposes.

Instance Method Summary collapse

Instance Method Details

#checkbox_count(form_name_or_index = 0) ⇒ Object

HTML element count of checkboxes



164
165
166
# File 'lib/honey_do.rb', line 164

def checkbox_count(form_name_or_index = 0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').type_count('checkbox')").to_i
end

#clear_checkboxes(form_name_or_index = 0) ⇒ Object



154
155
156
# File 'lib/honey_do.rb', line 154

def clear_checkboxes(form_name_or_index = 0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').clear_checkboxes()")
end

#get_all_button_names(form_name_or_index = 0) ⇒ Object



133
134
135
# File 'lib/honey_do.rb', line 133

def get_all_button_names(form_name_or_index=0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').all_button_names()")
end

#get_all_cell_text(table_id_or_index) ⇒ Object

table reader - returns comma delimited string of all <td> text



180
181
182
183
# File 'lib/honey_do.rb', line 180

def get_all_cell_text(table_id_or_index)
  js = "dom=new Table_(this, '#{table_id_or_index}').all_cell_text()"
  get_eval(js)
end

#get_all_checkbox_names(form_name_or_index = 0) ⇒ Object



142
143
144
# File 'lib/honey_do.rb', line 142

def get_all_checkbox_names(form_name_or_index = 0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').checkbox_names()")
end

#get_all_checked(form_name_or_index = 0) ⇒ Object



150
151
152
# File 'lib/honey_do.rb', line 150

def get_all_checked(form_name_or_index = 0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').all_checked()").split(',')
end

#get_all_form_namesObject

comma delimited list of form names. could include index value if no name attribute on the form



169
170
171
# File 'lib/honey_do.rb', line 169

def get_all_form_names
  get_eval("dom=all_form_names(this)")
end

#get_cell_ids_and_text(table_id_or_index = 0) ⇒ Object

table reader - hash of <td> id’s and text for cells that have text



174
175
176
177
# File 'lib/honey_do.rb', line 174

def get_cell_ids_and_text(table_id_or_index=0)
  js = "dom=new Table_(this, '#{table_id_or_index}').all_cell_ids_and_text()"
  to_hash(get_eval(js)).keys_to_sym
end

#get_checkbox_name_by_pattern(form_name, name_pattern) ⇒ Object

given a javascript friendly regex, returns the first matching name



138
139
140
# File 'lib/honey_do.rb', line 138

def get_checkbox_name_by_pattern(form_name, name_pattern)
  get_eval("dom=new Form_(this, '#{form_name}').first_checkbox(#{name_pattern})").to_sym
end

#get_droplist_size(element_name, form_name_or_index = 0) ⇒ Object



146
147
148
# File 'lib/honey_do.rb', line 146

def get_droplist_size(element_name, form_name_or_index = 0)
   get_eval("dom=new Form_(this, '#{form_name_or_index}').droplist_size('#{element_name}')").to_i
end

#get_enabled_form_elements(form_name_or_index = 0) ⇒ Object

gets comma separated list of non-hidden, non-disabled form element names



129
130
131
# File 'lib/honey_do.rb', line 129

def get_enabled_form_elements(form_name_or_index=0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').enabled_elements()")
end

#get_form_element_indexes(form_name_or_index = 0) ⇒ Object

table (nested array) of element names and indices. 0 based because the DOM is.



121
122
123
124
125
126
# File 'lib/honey_do.rb', line 121

def get_form_element_indexes(form_name_or_index=0)
  element_index_table = []
  element_indexes = get_eval("dom=new Form_(this, '#{form_name_or_index}').element_indexes()").split(',')
  element_indexes.each {|item| element_index_table << item.split(FIELD_DELIMITER)}
  return element_index_table
end

#get_form_elements(form_name_or_index = 0) ⇒ Object

gets comma separated list of non-hidden form element names



116
117
118
# File 'lib/honey_do.rb', line 116

def get_form_elements(form_name_or_index=0)
  get_eval("dom=new Form_(this, '#{form_name_or_index}').visible_elements()")
end

#get_form_values(form_name_or_index = 0) ⇒ Object

hash map of element names to values, but only for those elements that have values.



110
111
112
113
# File 'lib/honey_do.rb', line 110

def get_form_values(form_name_or_index=0)
  js = "dom=new Form_(this, '#{form_name_or_index}').values()"
  to_hash(get_eval(js)).keys_to_sym
end

#get_table_size(table_id_or_index) ⇒ Object

HTML table row count



186
187
188
# File 'lib/honey_do.rb', line 186

def get_table_size(table_id_or_index)
  get_eval("dom=new Table_(this, '#{table_id_or_index}').size()").to_i
end

#set_all_checkboxes(form_name_or_index = 0) ⇒ Object



158
159
160
161
# File 'lib/honey_do.rb', line 158

def set_all_checkboxes(form_name_or_index = 0)
  clear_checkboxes
  get_eval("dom=new Form_(this, '#{form_name_or_index}').set_checkboxes()")
end

#set_form_values(input_list, processing_params = {}) ⇒ Object

input_list

  • meant to be flexible and tolerant so you can code your data in whatever way is handy to the situation

  • any mix of HTML form element names and pairs of element names and values.

  • can be a single string, single symbol, single integer, hash map, or array consisting of any number of strings, symbols, or 2 element arrays

HTML form element identifiers

name attribute

YES

form.elements index

YES

id attribute

YES

value attribute

NO

element names (or indexes) without values get clicked if they are

clickable

button, submit, reset, radio, checkbox

sel.set_form_values(:clearButton)

sel.set_form_values([:includeDocuments_cb, :requireSig_cb])

sel.set_form_values("resetButton")

sel.set_form_values(0)

element names (or indexes) with values get set if they are

  1. settable: text, textarea, password

  2. selectable: select-one, select-mulitple

  3. a grouped item with a value: checkbox, radio

    sel.set_form_values(:city => "Appleton")
    
    sel.set_form_values(:dealerid => "Foster-Stevens", :includeDocuments_cb => :check)
    
    sel.set_form_values(:state => "IL", :street_1 => "113 Foo St.", :city => "Sandwich", :zip => 60548, :same_as_shipping => true)
    
    sel.set_form_values(:color => 8,
                    :hobbies => "hacking",
                    :username => "ernie",  
                    :password => "bert",  
                    :further_description => "Test Input String blah " * 50,
                    :extras => 1,
                    :browser => "safari")
    

values for clickable elements are ignored. They are useless but harmless.

sel.set_form_values(:clearButton => "Clear")  

sel.set_form_values(3 => "Clear")

"Clear" is the element’s value attribute (or visible text) and is ignored in both cases. :clearButton is the name attribute and is used; 3 is the element’s index (within form.elements) and would also be used.

input as array guarantees input order and allows us to mix in clickables without dummy values

sel.set_form_values([[:search_customer_name, "Foster"], [:search_customer_city, "Wentworth"], :submitSearchForm])

processing_params

These aren’t usually necessary.

:form_name_or_index

Defaults to 0, because there is usually just one form per page. String or Integer

:ok_if_not_found

true to swallow the error, nil/false/null if not present (the default). Useful for testing multiple versions of your app when names have changed, or widgets have been added or removed.

:select_as_text

true to force droplist values to be treated as text, even if they are digits nil/false/null if not present (the default). Useful when the visible option text is a number (e.g., “day of month” lists). Without it, the input is taken to an index.

:one_field_at_a_time

true to use mulitple-call mode. Makes Ruby loop on the list, instead JavaScript, forcing a separate get_eval call for each item. Effectively slows it down as a means of handling Ajax refreshes in Firefox.

:retry_max

0 or 1 to not retry at all. Anything > 2 (the default, which means 1 try and 1 retry) is probably useless, but I don’t know your app. Integer

:retry_interval

To change the default wait time (0.75 seconds) between retries. Float

Make sure your input_list items and processing_params are in separate data structures in the arg list

sel.set_form_values(:search_customer_name => "Foster", :form_name_or_index => "form_2")  # WRONG!  that's a 2-item input list

sel.set_form_values({:search_customer_name => "Foster"}, :form_name_or_index => "form_2")  # RIGHT!  Ruby will make the 2nd hash for you


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/honey_do.rb', line 86

def set_form_values(input_list, processing_params = {})
  which_form     = processing_params[:form_name_or_index] ? processing_params[:form_name_or_index] : 0
  retry_max      = processing_params[:retry_max] ? processing_params[:retry_max] : 2
  retry_interval = processing_params[:retry_interval] ? processing_params[:retry_interval] : 0.75

  js_open  = "dom=new Form_( this, '#{which_form}' )." 
  js_close = ", '#{processing_params[:ok_if_not_found]}', '#{processing_params[:select_as_text]}' )"
  errors   = ""

  # when input is a single symbol or int

  input_list = input_list.to_s if [Symbol, Fixnum].include?(input_list.class)
  
  re_try(retry_max, retry_interval) do 
    if processing_params[:one_field_at_a_time]
      # we can be a hash, array, or string here: 'each' with a single |arg| treats us as an array.

      input_list.each { |pair| errors << get_eval(js_open + "set_value( #{pair_to_args(pair)}" + js_close) }
    else
      errors = get_eval(js_open + "set_values( '#{list_to_big_string(input_list)}'" + js_close)
    end
    raise_js_errors(errors)
  end
end