honey-do 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/bin/init_selenium_proxy.bat +2 -0
- data/bin/killableprocess.exe +0 -0
- data/demo/page/day_list.html +16 -0
- data/demo/page/everything.html +10 -5
- data/demo/page/everything.js +12 -1
- data/js/user-extensions.js +20 -18
- data/lib/honey_do.rb +3 -2
- data/test/general_form_test.rb +33 -0
- data/test/select_as_text_test.rb +28 -0
- data/test/select_list_test.rb +2 -1
- data/test/submit_test.rb +6 -0
- metadata +7 -2
data/Rakefile
CHANGED
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>HoneyDo Demo Form: Just give it a list!</title>
|
4
|
+
<script language="JavaScript" src="everything.js"></script>
|
5
|
+
</head>
|
6
|
+
<body onload="populate_number_list(day_list_form.elements['day_of_month'],1,31,true);">
|
7
|
+
<div>
|
8
|
+
<form name="day_list_form">
|
9
|
+
<table border="3" bgcolor="beige" cellspacing="1" cellpadding="4">
|
10
|
+
<tr><td>Day of Month:<br><select name="day_of_month"></select></td></tr>
|
11
|
+
<tr><td><input type="reset" value="Reset" name="resetButton"></td></tr>
|
12
|
+
</table>
|
13
|
+
</form>
|
14
|
+
</div>
|
15
|
+
</body>
|
16
|
+
</html>
|
data/demo/page/everything.html
CHANGED
@@ -4,18 +4,20 @@
|
|
4
4
|
<script language="JavaScript" src="everything.js"></script>
|
5
5
|
</head>
|
6
6
|
<body>
|
7
|
+
|
7
8
|
<!-- A one-of-everything HTML form:
|
8
9
|
after David Flanagan, Chapter 18 of "JavaScript: The Definitive Guide", O'Reilly, 5th edition
|
9
10
|
-->
|
10
11
|
<div align="center">
|
11
|
-
<form name="everything" method="POST" action="../display">
|
12
|
+
<form name="everything" method="POST" action="../display" >
|
12
13
|
<table border="3" bgcolor="beige" cellspacing="1" cellpadding="4">
|
13
14
|
<tr>
|
14
|
-
<td colspan="
|
15
|
+
<td colspan="5"><h4>All Possible Form Elements</h4></td>
|
15
16
|
</tr>
|
16
17
|
<tr>
|
17
|
-
<td>
|
18
|
-
<td>
|
18
|
+
<td>Id Only:<br>[1]<input type="text" id="id_not_name" size="5"></td>
|
19
|
+
<td>Username:<br>[1]<input type="text" name="username" id="id_of_username_field" size="15"></td>
|
20
|
+
<td>Password:<br>[2]<input type="password" name="password" size="10"></td>
|
19
21
|
<td rowspan="4">Input Events[3]<br>
|
20
22
|
<textarea name="event_reports_area" rows="20" cols="40"></textarea></td>
|
21
23
|
<td rowspan="4" align="center" valign="center">
|
@@ -25,7 +27,7 @@
|
|
25
27
|
[13]<input type="hidden" value="you can't see this unless you're looking at the source" name="justHiding"><br></td>
|
26
28
|
</tr>
|
27
29
|
<tr>
|
28
|
-
<td colspan="
|
30
|
+
<td colspan="3">
|
29
31
|
Filename: [4]<input type="file" name="file" size="15"> </td>
|
30
32
|
</tr>
|
31
33
|
<tr>
|
@@ -81,6 +83,7 @@
|
|
81
83
|
<option value="gold">Gold
|
82
84
|
<option value="zinc">Zinc
|
83
85
|
</select></td>
|
86
|
+
|
84
87
|
</tr>
|
85
88
|
</table>
|
86
89
|
</form>
|
@@ -110,3 +113,5 @@
|
|
110
113
|
</form>
|
111
114
|
</div>
|
112
115
|
</body>
|
116
|
+
</html>
|
117
|
+
|
data/demo/page/everything.js
CHANGED
@@ -52,4 +52,15 @@ function removehandlers(f) {
|
|
52
52
|
}
|
53
53
|
}
|
54
54
|
|
55
|
-
function selectable(type) { return (/^select/i).test(type);}
|
55
|
+
function selectable(type) { return (/^select/i).test(type);}
|
56
|
+
|
57
|
+
function populate_number_list(theObj,minVal,maxVal) {
|
58
|
+
var selIdx = 0;
|
59
|
+
if (theObj.options.length <= 2) {
|
60
|
+
var idx = theObj.options.length;
|
61
|
+
for (var i=minVal; i<=maxVal; i++) {
|
62
|
+
var label = i;
|
63
|
+
theObj.options[idx++] = new Option(label,i);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
data/js/user-extensions.js
CHANGED
@@ -16,22 +16,25 @@
|
|
16
16
|
|
17
17
|
Form_.FIELD_DELIMITER = '|'
|
18
18
|
Form_.PAIR_DELIMITER = ':::'
|
19
|
+
|
19
20
|
|
20
|
-
Form_.prototype.set_values = function(big_string, ok_if_not_found){
|
21
|
+
Form_.prototype.set_values = function(big_string, ok_if_not_found, select_as_text){
|
21
22
|
var pairs = big_string.split(Form_.FIELD_DELIMITER), pair = [], error_values = '';
|
22
23
|
|
23
24
|
for(var i = 0; i < pairs.length; i++){
|
24
25
|
pair = pairs[i].split(Form_.PAIR_DELIMITER);
|
25
|
-
error_values += this.set_value(pair[0], pair[1], ok_if_not_found);
|
26
|
+
error_values += this.set_value(pair[0], pair[1], ok_if_not_found, select_as_text);
|
26
27
|
}
|
27
28
|
return error_values;
|
28
29
|
}
|
29
30
|
|
30
|
-
Form_.prototype.set_value = function(name, value, ok_if_not_found){
|
31
|
+
Form_.prototype.set_value = function(name, value, ok_if_not_found, select_as_text){
|
31
32
|
var error_text = '', e = null;
|
32
33
|
var selectable = /(select-one|select-multiple)/i;
|
33
34
|
var settable = /(text|textarea|password)/i;
|
34
35
|
var clickable = /(button|submit|reset|radio|image)/i;
|
36
|
+
Form_.SELECT_AS_TEXT = select_as_text;
|
37
|
+
|
35
38
|
try {
|
36
39
|
// if you wanted to do something to explicitly wait for Ajax, you would do it here, before the element lookup
|
37
40
|
e = this.form.elements[name];
|
@@ -94,7 +97,7 @@
|
|
94
97
|
}
|
95
98
|
|
96
99
|
Form_.option_index = function(e, in_value){
|
97
|
-
if (isNaN(parseInt(in_value))) {
|
100
|
+
if (isNaN(parseInt(in_value)) || Form_.SELECT_AS_TEXT) {
|
98
101
|
return Form_.index_of_text(e, in_value);
|
99
102
|
}
|
100
103
|
return in_value; // Todo: 'range' error if index too high
|
@@ -146,10 +149,7 @@
|
|
146
149
|
var e = this.form.elements;
|
147
150
|
for(var i = 0; i < e.length; i++){
|
148
151
|
if (e[i].type != 'hidden') {
|
149
|
-
|
150
|
-
element_list.push(e[i].name);
|
151
|
-
else
|
152
|
-
element_list.push(e[i].value);
|
152
|
+
element_list.push(prop_value(e[i], 'name', 'id', 'value'));
|
153
153
|
}
|
154
154
|
}
|
155
155
|
return element_list;
|
@@ -160,10 +160,7 @@
|
|
160
160
|
var e = this.form.elements;
|
161
161
|
for(var i = 0; i < e.length; i++){
|
162
162
|
if (!e[i].disabled && e[i].type != 'hidden') {
|
163
|
-
|
164
|
-
element_list.push(e[i].name);
|
165
|
-
else
|
166
|
-
element_list.push(e[i].value);
|
163
|
+
element_list.push(prop_value(e[i], 'name', 'id', 'value'));
|
167
164
|
}
|
168
165
|
}
|
169
166
|
return element_list;
|
@@ -173,7 +170,7 @@
|
|
173
170
|
var element_list = [];
|
174
171
|
var e = this.form.elements;
|
175
172
|
for(var i = 0; i < e.length; i++){
|
176
|
-
element_list.push(e[i]
|
173
|
+
element_list.push(prop_value(e[i], 'name', 'id') + '|' + i);
|
177
174
|
}
|
178
175
|
return element_list;
|
179
176
|
}
|
@@ -189,7 +186,7 @@
|
|
189
186
|
|
190
187
|
for(var i = 0;i < e.length; i++){
|
191
188
|
if (target_types.test(e[i].type)) {
|
192
|
-
element_name = e[i]
|
189
|
+
element_name = prop_value(e[i], 'name', 'id');
|
193
190
|
element_text = e[i].value.custom_trim();
|
194
191
|
if ('selectedIndex' in e[i] && e[i].selectedIndex > -1) {
|
195
192
|
if (e[i].type == 'select-multiple') {
|
@@ -239,10 +236,7 @@
|
|
239
236
|
var a = [];
|
240
237
|
var buttons = this.buttons();
|
241
238
|
for(var i = 0; i < buttons.length; i++){
|
242
|
-
|
243
|
-
a.push(buttons[i].name);
|
244
|
-
else
|
245
|
-
a.push(buttons[i].value);
|
239
|
+
a.push(prop_value(buttons[i], 'name', 'id', 'value'));
|
246
240
|
}
|
247
241
|
return a;
|
248
242
|
}
|
@@ -333,6 +327,7 @@
|
|
333
327
|
return this.replace(special_characters, '\\$1');
|
334
328
|
}
|
335
329
|
|
330
|
+
|
336
331
|
/* Stand-alone Functions */
|
337
332
|
function all_form_names(page) {
|
338
333
|
var names = [];
|
@@ -356,4 +351,11 @@
|
|
356
351
|
|
357
352
|
return text_value;
|
358
353
|
}
|
354
|
+
|
355
|
+
// return value of first property found: e.g., prop_value(element, 'name', 'id')
|
356
|
+
function prop_value() {
|
357
|
+
var args = prop_value.arguments;
|
358
|
+
var obj = args[0];
|
359
|
+
for(i=1; i < args.length; i++) { if (obj[args[i]]) return obj[args[i]]}
|
360
|
+
}
|
359
361
|
|
data/lib/honey_do.rb
CHANGED
@@ -27,7 +27,7 @@ module HoneyDo
|
|
27
27
|
# ====HTML +form+ element identifiers
|
28
28
|
# <b><tt>name</tt> attribute</b>:: YES
|
29
29
|
# <b><tt>form.elements</tt> index</b>:: YES
|
30
|
-
# <b><tt>id</tt> attribute</b>::
|
30
|
+
# <b><tt>id</tt> attribute</b>:: YES
|
31
31
|
# <b><tt>value</tt> attribute</b>:: NO
|
32
32
|
#
|
33
33
|
# <b>element names (or indexes) without values get <i>clicked </i></b> if they are
|
@@ -74,6 +74,7 @@ module HoneyDo
|
|
74
74
|
# <b>These aren't usually necessary</b>.
|
75
75
|
# <tt>:form_name_or_index</tt>:: Defaults to 0, because there is usually just one form per page. +String+ or +Integer+
|
76
76
|
# <tt>:ok_if_not_found</tt>:: +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.
|
77
|
+
# <tt>:select_as_text</tt>:: +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.
|
77
78
|
# <tt>:one_field_at_a_time</tt>:: +true+ to use mulitple-call mode. Makes Ruby loop on the list, instead JavaScript, forcing a separate <tt>get_eval</tt> call for each item. Effectively slows it down as a means of handling _Ajax_ refreshes in _Firefox_.
|
78
79
|
# <tt>:retry_max</tt>:: 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+
|
79
80
|
# <tt>:retry_interval</tt>:: To change the default wait time (0.75 seconds) between retries. +Float+
|
@@ -88,7 +89,7 @@ module HoneyDo
|
|
88
89
|
retry_interval = processing_params[:retry_interval] ? processing_params[:retry_interval] : 0.75
|
89
90
|
|
90
91
|
js_open = "dom=new Form_( this, '#{which_form}' )."
|
91
|
-
js_close = ", '#{processing_params[:ok_if_not_found]}' )"
|
92
|
+
js_close = ", '#{processing_params[:ok_if_not_found]}', '#{processing_params[:select_as_text]}' )"
|
92
93
|
errors = ""
|
93
94
|
|
94
95
|
# when input is a single symbol or int
|
data/test/general_form_test.rb
CHANGED
@@ -178,6 +178,39 @@ class TestGeneralInputOptions < Test::Unit::TestCase
|
|
178
178
|
assert_nil(browser.get_form_values[:event_reports_area], "no longer firing events")
|
179
179
|
end
|
180
180
|
|
181
|
+
def test_id_works_for_input_if_no_name_present
|
182
|
+
input_string = "boy look at the size of that"
|
183
|
+
assert_nothing_raised(RuntimeError, "id attribute should be sufficient identifier for HTMLElementCollection") do
|
184
|
+
browser.set_form_values(:id_not_name => input_string)
|
185
|
+
end
|
186
|
+
|
187
|
+
assert_equal(input_string, browser.get_form_values[:id_not_name])
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_id_or_name_equivalent_for_input_on_field_with_both
|
191
|
+
id_text = "id text"
|
192
|
+
name_text = "name is used here"
|
193
|
+
assert_nothing_raised(RuntimeError, "id attribute is ok even when there's a name") do
|
194
|
+
browser.set_form_values(:id_of_username_field => id_text)
|
195
|
+
end
|
196
|
+
|
197
|
+
assert_equal(id_text, browser.get_form_values[:username])
|
198
|
+
|
199
|
+
browser.set_form_values(:username => name_text)
|
200
|
+
|
201
|
+
assert_equal(name_text, browser.get_form_values[:username])
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_name_attribute_trumps_id_attribute
|
205
|
+
input_text = "That song with an apostrophe in it by Spirit"
|
206
|
+
browser.set_form_values(:id_of_username_field => input_text, :id_not_name => input_text)
|
207
|
+
|
208
|
+
values_read_back = browser.get_form_values
|
209
|
+
assert_equal(input_text, values_read_back[:username], "name attribute trumps id attribute")
|
210
|
+
assert_equal(input_text, values_read_back[:id_not_name], "id works because name is not present")
|
211
|
+
assert_nil(values_read_back[:id_of_username_field], "id doesn't work because name is present")
|
212
|
+
end
|
213
|
+
|
181
214
|
protected
|
182
215
|
|
183
216
|
def setup
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_master'
|
2
|
+
|
3
|
+
class TestSelectFeatures < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_select_digit_label_as_text
|
6
|
+
browser.open("day_list.html")
|
7
|
+
|
8
|
+
browser.set_form_values(:day_of_month => 11 )
|
9
|
+
assert_equal("12", browser.get_form_values[:day_of_month], "option selected by index")
|
10
|
+
|
11
|
+
reset
|
12
|
+
browser.set_form_values({:day_of_month => 11}, :select_as_text => true )
|
13
|
+
assert_equal("11", browser.get_form_values[:day_of_month], "option selected by option value")
|
14
|
+
|
15
|
+
reset
|
16
|
+
browser.set_form_values({:day_of_month => :last})
|
17
|
+
assert_equal("31", browser.get_form_values[:day_of_month], "last option selected, safely by index")
|
18
|
+
|
19
|
+
reset
|
20
|
+
browser.set_form_values({:day_of_month => 31}, :select_as_text => true )
|
21
|
+
assert_equal("31", browser.get_form_values[:day_of_month], "option selected by index")
|
22
|
+
|
23
|
+
reset
|
24
|
+
assert_raise(RuntimeError, "index out of bounds: 'e.options[i] has no properties'") do
|
25
|
+
browser.set_form_values({:day_of_month => 31}, :retry_max => 0 )
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/test/select_list_test.rb
CHANGED
@@ -29,7 +29,7 @@ class TestSelectFeatures < Test::Unit::TestCase
|
|
29
29
|
reset_then_set(:color => option_value_property.upcase)
|
30
30
|
assert_equal(option_text_property, browser.get_form_values[:color], "case insensitive")
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# substring match - anchored to ^ (beginning of string); *, ? and + are just text (not wildcards)
|
34
34
|
def test_select_from_droplist_by_substring_match_on_visible_text
|
35
35
|
default_selection = browser.get_form_values[:color]
|
@@ -152,4 +152,5 @@ class TestSelectFeatures < Test::Unit::TestCase
|
|
152
152
|
def reset_then_set_without_retry(input_hash)
|
153
153
|
browser.set_form_values(input_hash.to_a.unshift(:resetButton), :retry_max => 0 )
|
154
154
|
end
|
155
|
+
|
155
156
|
end
|
data/test/submit_test.rb
CHANGED
@@ -54,6 +54,12 @@ class TestSubmitForm < Test::Unit::TestCase
|
|
54
54
|
verify_all_values_persist_on_display_page(submitted_values)
|
55
55
|
end
|
56
56
|
|
57
|
+
def test_fields_with_no_name_not_submitted
|
58
|
+
browser.set_form_values([[:id_not_name, "snooky!"], :submitButton])
|
59
|
+
verify_page_loaded
|
60
|
+
assert_nil( browser.get_cell_ids_and_text[:id_not_name])
|
61
|
+
end
|
62
|
+
|
57
63
|
protected
|
58
64
|
|
59
65
|
def setup
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honey-do
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Camper
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-12-18 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -41,6 +41,7 @@ extra_rdoc_files:
|
|
41
41
|
- test/general_form_test.rb
|
42
42
|
- test/hidden_and_disabled_field_test.rb
|
43
43
|
- test/radio_button_test.rb
|
44
|
+
- test/select_as_text_test.rb
|
44
45
|
- test/select_list_test.rb
|
45
46
|
- test/submit_test.rb
|
46
47
|
- test/test_master.rb
|
@@ -61,6 +62,7 @@ files:
|
|
61
62
|
- test/general_form_test.rb
|
62
63
|
- test/hidden_and_disabled_field_test.rb
|
63
64
|
- test/radio_button_test.rb
|
65
|
+
- test/select_as_text_test.rb
|
64
66
|
- test/select_list_test.rb
|
65
67
|
- test/submit_test.rb
|
66
68
|
- test/test_master.rb
|
@@ -68,10 +70,13 @@ files:
|
|
68
70
|
- demo/display
|
69
71
|
- demo/display/webrick_servlet_needs_this_folder.txt
|
70
72
|
- demo/page
|
73
|
+
- demo/page/day_list.html
|
71
74
|
- demo/page/everything.html
|
72
75
|
- demo/page/everything.js
|
73
76
|
- demo/webrick-servlet.rb
|
74
77
|
- functional_testcase/functional_testcase.rb
|
78
|
+
- bin/init_selenium_proxy.bat
|
79
|
+
- bin/killableprocess.exe
|
75
80
|
- bin/start_selenium_proxy.bat
|
76
81
|
- bin/start_selenium_proxy.sh
|
77
82
|
- js/user-extensions.js
|