@@ -12,6 +12,7 @@ var clientSideScripts = require('./clientsidescripts.js');
12
12
var ProtractorBy = require ( './locators.js' ) . ProtractorBy ;
13
13
var ExpectedConditions = require ( './expectedConditions.js' ) ;
14
14
15
+ // jshint browser: true
15
16
/* global angular */
16
17
17
18
var DEFER_LABEL = 'NG_DEFER_BOOTSTRAP!' ;
@@ -276,6 +277,7 @@ Protractor.prototype.executeAsyncScript_ =
276
277
*/
277
278
Protractor . prototype . waitForAngular = function ( opt_description ) {
278
279
var description = opt_description ? ' - ' + opt_description : '' ;
280
+ var self = this ;
279
281
if ( this . ignoreSynchronization ) {
280
282
return webdriver . promise . fulfilled ( ) ;
281
283
}
@@ -301,9 +303,41 @@ Protractor.prototype.waitForAngular = function(opt_description) {
301
303
timeout = / - ? [ \d \. ] * \ m s / . exec ( err . message ) ;
302
304
}
303
305
if ( timeout ) {
304
- throw 'Timed out waiting for Protractor to synchronize with ' +
306
+ var errMsg = 'Timed out waiting for Protractor to synchronize with ' +
305
307
'the page after ' + timeout + '. Please see ' +
306
308
'https://github.com/angular/protractor/blob/master/docs/faq.md' ;
309
+ var pendingTimeoutsPromise = self . executeScript_ (
310
+ 'return window.NG_PENDING_TIMEOUTS' ,
311
+ 'Protractor.waitForAngular() - getting pending timeouts' + description
312
+ ) ;
313
+ var pendingHttpsPromise = self . executeScript_ (
314
+ clientSideScripts . getPendingHttpRequests ,
315
+ 'Protractor.waitForAngular() - getting pending https' + description ,
316
+ self . rootEl
317
+ ) ;
318
+ return webdriver . promise . all ( [
319
+ pendingTimeoutsPromise , pendingHttpsPromise ] ) .
320
+ then ( function ( arr ) {
321
+ var pendingTimeouts = arr [ 0 ] || [ ] ;
322
+ var pendingHttps = arr [ 1 ] || [ ] ;
323
+
324
+ var key , pendingTasks = [ ] ;
325
+ for ( key in pendingTimeouts ) {
326
+ if ( pendingTimeouts . hasOwnProperty ( key ) ) {
327
+ pendingTasks . push ( '- $timeout: ' + pendingTimeouts [ key ] ) ;
328
+ }
329
+ }
330
+ for ( key in pendingHttps ) {
331
+ pendingTasks . push ( '- $http: ' + pendingHttps [ key ] . url ) ;
332
+ }
333
+ if ( pendingTasks . length ) {
334
+ errMsg += '. The following tasks were pending:\n' ;
335
+ errMsg += pendingTasks . join ( '\n' ) ;
336
+ }
337
+ throw errMsg ;
338
+ } , function ( ) {
339
+ throw errMsg ;
340
+ } ) ;
307
341
} else {
308
342
throw err ;
309
343
}
@@ -414,6 +448,48 @@ Protractor.prototype.addBaseMockModules_ = function() {
414
448
if ( $compileProvider . debugInfoEnabled ) {
415
449
$compileProvider . debugInfoEnabled ( true ) ;
416
450
}
451
+ } ] ) .
452
+ config ( [ '$provide' , function ( $provide ) {
453
+ $provide . decorator ( '$timeout' , [ '$delegate' , function ( $delegate ) {
454
+ var $timeout = $delegate ;
455
+
456
+ var taskId = 0 ;
457
+ if ( ! window . NG_PENDING_TIMEOUTS ) {
458
+ window . NG_PENDING_TIMEOUTS = { } ;
459
+ }
460
+
461
+ var extendedTimeout = function ( ) {
462
+ var args = Array . prototype . slice . call ( arguments ) ;
463
+ if ( typeof ( args [ 0 ] ) !== 'function' ) {
464
+ return $timeout . apply ( null , args ) ;
465
+ }
466
+
467
+ taskId ++ ;
468
+ var fn = args [ 0 ] ;
469
+ window . NG_PENDING_TIMEOUTS [ taskId ] = fn . toString ( ) ;
470
+ var wrappedFn = ( function ( taskId_ ) {
471
+ return function ( ) {
472
+ delete window . NG_PENDING_TIMEOUTS [ taskId_ ] ;
473
+ return fn . apply ( null , arguments ) ;
474
+ } ;
475
+ } ) ( taskId ) ;
476
+ args [ 0 ] = wrappedFn ;
477
+
478
+ var promise = $timeout . apply ( null , args ) ;
479
+ promise . ptorTaskId_ = taskId ;
480
+ return promise ;
481
+ } ;
482
+
483
+ extendedTimeout . cancel = function ( ) {
484
+ var taskId_ = arguments [ 0 ] && arguments [ 0 ] . ptorTaskId_ ;
485
+ if ( taskId_ ) {
486
+ delete window . NG_PENDING_TIMEOUTS [ taskId_ ] ;
487
+ }
488
+ return $timeout . cancel . apply ( $timeout , arguments ) ;
489
+ } ;
490
+
491
+ return extendedTimeout ;
492
+ } ] ) ;
417
493
} ] ) ;
418
494
} ) ;
419
495
} ;
0 commit comments