-
Notifications
You must be signed in to change notification settings - Fork 5
/
FoneMonkey.jslib
251 lines (217 loc) · 9.28 KB
/
FoneMonkey.jslib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/* This file is part of FoneMonkey.
FoneMonkey is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FoneMonkey is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FoneMonkey. If not, see <http://www.gnu.org/licenses/>. */
//
// FoneMonkey.js
// FoneMonkey
//
// Copyright 2011 Gorilla Logic, Inc. All rights reserved.
//
/** @namespace <a href="http://www.gorillalogic.com/fonemonkey">FoneMonkey</a> helper function library for iOS <a href="http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/_index.html">UIAutomation</a> scripting
@author Gorilla Logic, Inc. - <a href="http://www.gorillalogic.com">www.gorillalogic.com</>
@see <a href="http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/_index.html">UIAutomation Reference</a>, <a href="http://www.gorillalogic.com/fonemonkey">FoneMonkey Project Home</a>
*/
var FoneMonkey = {
/** @private */
debugEnabled:false,
/** @private */
debug: function(msg) {
if (this.debugEnabled) {
UIALogger.logMessage(msg);
}
},
/** Search the component tree for the element with the supplied name until found or timeout
@returns {UIAElement} the found element or UIAElementNil if no element is found before the timeout occurs
@param {String} name the name of the element to search for
@param {Number} [timeout=UIATarget.localTarget().timeout()] the maximum time, in seconds, to wait for the element to appear
*/
elementNamed: function(name, timeout) {
var start = (new Date()).getTime();
if (!timeout) {
timeout = UIATarget.localTarget().timeout();
}
this.debug("Searching for " + name);
var result;
while (((new Date()).getTime() - start) < (timeout * 1000) || timeout == 0) {
result = this.searchElements(UIATarget.localTarget().frontMostApp().mainWindow(), name, "name");
if (!this.isNil(result)) {
this.debug("searchElements returned " + result.toString());
UIATarget.localTarget().delay(.5); // A little throttling to allow UI to catch up
return result;
}
if (timeout == 0) {
break;
}
}
UIALogger.logFail("Unable to find element named " + name);
return result;
},
/** Scroll the UITableView with the supplied name to the supplied group and item number
@param {String} tableName the name of the UITableView to scroll
@param {Number} [item=0] the position number of the item to scroll to
@param {Number} [group=0] the position of the group to scroll to
@param {Number} [timeout=UIATarget.localTarget().timeout()] the maximum time, in seconds, to wait for the UITableView to appear
*/
scrollTo: function(tableName, item, group, timeout) {
var table = FoneMonkey.elementNamed(tableName, timeout);
var grp;
var grps = table.groups();
if (grps.length) {
grp = table.groups()[group];
} else {
grp = table.cells();
}
var itm = grp[item];
itm.logElement();
table.scrollToElementWithName(itm.name());
},
/** Scroll the UIPickerView with the supplied name to the supplied row number of the supplied component number
@param {String} pickerName the name of the UIPickerView to select from
@param {Number} [row=0] the position number of the row to select
@param {Number} [component=0] the position of the component containing the row
@param {Number} [timeout=UIATarget.localTarget().timeout()] the maximum time, in seconds, to wait for the UIPickerView to appear
*/
selectPickerValue: function(pickerName, row, component, timeout) {
var picker = FoneMonkey.elementNamed(pickerName, timeout);
return this.movePicker(picker, component, row);
var wheels = picker.wheels();
var wheel = wheels[component];
var values = wheel.values();
var itm = values[row];
// errors out, see ed's apple bug #8826533 - ejs Jan 2011
wheel.selectValue(itm);
},
/** Toggle the UISwitch with the supplied name
@param {String} switchName the name of the UISwitch to toggle
@param {Number} [timeout=UIATarget.localTarget().timeout()] the maximum time, in seconds, to wait for the UISwitch to appear
*/
toggleSwitch: function(switchName, timeout) {
swtch = this.elementNamed(switchName, timeout);
val = swtch.value();
swtch.setValue(!val);
},
/** @private */
searchElements: function(elem, value, key) {
//this.debug("checking " + elems.length + " kids");
//var result = elems.firstWithValueForKey(value, key);
try {
UIATarget.localTarget().pushTimeout(0);
this.debug("checking " + Object.prototype.toString.call(elem) + " elem.name()=\"" + elem.name() + "\" elem.value()=\"" + elem.value() + "\" value=\"" + value + "\" key=\"" + key + "\"");
var result = elem.withValueForKey(value, key);
if (!this.isNil(result)) {
this.debug("returning " + result.toString());
return result;
}
var elems = elem.elements();
this.debug("checking " + elems.length + " children" );
var i;
for (i = 0; i < elems.length; i++) {
var child = elems[i];
result = this.searchElements(child, value, key);
if (!this.isNil(result)) {
this.debug("returning child of " + elem.name());
return result;
}
}
this.debug(value + " not found in children of " + elem.name());
return result;
} finally {
UIATarget.localTarget().popTimeout();
}
},
/** Tests if the supplied element is UIAElementNil
@param {UIAElement} element the element to test
@returns {Boolean} true if the supplied element is UIAElementNil
*/
isNil: function(element) {
return (element.toString() == "[object UIAElementNil]");
},
/** Log <span style="color:green; font-weight:bold">Pass</span> if an element with the supplied name and value is found before the supplied timeout occurs, and log <span style="color:red; font-weight:bold">Fail</span> otherwise
@param {String} name the name of the element to search for
@param {String} value the value of the element to search for
@param {Number} [timeout=UIATarget.localTarget().timeout()] the maximum time, in seconds, to wait for the element and value to appear
*/
assertElementValue: function(name, value, timeout) {
var start = (new Date()).getTime();
//if (element && element.withPredicate("value == \"" + expected + "\"").name() != element.name()) {
if (!timeout) {
timeout = UIATarget.localTarget().timeout();
}
var element = FoneMonkey.elementNamed(name, timeout);
if (this.isNil(element)) {
return;
}
while (((new Date()).getTime() - start) < (timeout * 1000) || timeout == 0) {
if (element.value() == value) {
UIALogger.logPass(element.name() + " had expected value '" + value + " '");
return;
}
if (timeout == 0) {
break;
}
//UIATarget.localTarget().delay(.1);
}
UIALogger.LogFail("Verify failed for Component '" + element.name() + "' property 'value': expected '" + value + "', but found " + element.value());
return;
},
/** Log <span style="color:green; font-weight:bold">Pass</span> if an element with the supplied name is found before the supplied timeout occurs, and log <span style="color:red; font-weight:bold">Fail</span> otherwise
@param {String} name the name of the element to search for
@param {Number} [timeout=UIATarget.localTarget().timeout()] the maximum time, in seconds, to wasit for the element to appear
*/
assertElement: function(name, timeout) {
var element = FoneMonkey.elementNamed(name, timeout);
if (this.isNil(element)) {
UIALogger.logFail("Verify failed. Element '" + name + "' not found.");
} else {
UIALogger.logPass(name + " found.");
}
},
// adapted from Apple Developer Forum Post at
// https://devforums.apple.com/message/242678#242678
// This will move a picker index
/** @private */
movePicker: function(picker, pickerIndex, indexInPicker) {
// Verify it is valid
if (!picker.isValid()) {
// Not valid for whatever reason
return false;
} // if
var startPicker=picker.wheels()[pickerIndex];
var itemCount=startPicker.values().length;
// The height of a picker item in our application
var HEIGHT_OF_PICKER_ITEMS = 40;
// Grab the hit point of this object. This will be the exact center of the
// picker
var hitPoint = startPicker.hitpoint();
// Keep this the same
var hitPointX = hitPoint.x;
// go to the top of the picker (select the topmost item)
// This will move us to the previous picker item, if there is one
var hitPointY = hitPoint.y - HEIGHT_OF_PICKER_ITEMS;
for (var xx=0; xx<itemCount; xx++) {
// Tap on the next item
UIATarget.localTarget().tapWithOptions({x:hitPointX, y:hitPointY}, {touchCount:1, tapCount:1});
// Allow the picker to render itself
UIATarget.localTarget().delay(1);
} // for
// go to the top of the picker (select the topmost item)
// This will move us to the desired picker item, if there is one
hitPointY = hitPoint.y + HEIGHT_OF_PICKER_ITEMS;
for (var i = 0; i < indexInPicker; i++) {
// Tap on the next item
UIATarget.localTarget().tapWithOptions({x:hitPointX, y:hitPointY}, {touchCount:1, tapCount:1});
// Allow the picker to render itself
UIATarget.localTarget().delay(1);
} // for
// We performed our action successfully
return true;
} // movePicker
}