capybara-ng 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,669 @@
1
+ module Angular
2
+ module ClientScript
3
+ # /**
4
+ # * Wait until Angular has finished rendering and has
5
+ # * no outstanding $http calls before continuing.
6
+ # *
7
+ # * Asynchronous.
8
+ # *
9
+ # * @param {string} selector The selector housing an ng-app
10
+ # * @param {function} callback callback
11
+ # */
12
+ FN_waitForAngular = <<-FN
13
+ function(selector, callback) {
14
+ var el = document.querySelector(selector);
15
+ return el;
16
+ try {
17
+ if (angular.getTestability) {
18
+ angular.getTestability(el).whenStable(callback);
19
+ } else {
20
+ angular.element(el).injector().get('$browser').
21
+ notifyWhenNoOutstandingRequests(callback);
22
+ }
23
+ } catch (e) {
24
+ callback(e);
25
+ }
26
+ };
27
+ FN
28
+
29
+ # /**
30
+ # * Find a list of elements in the page by their angular binding.
31
+ # *
32
+ # * @param {string} binding The binding, e.g. {{cat.name}}.
33
+ # * @param {boolean} exactMatch Whether the binding needs to be matched exactly
34
+ # * @param {Element} using The scope of the search.
35
+ # * @param {string} rootSelector The selector to use for the root app element.
36
+ # *
37
+ # * @return {Array.<Element>} The elements containing the binding.
38
+ # */
39
+ FN_findBindings = <<-FN
40
+ function(binding, exactMatch, using, rootSelector) {
41
+ rootSelector = rootSelector || 'body';
42
+ using = using || document.querySelector(rootSelector);
43
+ if (angular.getTestability) {
44
+ return angular.getTestability(using).
45
+ findBindings(using, binding, exactMatch);
46
+ }
47
+ var bindings = using.getElementsByClassName('ng-binding');
48
+ var matches = [];
49
+ for (var i = 0; i < bindings.length; ++i) {
50
+ var dataBinding = angular.element(bindings[i]).data('$binding');
51
+ if(dataBinding) {
52
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
53
+ if (exactMatch) {
54
+ var matcher = new RegExp('({|\\\\s|$|\\\\|)' + binding + '(}|\\\\s|^|\\\\|)');
55
+ if (matcher.test(bindingName)) {
56
+ matches.push(bindings[i]);
57
+ }
58
+ } else {
59
+ if (bindingName.indexOf(binding) != -1) {
60
+ matches.push(bindings[i]);
61
+ }
62
+ }
63
+
64
+ }
65
+ }
66
+ return matches; /* Return the whole array for webdriver.findElements. */
67
+ };
68
+ FN
69
+
70
+ # /**
71
+ # * Find an array of elements matching a row within an ng-repeat.
72
+ # * Always returns an array of only one element for plain old ng-repeat.
73
+ # * Returns an array of all the elements in one segment for ng-repeat-start.
74
+ # *
75
+ # * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.
76
+ # * @param {number} index The row index.
77
+ # * @param {Element} using The scope of the search.
78
+ # * @param {string} rootSelector The selector to use for the root app element.
79
+ # *
80
+ # * @return {Array.<Element>} The row of the repeater, or an array of elements
81
+ # * in the first row in the case of ng-repeat-start.
82
+ # */
83
+ FN_findRepeaterRows = <<-FN
84
+ function(repeater, index, using, rootSelector) {
85
+ rootSelector = rootSelector || 'body';
86
+ using = using || document.querySelector(rootSelector);
87
+
88
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
89
+ var rows = [];
90
+ for (var p = 0; p < prefixes.length; ++p) {
91
+ var attr = prefixes[p] + 'repeat';
92
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
93
+ attr = attr.replace(/\\\\/g, '');
94
+ for (var i = 0; i < repeatElems.length; ++i) {
95
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
96
+ rows.push(repeatElems[i]);
97
+ }
98
+ }
99
+ }
100
+ /* multiRows is an array of arrays, where each inner array contains
101
+ one row of elements. */
102
+ var multiRows = [];
103
+ for (var p = 0; p < prefixes.length; ++p) {
104
+ var attr = prefixes[p] + 'repeat-start';
105
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
106
+ attr = attr.replace(/\\\\/g, '');
107
+ for (var i = 0; i < repeatElems.length; ++i) {
108
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
109
+ var elem = repeatElems[i];
110
+ var row = [];
111
+ while (elem.nodeType != 8 ||
112
+ elem.nodeValue.indexOf(repeater) == -1) {
113
+ if (elem.nodeType == 1) {
114
+ row.push(elem);
115
+ }
116
+ elem = elem.nextSibling;
117
+ }
118
+ multiRows.push(row);
119
+ }
120
+ }
121
+ }
122
+ return [rows[index]].concat(multiRows[index]);
123
+ };
124
+ FN
125
+
126
+ # /**
127
+ # * Find all rows of an ng-repeat.
128
+ # *
129
+ # * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.
130
+ # * @param {Element} using The scope of the search.
131
+ # * @param {string} rootSelector The selector to use for the root app element.
132
+ # *
133
+ # * @return {Array.<Element>} All rows of the repeater.
134
+ # */
135
+ FN_findAllRepeaterRows = <<-FN
136
+ function(repeater, using, rootSelector) {
137
+ rootSelector = rootSelector || 'body';
138
+ using = using || document.querySelector(rootSelector);
139
+
140
+ var rows = [];
141
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
142
+ for (var p = 0; p < prefixes.length; ++p) {
143
+ var attr = prefixes[p] + 'repeat';
144
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
145
+ attr = attr.replace(/\\\\/g, '');
146
+ for (var i = 0; i < repeatElems.length; ++i) {
147
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
148
+ rows.push(repeatElems[i]);
149
+ }
150
+ }
151
+ }
152
+ for (var p = 0; p < prefixes.length; ++p) {
153
+ var attr = prefixes[p] + 'repeat-start';
154
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
155
+ attr = attr.replace(/\\\\/g, '');
156
+ for (var i = 0; i < repeatElems.length; ++i) {
157
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
158
+ var elem = repeatElems[i];
159
+ while (elem.nodeType != 8 ||
160
+ elem.nodeValue.indexOf(repeater) == -1) {
161
+ if (elem.nodeType == 1) {
162
+ rows.push(elem);
163
+ }
164
+ elem = elem.nextSibling;
165
+ }
166
+ }
167
+ }
168
+ }
169
+ return rows;
170
+ };
171
+ FN
172
+
173
+ # /**
174
+ # * Find an element within an ng-repeat by its row and column.
175
+ # *
176
+ # * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.
177
+ # * @param {number} index The row index.
178
+ # * @param {string} binding The column binding, e.g. '{{cat.name}}'.
179
+ # * @param {Element} using The scope of the search.
180
+ # * @param {string} rootSelector The selector to use for the root app element.
181
+ # *
182
+ # * @return {Array.<Element>} The element in an array.
183
+ # */
184
+ FN_findRepeaterElement = <<-FN
185
+ function(repeater, index, binding, using, rootSelector) {
186
+ var matches = [];
187
+ rootSelector = rootSelector || 'body';
188
+ using = using || document.querySelector(rootSelector);
189
+
190
+ var rows = [];
191
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
192
+ for (var p = 0; p < prefixes.length; ++p) {
193
+ var attr = prefixes[p] + 'repeat';
194
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
195
+ attr = attr.replace(/\\\\/g, '');
196
+ for (var i = 0; i < repeatElems.length; ++i) {
197
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
198
+ rows.push(repeatElems[i]);
199
+ }
200
+ }
201
+ }
202
+ /* multiRows is an array of arrays, where each inner array contains
203
+ one row of elements. */
204
+ var multiRows = [];
205
+ for (var p = 0; p < prefixes.length; ++p) {
206
+ var attr = prefixes[p] + 'repeat-start';
207
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
208
+ attr = attr.replace(/\\\\/g, '');
209
+ for (var i = 0; i < repeatElems.length; ++i) {
210
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
211
+ var elem = repeatElems[i];
212
+ var row = [];
213
+ while (elem.nodeType != 8 ||
214
+ (elem.nodeValue && elem.nodeValue.indexOf(repeater) == -1)) {
215
+ if (elem.nodeType == 1) {
216
+ row.push(elem);
217
+ }
218
+ elem = elem.nextSibling;
219
+ }
220
+ multiRows.push(row);
221
+ }
222
+ }
223
+ }
224
+ var row = rows[index];
225
+ var multiRow = multiRows[index];
226
+ var bindings = [];
227
+ if (row) {
228
+ if (angular.getTestability) {
229
+ matches.push.apply(
230
+ matches,
231
+ angular.getTestability(using).findBindings(row, binding));
232
+ } else {
233
+ if (row.className.indexOf('ng-binding') != -1) {
234
+ bindings.push(row);
235
+ }
236
+ var childBindings = row.getElementsByClassName('ng-binding');
237
+ for (var i = 0; i < childBindings.length; ++i) {
238
+ bindings.push(childBindings[i]);
239
+ }
240
+ }
241
+ }
242
+ if (multiRow) {
243
+ for (var i = 0; i < multiRow.length; ++i) {
244
+ var rowElem = multiRow[i];
245
+ if (angular.getTestability) {
246
+ matches.push.apply(
247
+ matches,
248
+ angular.getTestability(using).findBindings(rowElem, binding));
249
+ } else {
250
+ if (rowElem.className.indexOf('ng-binding') != -1) {
251
+ bindings.push(rowElem);
252
+ }
253
+ var childBindings = rowElem.getElementsByClassName('ng-binding');
254
+ for (var j = 0; j < childBindings.length; ++j) {
255
+ bindings.push(childBindings[j]);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ for (var i = 0; i < bindings.length; ++i) {
261
+ var dataBinding = angular.element(bindings[i]).data('$binding');
262
+ if(dataBinding) {
263
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
264
+ if (bindingName.indexOf(binding) != -1) {
265
+ matches.push(bindings[i]);
266
+ }
267
+ }
268
+ }
269
+ return matches;
270
+ };
271
+ FN
272
+
273
+ # /**
274
+ # * Find the elements in a column of an ng-repeat.
275
+ # *
276
+ # * @param {string} repeater The text of the repeater, e.g. 'cat in cats'.
277
+ # * @param {string} binding The column binding, e.g. '{{cat.name}}'.
278
+ # * @param {Element} using The scope of the search.
279
+ # * @param {string} rootSelector The selector to use for the root app element.
280
+ # *
281
+ # * @return {Array.<Element>} The elements in the column.
282
+ # */
283
+ FN_findRepeaterColumn = <<-FN
284
+ function(repeater, binding, using, rootSelector) {
285
+ var matches = [];
286
+ rootSelector = rootSelector || 'body';
287
+ using = using || document.querySelector(rootSelector);
288
+
289
+ var rows = [];
290
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
291
+ for (var p = 0; p < prefixes.length; ++p) {
292
+ var attr = prefixes[p] + 'repeat';
293
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
294
+ attr = attr.replace(/\\\\/g, '');
295
+ for (var i = 0; i < repeatElems.length; ++i) {
296
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
297
+ rows.push(repeatElems[i]);
298
+ }
299
+ }
300
+ }
301
+ /* multiRows is an array of arrays, where each inner array contains
302
+ one row of elements. */
303
+ var multiRows = [];
304
+ for (var p = 0; p < prefixes.length; ++p) {
305
+ var attr = prefixes[p] + 'repeat-start';
306
+ var repeatElems = using.querySelectorAll('[' + attr + ']');
307
+ attr = attr.replace(/\\\\/g, '');
308
+ for (var i = 0; i < repeatElems.length; ++i) {
309
+ if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
310
+ var elem = repeatElems[i];
311
+ var row = [];
312
+ while (elem.nodeType != 8 ||
313
+ (elem.nodeValue && elem.nodeValue.indexOf(repeater) == -1)) {
314
+ if (elem.nodeType == 1) {
315
+ row.push(elem);
316
+ }
317
+ elem = elem.nextSibling;
318
+ }
319
+ multiRows.push(row);
320
+ }
321
+ }
322
+ }
323
+ var bindings = [];
324
+ for (var i = 0; i < rows.length; ++i) {
325
+ if (angular.getTestability) {
326
+ matches.push.apply(
327
+ matches,
328
+ angular.getTestability(using).findBindings(rows[i], binding));
329
+ } else {
330
+ if (rows[i].className.indexOf('ng-binding') != -1) {
331
+ bindings.push(rows[i]);
332
+ }
333
+ var childBindings = rows[i].getElementsByClassName('ng-binding');
334
+ for (var k = 0; k < childBindings.length; ++k) {
335
+ bindings.push(childBindings[k]);
336
+ }
337
+ }
338
+ }
339
+ for (var i = 0; i < multiRows.length; ++i) {
340
+ for (var j = 0; j < multiRows[i].length; ++j) {
341
+ if (angular.getTestability) {
342
+ matches.push.apply(
343
+ matches,
344
+ angular.getTestability(using).findBindings(multiRows[i][j], binding));
345
+ } else {
346
+ var elem = multiRows[i][j];
347
+ if (elem.className.indexOf('ng-binding') != -1) {
348
+ bindings.push(elem);
349
+ }
350
+ var childBindings = elem.getElementsByClassName('ng-binding');
351
+ for (var k = 0; k < childBindings.length; ++k) {
352
+ bindings.push(childBindings[k]);
353
+ }
354
+ }
355
+ }
356
+ }
357
+ for (var j = 0; j < bindings.length; ++j) {
358
+ var dataBinding = angular.element(bindings[j]).data('$binding');
359
+ if (dataBinding) {
360
+ var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding;
361
+ if (bindingName.indexOf(binding) != -1) {
362
+ matches.push(bindings[j]);
363
+ }
364
+ }
365
+ }
366
+ return matches;
367
+ };
368
+ FN
369
+
370
+ # /**
371
+ # * Find elements by model name.
372
+ # *
373
+ # * @param {string} model The model name.
374
+ # * @param {Element} using The scope of the search.
375
+ # * @param {string} rootSelector The selector to use for the root app element.
376
+ # *
377
+ # * @return {Array.<Element>} The matching elements.
378
+ # */
379
+ FN_findByModel = <<-FN
380
+ function(model, using, rootSelector) {
381
+ rootSelector = rootSelector || 'body';
382
+ using = using || document.querySelector(rootSelector);
383
+
384
+ if (angular.getTestability) {
385
+ return angular.getTestability(using).
386
+ findModels(using, model, true);
387
+ }
388
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
389
+ for (var p = 0; p < prefixes.length; ++p) {
390
+ var selector = '[' + prefixes[p] + 'model="' + model + '"]';
391
+ var elements = using.querySelectorAll(selector);
392
+ if (elements.length) {
393
+ return elements;
394
+ }
395
+ }
396
+ };
397
+ FN
398
+
399
+ # /**
400
+ # * Find elements by options.
401
+ # *
402
+ # * @param {string} optionsDescriptor The descriptor for the option
403
+ # * (i.e. fruit for fruit in fruits).
404
+ # * @param {Element} using The scope of the search.
405
+ # * @param {string} rootSelector The selector to use for the root app element.
406
+ # *
407
+ # * @return {Array.<Element>} The matching elements.
408
+ # */
409
+ FN_findByOptions = <<-FN
410
+ function(optionsDescriptor, using, rootSelector) {
411
+ rootSelector = rootSelector || 'body';
412
+ using = using || document.querySelector(rootSelector);
413
+
414
+ var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\\\:'];
415
+ for (var p = 0; p < prefixes.length; ++p) {
416
+ var selector = '[' + prefixes[p] + 'options="' + optionsDescriptor + '"] option';
417
+ var elements = using.querySelectorAll(selector);
418
+ if (elements.length) {
419
+ return elements;
420
+ }
421
+ }
422
+ };
423
+ FN
424
+
425
+ # /**
426
+ # * Find buttons by textual content.
427
+ # *
428
+ # * @param {string} searchText The exact text to match.
429
+ # * @param {Element} using The scope of the search.
430
+ # * @param {string} rootSelector The selector to use for the root app element.
431
+ # *
432
+ # * @return {Array.<Element>} The matching elements.
433
+ # */
434
+ FN_findByButtonText = <<-FN
435
+ function(searchText, using, rootSelector) {
436
+ rootSelector = rootSelector || 'body';
437
+ using = using || document.querySelector(rootSelector);
438
+
439
+ var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');
440
+ var matches = [];
441
+ for (var i = 0; i < elements.length; ++i) {
442
+ var element = elements[i];
443
+ var elementText;
444
+ if (element.tagName.toLowerCase() == 'button') {
445
+ elementText = element.innerText || element.textContent;
446
+ } else {
447
+ elementText = element.value;
448
+ }
449
+ if (elementText.trim() === searchText) {
450
+ matches.push(element);
451
+ }
452
+ }
453
+
454
+ return matches;
455
+ };
456
+ FN
457
+
458
+ # /**
459
+ # * Find buttons by textual content.
460
+ # *
461
+ # * @param {string} searchText The exact text to match.
462
+ # * @param {Element} using The scope of the search.
463
+ # * @param {string} rootSelector The selector to use for the root app element.
464
+ # *
465
+ # * @return {Array.<Element>} The matching elements.
466
+ # */
467
+ FN_findByPartialButtonText = <<-FN
468
+ function(searchText, using, rootSelector) {
469
+ rootSelector = rootSelector || 'body';
470
+ using = using || document.querySelector(rootSelector);
471
+
472
+ var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]');
473
+ var matches = [];
474
+ for (var i = 0; i < elements.length; ++i) {
475
+ var element = elements[i];
476
+ var elementText;
477
+ if (element.tagName.toLowerCase() == 'button') {
478
+ elementText = element.innerText || element.textContent;
479
+ } else {
480
+ elementText = element.value;
481
+ }
482
+ if (elementText.indexOf(searchText) > -1) {
483
+ matches.push(element);
484
+ }
485
+ }
486
+
487
+ return matches;
488
+ };
489
+ FN
490
+
491
+ # /**
492
+ # * Find elements by css selector and textual content.
493
+ # *
494
+ # * @param {string} cssSelector The css selector to match.
495
+ # * @param {string} searchText The exact text to match.
496
+ # * @param {Element} using The scope of the search.
497
+ # * @param {string} rootSelector The selector to use for the root app element.
498
+ # *
499
+ # * @return {Array.<Element>} An array of matching elements.
500
+ # */
501
+ FN_findByCssContainingText = <<-FN
502
+ function(cssSelector, searchText, using, rootSelector) {
503
+ rootSelector = rootSelector || 'body';
504
+ using = using || document.querySelector(rootSelector);
505
+
506
+ var elements = using.querySelectorAll(cssSelector);
507
+ var matches = [];
508
+ for (var i = 0; i < elements.length; ++i) {
509
+ var element = elements[i];
510
+ var elementText = element.innerText || element.textContent;
511
+ if (elementText.indexOf(searchText) > -1) {
512
+ matches.push(element);
513
+ }
514
+ }
515
+ return matches;
516
+ };
517
+ FN
518
+
519
+ # /**
520
+ # * Tests whether the angular global variable is present on a page. Retries
521
+ # * in case the page is just loading slowly.
522
+ # *
523
+ # * Asynchronous.
524
+ # *
525
+ # * @param {number} attempts Number of times to retry.
526
+ # * @param {function} asyncCallback callback
527
+ # */
528
+ FN_testForAngular = <<-FN
529
+ function(attempts, asyncCallback) {
530
+ var callback = function(args) {
531
+ setTimeout(function() {
532
+ asyncCallback(args);
533
+ }, 0);
534
+ };
535
+ var check = function(n) {
536
+ try {
537
+ if (window.angular && window.angular.resumeBootstrap) {
538
+ callback([true, null]);
539
+ } else if (n < 1) {
540
+ if (window.angular) {
541
+ callback([false, 'angular never provided resumeBootstrap']);
542
+ } else {
543
+ callback([false, 'retries looking for angular exceeded']);
544
+ }
545
+ } else {
546
+ window.setTimeout(function() {check(n - 1);}, 1000);
547
+ }
548
+ } catch (e) {
549
+ callback([false, e]);
550
+ }
551
+ };
552
+ check(attempts);
553
+ };
554
+ FN
555
+
556
+ # /**
557
+ # * Evalute an Angular expression in the context of a given element.
558
+ # *
559
+ # * @param {Element} element The element in whose scope to evaluate.
560
+ # * @param {string} expression The expression to evaluate.
561
+ # *
562
+ # * @return {?Object} The result of the evaluation.
563
+ # */
564
+ FN_evaluate = <<-FN
565
+ function(element, expression) {
566
+ return angular.element(element).scope().$eval(expression);
567
+ };
568
+ FN
569
+
570
+ FN_allowAnimations = <<-FN
571
+ function(element, value) {
572
+ var ngElement = angular.element(element);
573
+ if (ngElement.allowAnimations) {
574
+ // AngularDart: $testability API.
575
+ return ngElement.allowAnimations(value);
576
+ } else {
577
+ // AngularJS
578
+ var enabledFn = ngElement.injector().get('$animate').enabled;
579
+ return (value == null) ? enabledFn() : enabledFn(value);
580
+ }
581
+ };
582
+ FN
583
+
584
+ # /**
585
+ # * Return the current url using $location.absUrl().
586
+ # *
587
+ # * @param {string} selector The selector housing an ng-app
588
+ # */
589
+ FN_getLocationAbsUrl = <<-FN
590
+ function(selector) {
591
+ var el = document.querySelector(selector);
592
+ if (angular.getTestability) {
593
+ return angular.getTestability(el).
594
+ getLocation();
595
+ }
596
+ return angular.element(el).injector().get('$location').absUrl();
597
+ };
598
+ FN
599
+
600
+ # /**
601
+ # * Get current location
602
+ # *
603
+ # * @param {string} selector The selector housing an ng-app
604
+ # * @param {string} url In page URL using the same syntax as $location.url(),
605
+ # * /path?search=a&b=c#hash
606
+ # */
607
+ FN_getLocation = <<-FN
608
+ function(selector) {
609
+ var el = document.querySelector(selector);
610
+ var $injector = angular.element(el).injector();
611
+ var $location = $injector.get('$location');
612
+ return $location.url();
613
+ };
614
+ FN
615
+
616
+ # /**
617
+ # * Browse to another page using in-page navigation.
618
+ # *
619
+ # * @param {string} selector The selector housing an ng-app
620
+ # * @param {string} url In page URL using the same syntax as $location.url(),
621
+ # * /path?search=a&b=c#hash
622
+ # */
623
+ FN_setLocation = <<-FN
624
+ function(selector, url) {
625
+ var el = document.querySelector(selector);
626
+ if (angular.getTestability) {
627
+ return angular.getTestability(el).
628
+ setLocation(url);
629
+ }
630
+ var $injector = angular.element(el).injector();
631
+ var $location = $injector.get('$location');
632
+ var $rootScope = $injector.get('$rootScope');
633
+
634
+ if (url !== $location.url()) {
635
+ $location.url(url);
636
+ $rootScope.$digest();
637
+ }
638
+ return $location.url();
639
+ };
640
+ FN
641
+
642
+ def self.functions
643
+ Hash[
644
+ self.constants.map do |cn|
645
+ [cn[3, cn.size].to_sym, self.const_get(cn)]
646
+ end
647
+ ]
648
+ end
649
+
650
+ def self.format_script(name, fn)
651
+ "try { return (#{fn}).apply(this, arguments); }\n" +
652
+ "catch(e) { throw (e instanceof Error) ? e : new Error(e); }"
653
+ end
654
+
655
+ def self.format_scripts
656
+ Hash[
657
+ functions.map do |name, fn|
658
+ [name, format_script(name,fn)]
659
+ end
660
+ ]
661
+ end
662
+
663
+ def self.window_scripts
664
+ functions
665
+ .map { |name, fn| "window.#{name} = #{fn};" }
666
+ end
667
+
668
+ end
669
+ end