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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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.



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

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



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

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.



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

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



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

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



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

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.

:select_exact_match

true to match entire droplist value (text or value attribute), overriding default substring match.

: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


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

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]}', '#{processing_params[:select_exact_match]}' )"
  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