1
1
/**
2
2
* All scripts to be run on the client via executeAsyncScript or
3
- * executeScript should be put here. These scripts are transmitted over
4
- * the wire using their toString representation, and cannot reference
5
- * external variables. They can, however use the array passed in to
6
- * arguments.
3
+ * executeScript should be put here.
4
+ *
5
+ * NOTE: These scripts are transmitted over the wire as JavaScript text
6
+ * constructed using their toString representation, and *cannot*
7
+ * reference external variables.
7
8
*
8
9
* Some implementations seem to have issues with // comments, so use star-style
9
- * inside scripts.
10
+ * inside scripts. (TODO: add issue number / example implementations
11
+ * that caused the switch to avoid the // comments.)
10
12
*/
11
13
12
- // jshint browser: true
13
- // jshint shadow: true
14
- /* global angular */
15
- var clientSideScripts = exports ;
14
+ // jshint browser: true
15
+ // jshint shadow: true
16
+ /* global angular */
17
+ var functions = { } ;
16
18
17
19
/**
18
20
* Wait until Angular has finished rendering and has
@@ -23,7 +25,7 @@ var clientSideScripts = exports;
23
25
* @param {string } selector The selector housing an ng-app
24
26
* @param {function } callback callback
25
27
*/
26
- clientSideScripts . waitForAngular = function ( selector , callback ) {
28
+ functions . waitForAngular = function ( selector , callback ) {
27
29
var el = document . querySelector ( selector ) ;
28
30
try {
29
31
angular . element ( el ) . injector ( ) . get ( '$browser' ) .
@@ -42,7 +44,7 @@ clientSideScripts.waitForAngular = function(selector, callback) {
42
44
*
43
45
* @return {Array.<Element> } The elements containing the binding.
44
46
*/
45
- clientSideScripts . findBindings = function ( binding , exactMatch , using ) {
47
+ functions . findBindings = function ( binding , exactMatch , using ) {
46
48
using = using || document ;
47
49
var bindings = using . getElementsByClassName ( 'ng-binding' ) ;
48
50
var matches = [ ] ;
@@ -78,7 +80,7 @@ clientSideScripts.findBindings = function(binding, exactMatch, using) {
78
80
* @return {Array.<Element> } The row of the repeater, or an array of elements
79
81
* in the first row in the case of ng-repeat-start.
80
82
*/
81
- clientSideScripts . findRepeaterRows = function ( repeater , index , using ) {
83
+ functions . findRepeaterRows = function ( repeater , index , using ) {
82
84
using = using || document ;
83
85
84
86
var prefixes = [ 'ng-' , 'ng_' , 'data-ng-' , 'x-ng-' , 'ng\\:' ] ;
@@ -126,7 +128,7 @@ clientSideScripts.findBindings = function(binding, exactMatch, using) {
126
128
*
127
129
* @return {Array.<Element> } All rows of the repeater.
128
130
*/
129
- clientSideScripts . findAllRepeaterRows = function ( repeater , using ) {
131
+ functions . findAllRepeaterRows = function ( repeater , using ) {
130
132
using = using || document ;
131
133
132
134
var rows = [ ] ;
@@ -171,7 +173,7 @@ clientSideScripts.findBindings = function(binding, exactMatch, using) {
171
173
*
172
174
* @return {Array.<Element> } The element in an array.
173
175
*/
174
- clientSideScripts . findRepeaterElement = function ( repeater , index , binding , using ) {
176
+ functions . findRepeaterElement = function ( repeater , index , binding , using ) {
175
177
var matches = [ ] ;
176
178
using = using || document ;
177
179
@@ -254,7 +256,7 @@ clientSideScripts.findRepeaterElement = function(repeater, index, binding, using
254
256
*
255
257
* @return {Array.<Element> } The elements in the column.
256
258
*/
257
- clientSideScripts . findRepeaterColumn = function ( repeater , binding , using ) {
259
+ functions . findRepeaterColumn = function ( repeater , binding , using ) {
258
260
var matches = [ ] ;
259
261
using = using || document ;
260
262
@@ -334,7 +336,7 @@ clientSideScripts.findRepeaterColumn = function(repeater, binding, using) {
334
336
*
335
337
* @return {Array.<Element> } The matching elements.
336
338
*/
337
- clientSideScripts . findByModel = function ( model , using ) {
339
+ functions . findByModel = function ( model , using ) {
338
340
using = using || document ;
339
341
var prefixes = [ 'ng-' , 'ng_' , 'data-ng-' , 'x-ng-' , 'ng\\:' ] ;
340
342
for ( var p = 0 ; p < prefixes . length ; ++ p ) {
@@ -354,7 +356,7 @@ clientSideScripts.findByModel = function(model, using) {
354
356
*
355
357
* @return {Array.<Element> } The matching elements.
356
358
*/
357
- clientSideScripts . findByButtonText = function ( searchText , using ) {
359
+ functions . findByButtonText = function ( searchText , using ) {
358
360
using = using || document ;
359
361
var elements = using . querySelectorAll ( 'button, input[type="button"], input[type="submit"]' ) ;
360
362
var matches = [ ] ;
@@ -382,7 +384,7 @@ clientSideScripts.findByButtonText = function(searchText, using) {
382
384
*
383
385
* @return {Array.<Element> } The matching elements.
384
386
*/
385
- clientSideScripts . findByPartialButtonText = function ( searchText , using ) {
387
+ functions . findByPartialButtonText = function ( searchText , using ) {
386
388
using = using || document ;
387
389
var elements = using . querySelectorAll ( 'button, input[type="button"], input[type="submit"]' ) ;
388
390
var matches = [ ] ;
@@ -411,7 +413,7 @@ clientSideScripts.findByPartialButtonText = function(searchText, using) {
411
413
*
412
414
* @return {Array.<Element> } An array of matching elements.
413
415
*/
414
- clientSideScripts . findByCssContainingText = function ( cssSelector , searchText , using ) {
416
+ functions . findByCssContainingText = function ( cssSelector , searchText , using ) {
415
417
var using = using || document ;
416
418
var elements = using . querySelectorAll ( cssSelector ) ;
417
419
var matches = [ ] ;
@@ -434,7 +436,7 @@ clientSideScripts.findByCssContainingText = function(cssSelector, searchText, us
434
436
* @param {number } attempts Number of times to retry.
435
437
* @param {function } asyncCallback callback
436
438
*/
437
- clientSideScripts . testForAngular = function ( attempts , asyncCallback ) {
439
+ functions . testForAngular = function ( attempts , asyncCallback ) {
438
440
var callback = function ( args ) {
439
441
setTimeout ( function ( ) {
440
442
asyncCallback ( args ) ;
@@ -468,7 +470,7 @@ clientSideScripts.testForAngular = function(attempts, asyncCallback) {
468
470
*
469
471
* @return {?Object } The result of the evaluation.
470
472
*/
471
- clientSideScripts . evaluate = function ( element , expression ) {
473
+ functions . evaluate = function ( element , expression ) {
472
474
473
475
return angular . element ( element ) . scope ( ) . $eval ( expression ) ;
474
476
} ;
@@ -478,7 +480,7 @@ clientSideScripts.evaluate = function(element, expression) {
478
480
*
479
481
* @param {string } selector The selector housing an ng-app
480
482
*/
481
- clientSideScripts . getLocationAbsUrl = function ( selector ) {
483
+ functions . getLocationAbsUrl = function ( selector ) {
482
484
var el = document . querySelector ( selector ) ;
483
485
return angular . element ( el ) . injector ( ) . get ( '$location' ) . absUrl ( ) ;
484
486
} ;
@@ -490,7 +492,7 @@ clientSideScripts.getLocationAbsUrl = function(selector) {
490
492
* @param {string } url In page URL using the same syntax as $location.url(),
491
493
* /path?search=a&b=c#hash
492
494
*/
493
- clientSideScripts . setLocation = function ( selector , url ) {
495
+ functions . setLocation = function ( selector , url ) {
494
496
var el = document . querySelector ( selector ) ;
495
497
var $injector = angular . element ( el ) . injector ( ) ;
496
498
var $location = $injector . get ( '$location' ) ;
@@ -501,3 +503,29 @@ clientSideScripts.setLocation = function(selector, url) {
501
503
$rootScope . $digest ( ) ;
502
504
}
503
505
} ;
506
+
507
+ /* Publish all the functions as strings to pass to WebDriver's
508
+ * exec[Async]Script. In addition, also include a script that will
509
+ * install all the functions on window (for debugging.)
510
+ *
511
+ * We also wrap any exceptions thrown by a clientSideScripts function
512
+ * that is not an instance of the Error type into an Error type. If we
513
+ * don't do so, then the resulting stack trace is completely unhelpful
514
+ * and the exception message is just "unknown error." These types of
515
+ * exceptins are the common case for dart2js code. This wrapping gives
516
+ * us the Dart stack trace and exception message.
517
+ */
518
+ var util = require ( 'util' ) ;
519
+ var scriptsList = [ ] ;
520
+ var scriptFmt = (
521
+ 'try { return (%s).apply(this, arguments); }\n' +
522
+ 'catch(e) { throw (e instanceof Error) ? e : new Error(e); }' ) ;
523
+ for ( var fnName in functions ) {
524
+ if ( functions . hasOwnProperty ( fnName ) ) {
525
+ exports [ fnName ] = util . format ( scriptFmt , functions [ fnName ] ) ;
526
+ scriptsList . push ( util . format ( '%s: %s' , fnName , functions [ fnName ] ) ) ;
527
+ }
528
+ }
529
+
530
+ exports . installInBrowser = ( util . format (
531
+ 'window.clientSideScripts = {%s};' , scriptsList . join ( ', ' ) ) ) ;
0 commit comments