honey-do 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|