angular_webdriver 0.0.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +32 -0
  6. data/Gemfile +2 -0
  7. data/Thorfile +33 -1
  8. data/angular_webdriver.gemspec +10 -3
  9. data/docs/overview.md +101 -0
  10. data/docs/sync.md +53 -0
  11. data/lib/angular_webdriver/protractor/by.rb +331 -0
  12. data/lib/angular_webdriver/protractor/by_repeater_inner.rb +106 -0
  13. data/lib/angular_webdriver/protractor/client_side_scripts.rb +1035 -0
  14. data/lib/angular_webdriver/protractor/protractor.rb +396 -77
  15. data/lib/angular_webdriver/protractor/protractor_element.rb +33 -0
  16. data/lib/angular_webdriver/protractor/rspec_helpers.rb +19 -0
  17. data/lib/angular_webdriver/protractor/watir_patch.rb +209 -0
  18. data/lib/angular_webdriver/protractor/webdriver_patch.rb +246 -0
  19. data/lib/angular_webdriver/version.rb +2 -2
  20. data/lib/angular_webdriver.rb +14 -1
  21. data/{LICENSE → license/angular_webdriver/LICENSE.txt} +0 -0
  22. data/{lib/angular_webdriver → license}/protractor/LICENSE.txt +0 -0
  23. data/{lib/angular_webdriver/protractor/get_url_trace.rb → notes/bootstrap_notes.md} +13 -0
  24. data/notes/element_by_id/element_by_id_sync_off.txt +12 -0
  25. data/notes/element_by_id/element_by_id_sync_on.txt +74 -0
  26. data/notes/element_chaining_debug.txt +94 -0
  27. data/notes/evaluate/js_evaluate_sync_on.txt +60 -0
  28. data/notes/evaluate/ruby_evaluate_sync_on.txt +35 -0
  29. data/notes/get_title/browser_get_title_sync_off.txt +11 -0
  30. data/notes/get_title/browser_get_title_sync_on.txt +54 -0
  31. data/notes/phantomjs.md +23 -0
  32. data/notes/protractor_cli_bugs.txt +39 -0
  33. data/notes/protractor_get/protractor_get.rb +102 -0
  34. data/notes/protractor_get/protractor_get_website_sync_off.txt +11 -0
  35. data/notes/protractor_get/protractor_get_website_sync_on.txt +86 -0
  36. data/notes/repeater/findAllRepeaterRows_annotated.txt +150 -0
  37. data/notes/repeater/findAllRepeaterRows_raw.txt +145 -0
  38. data/notes/repeater/findRepeaterColumn_annotated.txt +317 -0
  39. data/notes/repeater/findRepeaterColumn_raw.txt +310 -0
  40. data/notes/repeater/findRepeaterElement_annotated.txt +152 -0
  41. data/notes/repeater/findRepeaterElement_raw.txt +146 -0
  42. data/notes/repeater/findRepeaterRows_annotated.txt +156 -0
  43. data/notes/repeater/findRepeaterRows_raw.txt +152 -0
  44. data/notes/sync_after.md +46 -0
  45. data/notes/sync_notes.md +137 -0
  46. data/notes/synchronize_spec/status_gettext.txt +121 -0
  47. data/notes/synchronize_spec/status_gettext_x3.txt +451 -0
  48. data/notes/synchronize_spec/synchronize_spec.js.txt +74 -0
  49. data/notes/synchronize_spec/watir_gettext.txt +73 -0
  50. data/readme.md +52 -12
  51. data/release_notes.md +127 -0
  52. data/selenium_server/lib/logs.rb +50 -0
  53. data/selenium_server/lib/selenium_server.rb +21 -0
  54. data/selenium_server/readme.md +3 -0
  55. data/selenium_server/spec/logs_spec.rb +18 -0
  56. data/selenium_server/spec/nodejs_sync_spec_waithttp_annotated.txt +54 -0
  57. data/selenium_server/spec/nodejs_sync_spec_waithttp_raw.txt +367 -0
  58. data/selenium_server/spec/nodejs_sync_spec_waithttp_raw_processed.txt +43 -0
  59. data/selenium_server/spec/ruby_sync_spec_waithttp_annotated.txt +59 -0
  60. data/selenium_server/spec/ruby_sync_spec_waithttp_raw.txt +267 -0
  61. data/selenium_server/spec/ruby_sync_spec_waithttp_raw_processed.txt +39 -0
  62. data/selenium_server/spec/spec_helper.rb +6 -0
  63. data/selenium_server/spec/status_gettext_x3.txt +429 -0
  64. data/selenium_server/spec/status_gettext_x3_annotated.txt +86 -0
  65. metadata +91 -18
  66. data/lib/angular_webdriver/protractor/clientSideScripts.json +0 -19
  67. data/lib/angular_webdriver/protractor/clientsidescripts.js +0 -671
  68. data/lib/angular_webdriver/protractor/scripts.rb +0 -7
  69. data/lib/angular_webdriver/protractor/scripts_to_json.js +0 -11
  70. data/spec/protractor_spec.rb +0 -40
  71. data/spec/spec_helper.rb +0 -5
@@ -0,0 +1,1035 @@
1
+ module ClientSideScripts
2
+
3
+ # class methods
4
+
5
+ def self.scripts
6
+ @@client_side_scripts
7
+ end
8
+
9
+ def self.wait_for_angular
10
+ @@client_side_scripts[:waitForAngular]
11
+ end
12
+
13
+ def self.find_bindings
14
+ @@client_side_scripts[:findBindings]
15
+ end
16
+
17
+ def self.find_repeater_rows
18
+ @@client_side_scripts[:findRepeaterRows]
19
+ end
20
+
21
+ def self.find_all_repeater_rows
22
+ @@client_side_scripts[:findAllRepeaterRows]
23
+ end
24
+
25
+ def self.find_repeater_element
26
+ @@client_side_scripts[:findRepeaterElement]
27
+ end
28
+
29
+ def self.find_repeater_column
30
+ @@client_side_scripts[:findRepeaterColumn]
31
+ end
32
+
33
+ def self.find_by_model
34
+ @@client_side_scripts[:findByModel]
35
+ end
36
+
37
+ def self.find_by_options
38
+ @@client_side_scripts[:findByOptions]
39
+ end
40
+
41
+ def self.find_by_button_text
42
+ @@client_side_scripts[:findByButtonText]
43
+ end
44
+
45
+ def self.find_by_partial_button_text
46
+ @@client_side_scripts[:findByPartialButtonText]
47
+ end
48
+
49
+ def self.find_by_css_containing_text
50
+ @@client_side_scripts[:findByCssContainingText]
51
+ end
52
+
53
+ def self.test_for_angular
54
+ @@client_side_scripts[:testForAngular]
55
+ end
56
+
57
+ def self.evaluate
58
+ @@client_side_scripts[:evaluate]
59
+ end
60
+
61
+ def self.allow_animations
62
+ @@client_side_scripts[:allowAnimations]
63
+ end
64
+
65
+ def self.get_location_abs_url
66
+ @@client_side_scripts[:getLocationAbsUrl]
67
+ end
68
+
69
+ def self.set_location
70
+ @@client_side_scripts[:setLocation]
71
+ end
72
+
73
+ def self.install_in_browser
74
+ @@client_side_scripts[:installInBrowser]
75
+ end
76
+
77
+ @@client_side_scripts = {
78
+ waitForAngular: %q(try { return (function (rootSelector, callback) {
79
+ var el = document.querySelector(rootSelector);
80
+
81
+ try {
82
+ if (!window.angular) {
83
+ throw new Error('angular could not be found on the window');
84
+ }
85
+ if (angular.getTestability) {
86
+ angular.getTestability(el).whenStable(callback);
87
+ } else {
88
+ if (!angular.element(el).injector()) {
89
+ throw new Error('root element (' + rootSelector + ') has no injector.' +
90
+ ' this may mean it is not inside ng-app.');
91
+ }
92
+ angular.element(el).injector().get('$browser').
93
+ notifyWhenNoOutstandingRequests(callback);
94
+ }
95
+ } catch (err) {
96
+ callback(err.message);
97
+ }
98
+ }).apply(this, arguments); }
99
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
100
+ findBindings: %q(try { return (function (binding, exactMatch, using, rootSelector) {
101
+ var root = document.querySelector(rootSelector || 'body');
102
+ using = using || document;
103
+ if (angular.getTestability) {
104
+ return angular.getTestability(root).
105
+ findBindings(using, binding, exactMatch);
106
+ }
107
+ var bindings = using.getElementsByClassName('ng-binding');
108
+ var matches = [];
109
+ for (var i = 0; i < bindings.length; ++i) {
110
+ var dataBinding = angular.element(bindings[i]).data('$binding');
111
+ if (dataBinding) {
112
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
113
+ if (exactMatch) {
114
+ var matcher = new RegExp('({|\\\\s|^|\\\\|)' +
115
+ /* See http://stackoverflow.com/q/3561711 */
116
+ binding.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, '\\\\$&') +
117
+ '(}|\\\\s|$|\\\\|)');
118
+ if (matcher.test(bindingName)) {
119
+ matches.push(bindings[i]);
120
+ }
121
+ } else {
122
+ if (bindingName.indexOf(binding) != -1) {
123
+ matches.push(bindings[i]);
124
+ }
125
+ }
126
+
127
+ }
128
+ }
129
+ return matches; /* Return the whole array for webdriver.findElements. */
130
+ }).apply(this, arguments); }
131
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
132
+ findRepeaterRows: %q(try { return (function (repeater, exact, index, using) {
133
+ function repeaterMatch(ngRepeat, repeater, exact) {
134
+ if (exact) {
135
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
136
+ trim() == repeater;
137
+ } else {
138
+ return ngRepeat.indexOf(repeater) != -1;
139
+ }
140
+ }
141
+
142
+ using = using || document;
143
+
144
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
145
+ var rows = [];
146
+ for (var p = 0; p < prefixes.length; ++p) {
147
+ var attr = prefixes[p] + 'repeat';
148
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
149
+ attr = attr.replace(/\\\\/g, '');
150
+ for (var i = 0; i < repeatElems.length; ++i) {
151
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
152
+ rows.push(repeatElems[i]);
153
+ }
154
+ }
155
+ }
156
+ /* multiRows is an array of arrays, where each inner array contains
157
+ one row of elements. */
158
+ var multiRows = [];
159
+ for (var p = 0; p < prefixes.length; ++p) {
160
+ var attr = prefixes[p] + 'repeat-start';
161
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
162
+ attr = attr.replace(/\\\\/g, '');
163
+ for (var i = 0; i < repeatElems.length; ++i) {
164
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
165
+ var elem = repeatElems[i];
166
+ var row = [];
167
+ while (elem.nodeType != 8 ||
168
+ !repeaterMatch(elem.nodeValue, repeater, exact)) {
169
+ if (elem.nodeType == 1) {
170
+ row.push(elem);
171
+ }
172
+ elem = elem.nextSibling;
173
+ }
174
+ multiRows.push(row);
175
+ }
176
+ }
177
+ }
178
+ var row = rows[index] || [], multiRow = multiRows[index] || [];
179
+ return [].concat(row, multiRow);
180
+ }).apply(this, arguments); }
181
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
182
+ findAllRepeaterRows: %q(try { return (function (repeater, exact, using) {
183
+ function repeaterMatch(ngRepeat, repeater, exact) {
184
+ if (exact) {
185
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
186
+ trim() == repeater;
187
+ } else {
188
+ return ngRepeat.indexOf(repeater) != -1;
189
+ }
190
+ }
191
+
192
+ using = using || document;
193
+
194
+ var rows = [];
195
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
196
+ for (var p = 0; p < prefixes.length; ++p) {
197
+ var attr = prefixes[p] + 'repeat';
198
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
199
+ attr = attr.replace(/\\\\/g, '');
200
+ for (var i = 0; i < repeatElems.length; ++i) {
201
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
202
+ rows.push(repeatElems[i]);
203
+ }
204
+ }
205
+ }
206
+ for (var p = 0; p < prefixes.length; ++p) {
207
+ var attr = prefixes[p] + 'repeat-start';
208
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
209
+ attr = attr.replace(/\\\\/g, '');
210
+ for (var i = 0; i < repeatElems.length; ++i) {
211
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
212
+ var elem = repeatElems[i];
213
+ while (elem.nodeType != 8 ||
214
+ !repeaterMatch(elem.nodeValue, repeater, exact)) {
215
+ if (elem.nodeType == 1) {
216
+ rows.push(elem);
217
+ }
218
+ elem = elem.nextSibling;
219
+ }
220
+ }
221
+ }
222
+ }
223
+ return rows;
224
+ }).apply(this, arguments); }
225
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
226
+ findRepeaterElement: %q(try { return (function (repeater, exact, index, binding, using, rootSelector) {
227
+ function repeaterMatch(ngRepeat, repeater, exact) {
228
+ if (exact) {
229
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
230
+ trim() == repeater;
231
+ } else {
232
+ return ngRepeat.indexOf(repeater) != -1;
233
+ }
234
+ }
235
+
236
+ var matches = [];
237
+ var root = document.querySelector(rootSelector || 'body');
238
+ using = using || document;
239
+
240
+ var rows = [];
241
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
242
+ for (var p = 0; p < prefixes.length; ++p) {
243
+ var attr = prefixes[p] + 'repeat';
244
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
245
+ attr = attr.replace(/\\\\/g, '');
246
+ for (var i = 0; i < repeatElems.length; ++i) {
247
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
248
+ rows.push(repeatElems[i]);
249
+ }
250
+ }
251
+ }
252
+ /* multiRows is an array of arrays, where each inner array contains
253
+ one row of elements. */
254
+ var multiRows = [];
255
+ for (var p = 0; p < prefixes.length; ++p) {
256
+ var attr = prefixes[p] + 'repeat-start';
257
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
258
+ attr = attr.replace(/\\\\/g, '');
259
+ for (var i = 0; i < repeatElems.length; ++i) {
260
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
261
+ var elem = repeatElems[i];
262
+ var row = [];
263
+ while (elem.nodeType != 8 || (elem.nodeValue &&
264
+ !repeaterMatch(elem.nodeValue, repeater, exact))) {
265
+ if (elem.nodeType == 1) {
266
+ row.push(elem);
267
+ }
268
+ elem = elem.nextSibling;
269
+ }
270
+ multiRows.push(row);
271
+ }
272
+ }
273
+ }
274
+ var row = rows[index];
275
+ var multiRow = multiRows[index];
276
+ var bindings = [];
277
+ if (row) {
278
+ if (angular.getTestability) {
279
+ matches.push.apply(
280
+ matches,
281
+ angular.getTestability(root).findBindings(row, binding));
282
+ } else {
283
+ if (row.className.indexOf('ng-binding') != -1) {
284
+ bindings.push(row);
285
+ }
286
+ var childBindings = row.getElementsByClassName('ng-binding');
287
+ for (var i = 0; i < childBindings.length; ++i) {
288
+ bindings.push(childBindings[i]);
289
+ }
290
+ }
291
+ }
292
+ if (multiRow) {
293
+ for (var i = 0; i < multiRow.length; ++i) {
294
+ var rowElem = multiRow[i];
295
+ if (angular.getTestability) {
296
+ matches.push.apply(
297
+ matches,
298
+ angular.getTestability(root).findBindings(rowElem, binding));
299
+ } else {
300
+ if (rowElem.className.indexOf('ng-binding') != -1) {
301
+ bindings.push(rowElem);
302
+ }
303
+ var childBindings = rowElem.getElementsByClassName('ng-binding');
304
+ for (var j = 0; j < childBindings.length; ++j) {
305
+ bindings.push(childBindings[j]);
306
+ }
307
+ }
308
+ }
309
+ }
310
+ for (var i = 0; i < bindings.length; ++i) {
311
+ var dataBinding = angular.element(bindings[i]).data('$binding');
312
+ if (dataBinding) {
313
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
314
+ if (bindingName.indexOf(binding) != -1) {
315
+ matches.push(bindings[i]);
316
+ }
317
+ }
318
+ }
319
+ return matches;
320
+ }).apply(this, arguments); }
321
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
322
+ findRepeaterColumn: %q(try { return (function (repeater, exact, binding, using, rootSelector) {
323
+ function repeaterMatch(ngRepeat, repeater, exact) {
324
+ if (exact) {
325
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
326
+ trim() == repeater;
327
+ } else {
328
+ return ngRepeat.indexOf(repeater) != -1;
329
+ }
330
+ }
331
+
332
+ var matches = [];
333
+ var root = document.querySelector(rootSelector || 'body');
334
+ using = using || document;
335
+
336
+ var rows = [];
337
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
338
+ for (var p = 0; p < prefixes.length; ++p) {
339
+ var attr = prefixes[p] + 'repeat';
340
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
341
+ attr = attr.replace(/\\\\/g, '');
342
+ for (var i = 0; i < repeatElems.length; ++i) {
343
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
344
+ rows.push(repeatElems[i]);
345
+ }
346
+ }
347
+ }
348
+ /* multiRows is an array of arrays, where each inner array contains
349
+ one row of elements. */
350
+ var multiRows = [];
351
+ for (var p = 0; p < prefixes.length; ++p) {
352
+ var attr = prefixes[p] + 'repeat-start';
353
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
354
+ attr = attr.replace(/\\\\/g, '');
355
+ for (var i = 0; i < repeatElems.length; ++i) {
356
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
357
+ var elem = repeatElems[i];
358
+ var row = [];
359
+ while (elem.nodeType != 8 || (elem.nodeValue &&
360
+ !repeaterMatch(elem.nodeValue, repeater, exact))) {
361
+ if (elem.nodeType == 1) {
362
+ row.push(elem);
363
+ }
364
+ elem = elem.nextSibling;
365
+ }
366
+ multiRows.push(row);
367
+ }
368
+ }
369
+ }
370
+ var bindings = [];
371
+ for (var i = 0; i < rows.length; ++i) {
372
+ if (angular.getTestability) {
373
+ matches.push.apply(
374
+ matches,
375
+ angular.getTestability(root).findBindings(rows[i], binding));
376
+ } else {
377
+ if (rows[i].className.indexOf('ng-binding') != -1) {
378
+ bindings.push(rows[i]);
379
+ }
380
+ var childBindings = rows[i].getElementsByClassName('ng-binding');
381
+ for (var k = 0; k < childBindings.length; ++k) {
382
+ bindings.push(childBindings[k]);
383
+ }
384
+ }
385
+ }
386
+ for (var i = 0; i < multiRows.length; ++i) {
387
+ for (var j = 0; j < multiRows[i].length; ++j) {
388
+ if (angular.getTestability) {
389
+ matches.push.apply(
390
+ matches,
391
+ angular.getTestability(root).findBindings(multiRows[i][j], binding));
392
+ } else {
393
+ var elem = multiRows[i][j];
394
+ if (elem.className.indexOf('ng-binding') != -1) {
395
+ bindings.push(elem);
396
+ }
397
+ var childBindings = elem.getElementsByClassName('ng-binding');
398
+ for (var k = 0; k < childBindings.length; ++k) {
399
+ bindings.push(childBindings[k]);
400
+ }
401
+ }
402
+ }
403
+ }
404
+ for (var j = 0; j < bindings.length; ++j) {
405
+ var dataBinding = angular.element(bindings[j]).data('$binding');
406
+ if (dataBinding) {
407
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
408
+ if (bindingName.indexOf(binding) != -1) {
409
+ matches.push(bindings[j]);
410
+ }
411
+ }
412
+ }
413
+ return matches;
414
+ }).apply(this, arguments); }
415
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
416
+ findByModel: %q(try { return (function (model, using, rootSelector) {
417
+ var root = document.querySelector(rootSelector || 'body');
418
+ using = using || document;
419
+
420
+ if (angular.getTestability) {
421
+ return angular.getTestability(root).
422
+ findModels(using, model, true);
423
+ }
424
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
425
+ for (var p = 0; p < prefixes.length; ++p) {
426
+ var selector = '[' + prefixes[p] + 'model="' + model + '"]';
427
+ var elements = using.querySelectorAll(selector);
428
+ if (elements.length) {
429
+ return elements;
430
+ }
431
+ }
432
+ }).apply(this, arguments); }
433
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
434
+ findByOptions: %q(try { return (function (optionsDescriptor, using) {
435
+ using = using || document;
436
+
437
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
438
+ for (var p = 0; p < prefixes.length; ++p) {
439
+ var selector = '[' + prefixes[p] + 'options="' + optionsDescriptor + '"] option';
440
+ var elements = using.querySelectorAll(selector);
441
+ if (elements.length) {
442
+ return elements;
443
+ }
444
+ }
445
+ }).apply(this, arguments); }
446
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
447
+ findByButtonText: %q(try { return (function (searchText, using) {
448
+ using = using || document;
449
+
450
+ var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');
451
+ var matches = [];
452
+ for (var i = 0; i < elements.length; ++i) {
453
+ var element = elements[i];
454
+ var elementText;
455
+ if (element.tagName.toLowerCase() == 'button') {
456
+ elementText = element.textContent || element.innerText || '';
457
+ } else {
458
+ elementText = element.value;
459
+ }
460
+ if (elementText.trim() === searchText) {
461
+ matches.push(element);
462
+ }
463
+ }
464
+
465
+ return matches;
466
+ }).apply(this, arguments); }
467
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
468
+ findByPartialButtonText: %q(try { return (function (searchText, using) {
469
+ using = using || document;
470
+
471
+ var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');
472
+ var matches = [];
473
+ for (var i = 0; i < elements.length; ++i) {
474
+ var element = elements[i];
475
+ var elementText;
476
+ if (element.tagName.toLowerCase() == 'button') {
477
+ elementText = element.textContent || element.innerText || '';
478
+ } else {
479
+ elementText = element.value;
480
+ }
481
+ if (elementText.indexOf(searchText) > -1) {
482
+ matches.push(element);
483
+ }
484
+ }
485
+
486
+ return matches;
487
+ }).apply(this, arguments); }
488
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
489
+ findByCssContainingText: %q(try { return (function (cssSelector, searchText, using) {
490
+ using = using || document;
491
+
492
+ var elements = using.querySelectorAll(cssSelector);
493
+ var matches = [];
494
+ for (var i = 0; i < elements.length; ++i) {
495
+ var element = elements[i];
496
+ var elementText = element.textContent || element.innerText || '';
497
+ if (elementText.indexOf(searchText) > -1) {
498
+ matches.push(element);
499
+ }
500
+ }
501
+ return matches;
502
+ }).apply(this, arguments); }
503
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
504
+ testForAngular: %q(try { return (function (attempts, asyncCallback) {
505
+ var callback = function(args) {
506
+ setTimeout(function() {
507
+ asyncCallback(args);
508
+ }, 0);
509
+ };
510
+ var check = function(n) {
511
+ try {
512
+ if (window.angular && window.angular.resumeBootstrap) {
513
+ callback([true, null]);
514
+ } else if (n < 1) {
515
+ if (window.angular) {
516
+ callback([false, 'angular never provided resumeBootstrap']);
517
+ } else {
518
+ callback([false, 'retries looking for angular exceeded']);
519
+ }
520
+ } else {
521
+ window.setTimeout(function() {check(n - 1);}, 1000);
522
+ }
523
+ } catch (e) {
524
+ callback([false, e]);
525
+ }
526
+ };
527
+ check(attempts);
528
+ }).apply(this, arguments); }
529
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
530
+ evaluate: %q(try { return (function (element, expression) {
531
+ return angular.element(element).scope().$eval(expression);
532
+ }).apply(this, arguments); }
533
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
534
+ allowAnimations: %q(try { return (function (element, value) {
535
+ var ngElement = angular.element(element);
536
+ if (ngElement.allowAnimations) {
537
+ // AngularDart: $testability API.
538
+ return ngElement.allowAnimations(value);
539
+ } else {
540
+ // AngularJS
541
+ var enabledFn = ngElement.injector().get('$animate').enabled;
542
+ return (value == null) ? enabledFn() : enabledFn(value);
543
+ }
544
+ }).apply(this, arguments); }
545
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
546
+ getLocationAbsUrl: %q(try { return (function (selector) {
547
+ var el = document.querySelector(selector);
548
+ if (angular.getTestability) {
549
+ return angular.getTestability(el).
550
+ getLocation();
551
+ }
552
+ return angular.element(el).injector().get('$location').absUrl();
553
+ }).apply(this, arguments); }
554
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
555
+ setLocation: %q(try { return (function (selector, url) {
556
+ var el = document.querySelector(selector);
557
+ if (angular.getTestability) {
558
+ return angular.getTestability(el).
559
+ setLocation(url);
560
+ }
561
+ var $injector = angular.element(el).injector();
562
+ var $location = $injector.get('$location');
563
+ var $rootScope = $injector.get('$rootScope');
564
+
565
+ if (url !== $location.url()) {
566
+ $location.url(url);
567
+ $rootScope.$digest();
568
+ }
569
+ }).apply(this, arguments); }
570
+ catch(e) { throw (e instanceof Error) ? e : new Error(e); }).freeze,
571
+ installInBrowser: %q(window.clientSideScripts = {waitForAngular: function (rootSelector, callback) {
572
+ var el = document.querySelector(rootSelector);
573
+
574
+ try {
575
+ if (!window.angular) {
576
+ throw new Error('angular could not be found on the window');
577
+ }
578
+ if (angular.getTestability) {
579
+ angular.getTestability(el).whenStable(callback);
580
+ } else {
581
+ if (!angular.element(el).injector()) {
582
+ throw new Error('root element (' + rootSelector + ') has no injector.' +
583
+ ' this may mean it is not inside ng-app.');
584
+ }
585
+ angular.element(el).injector().get('$browser').
586
+ notifyWhenNoOutstandingRequests(callback);
587
+ }
588
+ } catch (err) {
589
+ callback(err.message);
590
+ }
591
+ }, findBindings: function (binding, exactMatch, using, rootSelector) {
592
+ var root = document.querySelector(rootSelector || 'body');
593
+ using = using || document;
594
+ if (angular.getTestability) {
595
+ return angular.getTestability(root).
596
+ findBindings(using, binding, exactMatch);
597
+ }
598
+ var bindings = using.getElementsByClassName('ng-binding');
599
+ var matches = [];
600
+ for (var i = 0; i < bindings.length; ++i) {
601
+ var dataBinding = angular.element(bindings[i]).data('$binding');
602
+ if (dataBinding) {
603
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
604
+ if (exactMatch) {
605
+ var matcher = new RegExp('({|\\\\s|^|\\\\|)' +
606
+ /* See http://stackoverflow.com/q/3561711 */
607
+ binding.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, '\\\\$&') +
608
+ '(}|\\\\s|$|\\\\|)');
609
+ if (matcher.test(bindingName)) {
610
+ matches.push(bindings[i]);
611
+ }
612
+ } else {
613
+ if (bindingName.indexOf(binding) != -1) {
614
+ matches.push(bindings[i]);
615
+ }
616
+ }
617
+
618
+ }
619
+ }
620
+ return matches; /* Return the whole array for webdriver.findElements. */
621
+ }, findRepeaterRows: function (repeater, exact, index, using) {
622
+ function repeaterMatch(ngRepeat, repeater, exact) {
623
+ if (exact) {
624
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
625
+ trim() == repeater;
626
+ } else {
627
+ return ngRepeat.indexOf(repeater) != -1;
628
+ }
629
+ }
630
+
631
+ using = using || document;
632
+
633
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
634
+ var rows = [];
635
+ for (var p = 0; p < prefixes.length; ++p) {
636
+ var attr = prefixes[p] + 'repeat';
637
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
638
+ attr = attr.replace(/\\\\/g, '');
639
+ for (var i = 0; i < repeatElems.length; ++i) {
640
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
641
+ rows.push(repeatElems[i]);
642
+ }
643
+ }
644
+ }
645
+ /* multiRows is an array of arrays, where each inner array contains
646
+ one row of elements. */
647
+ var multiRows = [];
648
+ for (var p = 0; p < prefixes.length; ++p) {
649
+ var attr = prefixes[p] + 'repeat-start';
650
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
651
+ attr = attr.replace(/\\\\/g, '');
652
+ for (var i = 0; i < repeatElems.length; ++i) {
653
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
654
+ var elem = repeatElems[i];
655
+ var row = [];
656
+ while (elem.nodeType != 8 ||
657
+ !repeaterMatch(elem.nodeValue, repeater, exact)) {
658
+ if (elem.nodeType == 1) {
659
+ row.push(elem);
660
+ }
661
+ elem = elem.nextSibling;
662
+ }
663
+ multiRows.push(row);
664
+ }
665
+ }
666
+ }
667
+ var row = rows[index] || [], multiRow = multiRows[index] || [];
668
+ return [].concat(row, multiRow);
669
+ }, findAllRepeaterRows: function (repeater, exact, using) {
670
+ function repeaterMatch(ngRepeat, repeater, exact) {
671
+ if (exact) {
672
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
673
+ trim() == repeater;
674
+ } else {
675
+ return ngRepeat.indexOf(repeater) != -1;
676
+ }
677
+ }
678
+
679
+ using = using || document;
680
+
681
+ var rows = [];
682
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
683
+ for (var p = 0; p < prefixes.length; ++p) {
684
+ var attr = prefixes[p] + 'repeat';
685
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
686
+ attr = attr.replace(/\\\\/g, '');
687
+ for (var i = 0; i < repeatElems.length; ++i) {
688
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
689
+ rows.push(repeatElems[i]);
690
+ }
691
+ }
692
+ }
693
+ for (var p = 0; p < prefixes.length; ++p) {
694
+ var attr = prefixes[p] + 'repeat-start';
695
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
696
+ attr = attr.replace(/\\\\/g, '');
697
+ for (var i = 0; i < repeatElems.length; ++i) {
698
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
699
+ var elem = repeatElems[i];
700
+ while (elem.nodeType != 8 ||
701
+ !repeaterMatch(elem.nodeValue, repeater, exact)) {
702
+ if (elem.nodeType == 1) {
703
+ rows.push(elem);
704
+ }
705
+ elem = elem.nextSibling;
706
+ }
707
+ }
708
+ }
709
+ }
710
+ return rows;
711
+ }, findRepeaterElement: function (repeater, exact, index, binding, using, rootSelector) {
712
+ function repeaterMatch(ngRepeat, repeater, exact) {
713
+ if (exact) {
714
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
715
+ trim() == repeater;
716
+ } else {
717
+ return ngRepeat.indexOf(repeater) != -1;
718
+ }
719
+ }
720
+
721
+ var matches = [];
722
+ var root = document.querySelector(rootSelector || 'body');
723
+ using = using || document;
724
+
725
+ var rows = [];
726
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
727
+ for (var p = 0; p < prefixes.length; ++p) {
728
+ var attr = prefixes[p] + 'repeat';
729
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
730
+ attr = attr.replace(/\\\\/g, '');
731
+ for (var i = 0; i < repeatElems.length; ++i) {
732
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
733
+ rows.push(repeatElems[i]);
734
+ }
735
+ }
736
+ }
737
+ /* multiRows is an array of arrays, where each inner array contains
738
+ one row of elements. */
739
+ var multiRows = [];
740
+ for (var p = 0; p < prefixes.length; ++p) {
741
+ var attr = prefixes[p] + 'repeat-start';
742
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
743
+ attr = attr.replace(/\\\\/g, '');
744
+ for (var i = 0; i < repeatElems.length; ++i) {
745
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
746
+ var elem = repeatElems[i];
747
+ var row = [];
748
+ while (elem.nodeType != 8 || (elem.nodeValue &&
749
+ !repeaterMatch(elem.nodeValue, repeater, exact))) {
750
+ if (elem.nodeType == 1) {
751
+ row.push(elem);
752
+ }
753
+ elem = elem.nextSibling;
754
+ }
755
+ multiRows.push(row);
756
+ }
757
+ }
758
+ }
759
+ var row = rows[index];
760
+ var multiRow = multiRows[index];
761
+ var bindings = [];
762
+ if (row) {
763
+ if (angular.getTestability) {
764
+ matches.push.apply(
765
+ matches,
766
+ angular.getTestability(root).findBindings(row, binding));
767
+ } else {
768
+ if (row.className.indexOf('ng-binding') != -1) {
769
+ bindings.push(row);
770
+ }
771
+ var childBindings = row.getElementsByClassName('ng-binding');
772
+ for (var i = 0; i < childBindings.length; ++i) {
773
+ bindings.push(childBindings[i]);
774
+ }
775
+ }
776
+ }
777
+ if (multiRow) {
778
+ for (var i = 0; i < multiRow.length; ++i) {
779
+ var rowElem = multiRow[i];
780
+ if (angular.getTestability) {
781
+ matches.push.apply(
782
+ matches,
783
+ angular.getTestability(root).findBindings(rowElem, binding));
784
+ } else {
785
+ if (rowElem.className.indexOf('ng-binding') != -1) {
786
+ bindings.push(rowElem);
787
+ }
788
+ var childBindings = rowElem.getElementsByClassName('ng-binding');
789
+ for (var j = 0; j < childBindings.length; ++j) {
790
+ bindings.push(childBindings[j]);
791
+ }
792
+ }
793
+ }
794
+ }
795
+ for (var i = 0; i < bindings.length; ++i) {
796
+ var dataBinding = angular.element(bindings[i]).data('$binding');
797
+ if (dataBinding) {
798
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
799
+ if (bindingName.indexOf(binding) != -1) {
800
+ matches.push(bindings[i]);
801
+ }
802
+ }
803
+ }
804
+ return matches;
805
+ }, findRepeaterColumn: function (repeater, exact, binding, using, rootSelector) {
806
+ function repeaterMatch(ngRepeat, repeater, exact) {
807
+ if (exact) {
808
+ return ngRepeat.split(' track by ')[0].split(' as ')[0].split('|')[0].
809
+ trim() == repeater;
810
+ } else {
811
+ return ngRepeat.indexOf(repeater) != -1;
812
+ }
813
+ }
814
+
815
+ var matches = [];
816
+ var root = document.querySelector(rootSelector || 'body');
817
+ using = using || document;
818
+
819
+ var rows = [];
820
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
821
+ for (var p = 0; p < prefixes.length; ++p) {
822
+ var attr = prefixes[p] + 'repeat';
823
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
824
+ attr = attr.replace(/\\\\/g, '');
825
+ for (var i = 0; i < repeatElems.length; ++i) {
826
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
827
+ rows.push(repeatElems[i]);
828
+ }
829
+ }
830
+ }
831
+ /* multiRows is an array of arrays, where each inner array contains
832
+ one row of elements. */
833
+ var multiRows = [];
834
+ for (var p = 0; p < prefixes.length; ++p) {
835
+ var attr = prefixes[p] + 'repeat-start';
836
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
837
+ attr = attr.replace(/\\\\/g, '');
838
+ for (var i = 0; i < repeatElems.length; ++i) {
839
+ if (repeaterMatch(repeatElems[i].getAttribute(attr), repeater, exact)) {
840
+ var elem = repeatElems[i];
841
+ var row = [];
842
+ while (elem.nodeType != 8 || (elem.nodeValue &&
843
+ !repeaterMatch(elem.nodeValue, repeater, exact))) {
844
+ if (elem.nodeType == 1) {
845
+ row.push(elem);
846
+ }
847
+ elem = elem.nextSibling;
848
+ }
849
+ multiRows.push(row);
850
+ }
851
+ }
852
+ }
853
+ var bindings = [];
854
+ for (var i = 0; i < rows.length; ++i) {
855
+ if (angular.getTestability) {
856
+ matches.push.apply(
857
+ matches,
858
+ angular.getTestability(root).findBindings(rows[i], binding));
859
+ } else {
860
+ if (rows[i].className.indexOf('ng-binding') != -1) {
861
+ bindings.push(rows[i]);
862
+ }
863
+ var childBindings = rows[i].getElementsByClassName('ng-binding');
864
+ for (var k = 0; k < childBindings.length; ++k) {
865
+ bindings.push(childBindings[k]);
866
+ }
867
+ }
868
+ }
869
+ for (var i = 0; i < multiRows.length; ++i) {
870
+ for (var j = 0; j < multiRows[i].length; ++j) {
871
+ if (angular.getTestability) {
872
+ matches.push.apply(
873
+ matches,
874
+ angular.getTestability(root).findBindings(multiRows[i][j], binding));
875
+ } else {
876
+ var elem = multiRows[i][j];
877
+ if (elem.className.indexOf('ng-binding') != -1) {
878
+ bindings.push(elem);
879
+ }
880
+ var childBindings = elem.getElementsByClassName('ng-binding');
881
+ for (var k = 0; k < childBindings.length; ++k) {
882
+ bindings.push(childBindings[k]);
883
+ }
884
+ }
885
+ }
886
+ }
887
+ for (var j = 0; j < bindings.length; ++j) {
888
+ var dataBinding = angular.element(bindings[j]).data('$binding');
889
+ if (dataBinding) {
890
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
891
+ if (bindingName.indexOf(binding) != -1) {
892
+ matches.push(bindings[j]);
893
+ }
894
+ }
895
+ }
896
+ return matches;
897
+ }, findByModel: function (model, using, rootSelector) {
898
+ var root = document.querySelector(rootSelector || 'body');
899
+ using = using || document;
900
+
901
+ if (angular.getTestability) {
902
+ return angular.getTestability(root).
903
+ findModels(using, model, true);
904
+ }
905
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
906
+ for (var p = 0; p < prefixes.length; ++p) {
907
+ var selector = '[' + prefixes[p] + 'model="' + model + '"]';
908
+ var elements = using.querySelectorAll(selector);
909
+ if (elements.length) {
910
+ return elements;
911
+ }
912
+ }
913
+ }, findByOptions: function (optionsDescriptor, using) {
914
+ using = using || document;
915
+
916
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
917
+ for (var p = 0; p < prefixes.length; ++p) {
918
+ var selector = '[' + prefixes[p] + 'options="' + optionsDescriptor + '"] option';
919
+ var elements = using.querySelectorAll(selector);
920
+ if (elements.length) {
921
+ return elements;
922
+ }
923
+ }
924
+ }, findByButtonText: function (searchText, using) {
925
+ using = using || document;
926
+
927
+ var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');
928
+ var matches = [];
929
+ for (var i = 0; i < elements.length; ++i) {
930
+ var element = elements[i];
931
+ var elementText;
932
+ if (element.tagName.toLowerCase() == 'button') {
933
+ elementText = element.textContent || element.innerText || '';
934
+ } else {
935
+ elementText = element.value;
936
+ }
937
+ if (elementText.trim() === searchText) {
938
+ matches.push(element);
939
+ }
940
+ }
941
+
942
+ return matches;
943
+ }, findByPartialButtonText: function (searchText, using) {
944
+ using = using || document;
945
+
946
+ var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');
947
+ var matches = [];
948
+ for (var i = 0; i < elements.length; ++i) {
949
+ var element = elements[i];
950
+ var elementText;
951
+ if (element.tagName.toLowerCase() == 'button') {
952
+ elementText = element.textContent || element.innerText || '';
953
+ } else {
954
+ elementText = element.value;
955
+ }
956
+ if (elementText.indexOf(searchText) > -1) {
957
+ matches.push(element);
958
+ }
959
+ }
960
+
961
+ return matches;
962
+ }, findByCssContainingText: function (cssSelector, searchText, using) {
963
+ using = using || document;
964
+
965
+ var elements = using.querySelectorAll(cssSelector);
966
+ var matches = [];
967
+ for (var i = 0; i < elements.length; ++i) {
968
+ var element = elements[i];
969
+ var elementText = element.textContent || element.innerText || '';
970
+ if (elementText.indexOf(searchText) > -1) {
971
+ matches.push(element);
972
+ }
973
+ }
974
+ return matches;
975
+ }, testForAngular: function (attempts, asyncCallback) {
976
+ var callback = function(args) {
977
+ setTimeout(function() {
978
+ asyncCallback(args);
979
+ }, 0);
980
+ };
981
+ var check = function(n) {
982
+ try {
983
+ if (window.angular && window.angular.resumeBootstrap) {
984
+ callback([true, null]);
985
+ } else if (n < 1) {
986
+ if (window.angular) {
987
+ callback([false, 'angular never provided resumeBootstrap']);
988
+ } else {
989
+ callback([false, 'retries looking for angular exceeded']);
990
+ }
991
+ } else {
992
+ window.setTimeout(function() {check(n - 1);}, 1000);
993
+ }
994
+ } catch (e) {
995
+ callback([false, e]);
996
+ }
997
+ };
998
+ check(attempts);
999
+ }, evaluate: function (element, expression) {
1000
+ return angular.element(element).scope().$eval(expression);
1001
+ }, allowAnimations: function (element, value) {
1002
+ var ngElement = angular.element(element);
1003
+ if (ngElement.allowAnimations) {
1004
+ // AngularDart: $testability API.
1005
+ return ngElement.allowAnimations(value);
1006
+ } else {
1007
+ // AngularJS
1008
+ var enabledFn = ngElement.injector().get('$animate').enabled;
1009
+ return (value == null) ? enabledFn() : enabledFn(value);
1010
+ }
1011
+ }, getLocationAbsUrl: function (selector) {
1012
+ var el = document.querySelector(selector);
1013
+ if (angular.getTestability) {
1014
+ return angular.getTestability(el).
1015
+ getLocation();
1016
+ }
1017
+ return angular.element(el).injector().get('$location').absUrl();
1018
+ }, setLocation: function (selector, url) {
1019
+ var el = document.querySelector(selector);
1020
+ if (angular.getTestability) {
1021
+ return angular.getTestability(el).
1022
+ setLocation(url);
1023
+ }
1024
+ var $injector = angular.element(el).injector();
1025
+ var $location = $injector.get('$location');
1026
+ var $rootScope = $injector.get('$rootScope');
1027
+
1028
+ if (url !== $location.url()) {
1029
+ $location.url(url);
1030
+ $rootScope.$digest();
1031
+ }
1032
+ }};).freeze,
1033
+
1034
+ }.freeze
1035
+ end