@@ -134,10 +134,16 @@ function ptorMixin(to: any, from: any, fnName: string, setupFn?: Function) {
134
134
arguments [ i ] = arguments [ i ] . getWebElement ( ) ;
135
135
}
136
136
}
137
+ const run = ( ) => {
138
+ return from [ fnName ] . apply ( from , arguments ) ;
139
+ } ;
137
140
if ( setupFn ) {
138
- setupFn ( ) ;
141
+ const setupResult = setupFn ( ) ;
142
+ if ( setupResult && ( typeof setupResult . then === 'function' ) ) {
143
+ return setupResult . then ( run ) ;
144
+ }
139
145
}
140
- return from [ fnName ] . apply ( from , arguments ) ;
146
+ return run ( ) ;
141
147
} ;
142
148
} ;
143
149
@@ -252,13 +258,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
252
258
* @type {boolean }
253
259
*/
254
260
set ignoreSynchronization ( value ) {
255
- this . driver . controlFlow ( ) . execute ( ( ) => {
256
- if ( this . bpClient ) {
257
- logger . debug ( 'Setting waitForAngular' + value ) ;
258
- this . bpClient . setSynchronization ( ! value ) ;
259
- }
260
- } , `Set proxy synchronization to ${ value } ` ) ;
261
- this . internalIgnoreSynchronization = value ;
261
+ this . waitForAngularEnabled ( ! value ) ;
262
262
}
263
263
264
264
get ignoreSynchronization ( ) {
@@ -449,11 +449,20 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
449
449
* Call waitForAngularEnabled() without passing a value to read the current
450
450
* state without changing it.
451
451
*/
452
- waitForAngularEnabled ( enabled : boolean = null ) : boolean {
452
+ waitForAngularEnabled ( enabled : boolean = null ) : wdpromise . Promise < boolean > {
453
453
if ( enabled != null ) {
454
- this . ignoreSynchronization = ! enabled ;
454
+ const ret = this . driver . controlFlow ( ) . execute ( ( ) => {
455
+ if ( this . bpClient ) {
456
+ logger . debug ( 'Setting waitForAngular' + ! enabled ) ;
457
+ return this . bpClient . setSynchronization ( enabled ) . then ( ( ) => {
458
+ return enabled ;
459
+ } ) ;
460
+ }
461
+ } , `Set proxy synchronization enabled to ${ enabled } ` ) ;
462
+ this . internalIgnoreSynchronization = ! enabled ;
463
+ return ret ;
455
464
}
456
- return ! this . ignoreSynchronization ;
465
+ return wdpromise . when ( ! this . ignoreSynchronization ) ;
457
466
}
458
467
459
468
/**
@@ -659,7 +668,9 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
659
668
660
669
let runWaitForAngularScript : ( ) => wdpromise . Promise < any > = ( ) => {
661
670
if ( this . plugins_ . skipAngularStability ( ) || this . bpClient ) {
662
- return wdpromise . when ( null ) ;
671
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
672
+ return wdpromise . when ( null ) ;
673
+ } , 'bpClient or plugin stability override' ) ;
663
674
} else {
664
675
return this . executeAsyncScript_ (
665
676
clientSideScripts . waitForAngular , 'Protractor.waitForAngular()' + description ,
@@ -879,131 +890,139 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
879
890
get ( destination : string , timeout = this . getPageTimeout ) {
880
891
destination = this . baseUrl . indexOf ( 'file://' ) === 0 ? this . baseUrl + destination :
881
892
url . resolve ( this . baseUrl , destination ) ;
882
- let msg = ( str : string ) => {
883
- return 'Protractor.get(' + destination + ') - ' + str ;
884
- } ;
885
-
886
- if ( this . bpClient ) {
887
- this . driver . controlFlow ( ) . execute ( ( ) => {
888
- return this . bpClient . setSynchronization ( false ) ;
889
- } ) ;
890
- }
891
893
892
894
if ( this . ignoreSynchronization ) {
893
- this . driver . get ( destination ) ;
894
- return this . driver . controlFlow ( ) . execute ( ( ) => this . plugins_ . onPageLoad ( ) ) . then ( ( ) => { } ) ;
895
+ return this . driver . get ( destination )
896
+ . then ( ( ) => this . driver . controlFlow ( ) . execute ( ( ) => this . plugins_ . onPageLoad ( ) ) )
897
+ . then ( ( ) => null ) ;
895
898
}
896
899
897
- let deferred = wdpromise . defer < void > ( ) ;
898
-
899
- this . driver . get ( this . resetUrl ) . then ( null , deferred . reject ) ;
900
- this . executeScriptWithDescription (
901
- 'window.name = "' + DEFER_LABEL + '" + window.name;' +
902
- 'window.location.replace("' + destination + '");' ,
903
- msg ( 'reset url' ) )
904
- . then ( null , deferred . reject ) ;
905
-
906
- // We need to make sure the new url has loaded before
907
- // we try to execute any asynchronous scripts.
908
- this . driver
909
- . wait (
910
- ( ) => {
911
- return this
912
- . executeScriptWithDescription ( 'return window.location.href;' , msg ( 'get url' ) )
913
- . then (
914
- ( url : any ) => {
915
- return url !== this . resetUrl ;
916
- } ,
917
- ( err : IError ) => {
918
- if ( err . code == 13 ) {
919
- // Ignore the error, and continue trying. This is
920
- // because IE driver sometimes (~1%) will throw an
921
- // unknown error from this execution. See
922
- // https://github.com/angular/protractor/issues/841
923
- // This shouldn't mask errors because it will fail
924
- // with the timeout anyway.
925
- return false ;
926
- } else {
927
- throw err ;
928
- }
929
- } ) ;
930
- } ,
931
- timeout , 'waiting for page to load for ' + timeout + 'ms' )
932
- . then ( null , deferred . reject ) ;
933
-
934
- this . driver . controlFlow ( ) . execute ( ( ) => {
935
- return this . plugins_ . onPageLoad ( ) ;
936
- } ) ;
900
+ let msg = ( str : string ) => {
901
+ return 'Protractor.get(' + destination + ') - ' + str ;
902
+ } ;
937
903
938
- // Make sure the page is an Angular page.
939
- this . executeAsyncScript_ (
940
- clientSideScripts . testForAngular , msg ( 'test for angular' ) , Math . floor ( timeout / 1000 ) ,
941
- this . ng12Hybrid )
942
- . then (
943
- ( angularTestResult : { ver : number , message : string } ) => {
944
- let angularVersion = angularTestResult . ver ;
945
- if ( ! angularVersion ) {
946
- let message = angularTestResult . message ;
947
- logger . error ( `Could not find Angular on page ${ destination } : ${ message } ` ) ;
948
- throw new Error (
949
- `Angular could not be found on the page ${ destination } . If this is not an ` +
950
- `Angular application, you may need to turn off waiting for Angular. Please ` +
951
- `see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load` ) ;
952
- }
953
- return angularVersion ;
954
- } ,
955
- ( err : Error ) => {
956
- throw new Error ( 'Error while running testForAngular: ' + err . message ) ;
957
- } )
958
- . then ( loadMocks , deferred . reject ) ;
959
-
960
- let self = this ;
961
- function loadMocks ( angularVersion : number ) {
962
- if ( angularVersion === 1 ) {
963
- // At this point, Angular will pause for us until angular.resumeBootstrap is called.
964
- let moduleNames : string [ ] = [ ] ;
965
- for ( const { name, script, args} of self . mockModules_ ) {
966
- moduleNames . push ( name ) ;
967
- let executeScriptArgs = [ script , msg ( 'add mock module ' + name ) , ...args ] ;
968
- self . executeScriptWithDescription . apply ( self , executeScriptArgs )
904
+ return this . driver . controlFlow ( )
905
+ . execute ( ( ) => {
906
+ return wdpromise . when ( null ) ;
907
+ } )
908
+ . then ( ( ) => {
909
+ if ( this . bpClient ) {
910
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
911
+ return this . bpClient . setSynchronization ( false ) ;
912
+ } ) ;
913
+ }
914
+ } )
915
+ . then ( ( ) => {
916
+ // Go to reset url
917
+ return this . driver . get ( this . resetUrl ) ;
918
+ } )
919
+ . then ( ( ) => {
920
+ // Set defer label and navigate
921
+ return this . executeScriptWithDescription (
922
+ 'window.name = "' + DEFER_LABEL + '" + window.name;' +
923
+ 'window.location.replace("' + destination + '");' ,
924
+ msg ( 'reset url' ) ) ;
925
+ } )
926
+ . then ( ( ) => {
927
+ // We need to make sure the new url has loaded before
928
+ // we try to execute any asynchronous scripts.
929
+ return this . driver . wait ( ( ) => {
930
+ return this . executeScriptWithDescription ( 'return window.location.href;' , msg ( 'get url' ) )
931
+ . then (
932
+ ( url : any ) => {
933
+ return url !== this . resetUrl ;
934
+ } ,
935
+ ( err : IError ) => {
936
+ if ( err . code == 13 ) {
937
+ // Ignore the error, and continue trying. This is
938
+ // because IE driver sometimes (~1%) will throw an
939
+ // unknown error from this execution. See
940
+ // https://github.com/angular/protractor/issues/841
941
+ // This shouldn't mask errors because it will fail
942
+ // with the timeout anyway.
943
+ return false ;
944
+ } else {
945
+ throw err ;
946
+ }
947
+ } ) ;
948
+ } , timeout , 'waiting for page to load for ' + timeout + 'ms' ) ;
949
+ } )
950
+ . then ( ( ) => {
951
+ // Run Plugins
952
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
953
+ return this . plugins_ . onPageLoad ( ) ;
954
+ } ) ;
955
+ } )
956
+ . then ( ( ) => {
957
+ // Make sure the page is an Angular page.
958
+ return this
959
+ . executeAsyncScript_ (
960
+ clientSideScripts . testForAngular , msg ( 'test for angular' ) ,
961
+ Math . floor ( timeout / 1000 ) , this . ng12Hybrid )
969
962
. then (
970
- null ,
963
+ ( angularTestResult : { ver : number , message : string } ) => {
964
+ let angularVersion = angularTestResult . ver ;
965
+ if ( ! angularVersion ) {
966
+ let message = angularTestResult . message ;
967
+ logger . error ( `Could not find Angular on page ${ destination } : ${ message } ` ) ;
968
+ throw new Error (
969
+ 'Angular could not be found on the page ${destination}.' +
970
+ `If this is not an Angular application, you may need to turn off waiting for Angular.
971
+ Please see
972
+ https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load` ) ;
973
+ }
974
+ return angularVersion ;
975
+ } ,
971
976
( err : Error ) => {
972
- throw new Error (
973
- 'Error while running module script ' + name + ': ' + err . message ) ;
974
- } )
975
- . then ( null , deferred . reject ) ;
976
- }
977
-
978
- self . executeScriptWithDescription (
979
- 'window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' +
980
- 'angular.resumeBootstrap(arguments[0]);' ,
981
- msg ( 'resume bootstrap' ) , moduleNames )
982
- . then ( null , deferred . reject ) ;
983
- } else {
984
- // TODO: support mock modules in Angular2. For now, error if someone
985
- // has tried to use one.
986
- if ( self . mockModules_ . length > 1 ) {
987
- deferred . reject (
988
- 'Trying to load mock modules on an Angular2 app ' +
989
- 'is not yet supported.' ) ;
990
- }
991
- }
992
- }
993
-
994
- if ( this . bpClient ) {
995
- this . driver . controlFlow ( ) . execute ( ( ) => {
996
- return this . bpClient . setSynchronization ( ! this . internalIgnoreSynchronization ) ;
997
- } ) ;
998
- }
999
-
1000
- this . driver . controlFlow ( ) . execute ( ( ) => {
1001
- return this . plugins_ . onPageStable ( ) . then ( ( ) => {
1002
- deferred . fulfill ( ) ;
1003
- } , deferred . reject ) ;
1004
- } ) ;
977
+ throw new Error ( 'Error while running testForAngular: ' + err . message ) ;
978
+ } ) ;
1005
979
1006
- return deferred . promise ;
980
+ } )
981
+ . then ( ( angularVersion ) => {
982
+ // Load Angular Mocks
983
+ if ( angularVersion === 1 ) {
984
+ // At this point, Angular will pause for us until angular.resumeBootstrap is called.
985
+ let moduleNames : string [ ] = [ ] ;
986
+ let modulePromise : wdpromise . Promise < void > = wdpromise . when ( null ) ;
987
+ for ( const { name, script, args} of this . mockModules_ ) {
988
+ moduleNames . push ( name ) ;
989
+ let executeScriptArgs = [ script , msg ( 'add mock module ' + name ) , ...args ] ;
990
+ modulePromise = modulePromise . then (
991
+ ( ) => this . executeScriptWithDescription . apply ( this , executeScriptArgs )
992
+ . then ( null , ( err : Error ) => {
993
+ throw new Error (
994
+ 'Error while running module script ' + name + ': ' + err . message ) ;
995
+ } ) ) ;
996
+ }
997
+
998
+ return modulePromise . then (
999
+ ( ) => this . executeScriptWithDescription (
1000
+ 'window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' +
1001
+ 'angular.resumeBootstrap(arguments[0]);' ,
1002
+ msg ( 'resume bootstrap' ) , moduleNames ) ) ;
1003
+ } else {
1004
+ // TODO: support mock modules in Angular2. For now, error if someone
1005
+ // has tried to use one.
1006
+ if ( this . mockModules_ . length > 1 ) {
1007
+ throw 'Trying to load mock modules on an Angular2 app is not yet supported.' ;
1008
+ }
1009
+ }
1010
+ } )
1011
+ . then ( ( ) => {
1012
+ // Reset bpClient sync
1013
+ if ( this . bpClient ) {
1014
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
1015
+ return this . bpClient . setSynchronization ( ! this . internalIgnoreSynchronization ) ;
1016
+ } ) ;
1017
+ }
1018
+ } )
1019
+ . then ( ( ) => {
1020
+ // Run Plugins
1021
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
1022
+ return this . plugins_ . onPageStable ( ) ;
1023
+ } ) ;
1024
+ } )
1025
+ . then ( ( ) => null ) ;
1007
1026
}
1008
1027
1009
1028
/**
@@ -1053,15 +1072,15 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
1053
1072
* page has been changed.
1054
1073
*/
1055
1074
setLocation ( url : string ) : wdpromise . Promise < any > {
1056
- this . waitForAngular ( ) ;
1057
- return this
1058
- . executeScriptWithDescription (
1059
- clientSideScripts . setLocation , 'Protractor.setLocation()' , this . rootEl , url )
1060
- . then ( ( browserErr : Error ) => {
1061
- if ( browserErr ) {
1062
- throw 'Error while navigating to \'' + url + '\' : ' + JSON . stringify ( browserErr ) ;
1063
- }
1064
- } ) ;
1075
+ return this . waitForAngular ( ) . then (
1076
+ ( ) => this . executeScriptWithDescription (
1077
+ clientSideScripts . setLocation , 'Protractor.setLocation()' , this . rootEl , url )
1078
+ . then ( ( browserErr : Error ) => {
1079
+ if ( browserErr ) {
1080
+ throw 'Error while navigating to \'' + url + '\' : ' +
1081
+ JSON . stringify ( browserErr ) ;
1082
+ }
1083
+ } ) ) ;
1065
1084
}
1066
1085
1067
1086
/**
@@ -1075,9 +1094,9 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
1075
1094
* AngularJS.
1076
1095
*/
1077
1096
getLocationAbsUrl ( ) : wdpromise . Promise < any > {
1078
- this . waitForAngular ( ) ;
1079
- return this . executeScriptWithDescription (
1080
- clientSideScripts . getLocationAbsUrl , 'Protractor.getLocationAbsUrl()' , this . rootEl ) ;
1097
+ return this . waitForAngular ( ) . then (
1098
+ ( ) => this . executeScriptWithDescription (
1099
+ clientSideScripts . getLocationAbsUrl , 'Protractor.getLocationAbsUrl()' , this . rootEl ) ) ;
1081
1100
}
1082
1101
1083
1102
/**
@@ -1102,10 +1121,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
1102
1121
*/
1103
1122
debugger ( ) {
1104
1123
// jshint debug: true
1105
- this . driver . executeScript ( clientSideScripts . installInBrowser ) ;
1106
- wdpromise . controlFlow ( ) . execute ( ( ) => {
1107
- debugger ;
1108
- } , 'add breakpoint to control flow' ) ;
1124
+ return this . driver . executeScript ( clientSideScripts . installInBrowser )
1125
+ . then ( ( ) => wdpromise . controlFlow ( ) . execute ( ( ) => {
1126
+ debugger ;
1127
+ } , 'add breakpoint to control flow' ) ) ;
1109
1128
}
1110
1129
1111
1130
/**
0 commit comments