@@ -88,10 +88,16 @@ function ptorMixin(to: any, from: any, fnName: string, setupFn?: Function) {
88
88
arguments [ i ] = arguments [ i ] . getWebElement ( ) ;
89
89
}
90
90
}
91
+ const run = ( ) => {
92
+ return from [ fnName ] . apply ( from , arguments ) ;
93
+ } ;
91
94
if ( setupFn ) {
92
- setupFn ( ) ;
95
+ const setupResult = setupFn ( ) ;
96
+ if ( setupResult && ( typeof setupResult . then === 'function' ) ) {
97
+ return setupResult . then ( run ) ;
98
+ }
93
99
}
94
- return from [ fnName ] . apply ( from , arguments ) ;
100
+ return run ( ) ;
95
101
} ;
96
102
} ;
97
103
@@ -206,13 +212,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
206
212
* @type {boolean }
207
213
*/
208
214
set ignoreSynchronization ( value ) {
209
- this . driver . controlFlow ( ) . execute ( ( ) => {
210
- if ( this . bpClient ) {
211
- logger . debug ( 'Setting waitForAngular' + value ) ;
212
- this . bpClient . setSynchronization ( ! value ) ;
213
- }
214
- } , `Set proxy synchronization to ${ value } ` ) ;
215
- this . internalIgnoreSynchronization = value ;
215
+ this . waitForAngularEnabled ( ! value ) ;
216
216
}
217
217
218
218
get ignoreSynchronization ( ) {
@@ -403,11 +403,20 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
403
403
* Call waitForAngularEnabled() without passing a value to read the current
404
404
* state without changing it.
405
405
*/
406
- waitForAngularEnabled ( enabled : boolean = null ) : boolean {
406
+ waitForAngularEnabled ( enabled : boolean = null ) : wdpromise . Promise < boolean > {
407
407
if ( enabled != null ) {
408
- this . ignoreSynchronization = ! enabled ;
408
+ const ret = this . driver . controlFlow ( ) . execute ( ( ) => {
409
+ if ( this . bpClient ) {
410
+ logger . debug ( 'Setting waitForAngular' + ! enabled ) ;
411
+ return this . bpClient . setSynchronization ( enabled ) . then ( ( ) => {
412
+ return enabled ;
413
+ } ) ;
414
+ }
415
+ } , `Set proxy synchronization enabled to ${ enabled } ` ) ;
416
+ this . internalIgnoreSynchronization = ! enabled ;
417
+ return ret ;
409
418
}
410
- return ! this . ignoreSynchronization ;
419
+ return wdpromise . when ( ! this . ignoreSynchronization ) ;
411
420
}
412
421
413
422
/**
@@ -613,7 +622,9 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
613
622
614
623
let runWaitForAngularScript : ( ) => wdpromise . Promise < any > = ( ) => {
615
624
if ( this . plugins_ . skipAngularStability ( ) || this . bpClient ) {
616
- return wdpromise . fulfilled ( ) ;
625
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
626
+ return true ;
627
+ } , 'A plugin has set skipAngularStability' ) ;
617
628
} else {
618
629
return this . executeAsyncScript_ (
619
630
clientSideScripts . waitForAngular , 'Protractor.waitForAngular()' + description ,
@@ -833,131 +844,139 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
833
844
get ( destination : string , timeout = this . getPageTimeout ) {
834
845
destination = this . baseUrl . indexOf ( 'file://' ) === 0 ? this . baseUrl + destination :
835
846
url . resolve ( this . baseUrl , destination ) ;
836
- let msg = ( str : string ) => {
837
- return 'Protractor.get(' + destination + ') - ' + str ;
838
- } ;
839
-
840
- if ( this . bpClient ) {
841
- this . driver . controlFlow ( ) . execute ( ( ) => {
842
- return this . bpClient . setSynchronization ( false ) ;
843
- } ) ;
844
- }
845
847
846
848
if ( this . ignoreSynchronization ) {
847
- this . driver . get ( destination ) ;
848
- return this . driver . controlFlow ( ) . execute ( ( ) => this . plugins_ . onPageLoad ( ) ) . then ( ( ) => { } ) ;
849
+ return this . driver . get ( destination )
850
+ . then ( ( ) => this . driver . controlFlow ( ) . execute ( ( ) => this . plugins_ . onPageLoad ( ) ) )
851
+ . then ( ( ) => null ) ;
849
852
}
850
853
851
- let deferred = wdpromise . defer < void > ( ) ;
852
-
853
- this . driver . get ( this . resetUrl ) . then ( null , deferred . reject ) ;
854
- this . executeScriptWithDescription (
855
- 'window.name = "' + DEFER_LABEL + '" + window.name;' +
856
- 'window.location.replace("' + destination + '");' ,
857
- msg ( 'reset url' ) )
858
- . then ( null , deferred . reject ) ;
859
-
860
- // We need to make sure the new url has loaded before
861
- // we try to execute any asynchronous scripts.
862
- this . driver
863
- . wait (
864
- ( ) => {
865
- return this
866
- . executeScriptWithDescription ( 'return window.location.href;' , msg ( 'get url' ) )
867
- . then (
868
- ( url : any ) => {
869
- return url !== this . resetUrl ;
870
- } ,
871
- ( err : IError ) => {
872
- if ( err . code == 13 ) {
873
- // Ignore the error, and continue trying. This is
874
- // because IE driver sometimes (~1%) will throw an
875
- // unknown error from this execution. See
876
- // https://github.com/angular/protractor/issues/841
877
- // This shouldn't mask errors because it will fail
878
- // with the timeout anyway.
879
- return false ;
880
- } else {
881
- throw err ;
882
- }
883
- } ) ;
884
- } ,
885
- timeout , 'waiting for page to load for ' + timeout + 'ms' )
886
- . then ( null , deferred . reject ) ;
887
-
888
- this . driver . controlFlow ( ) . execute ( ( ) => {
889
- return this . plugins_ . onPageLoad ( ) ;
890
- } ) ;
854
+ let msg = ( str : string ) => {
855
+ return 'Protractor.get(' + destination + ') - ' + str ;
856
+ } ;
891
857
892
- // Make sure the page is an Angular page.
893
- this . executeAsyncScript_ (
894
- clientSideScripts . testForAngular , msg ( 'test for angular' ) , Math . floor ( timeout / 1000 ) ,
895
- this . ng12Hybrid )
896
- . then (
897
- ( angularTestResult : { ver : number , message : string } ) => {
898
- let angularVersion = angularTestResult . ver ;
899
- if ( ! angularVersion ) {
900
- let message = angularTestResult . message ;
901
- logger . error ( `Could not find Angular on page ${ destination } : ${ message } ` ) ;
902
- throw new Error (
903
- `Angular could not be found on the page ${ destination } . If this is not an ` +
904
- `Angular application, you may need to turn off waiting for Angular. Please ` +
905
- `see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load` ) ;
906
- }
907
- return angularVersion ;
908
- } ,
909
- ( err : Error ) => {
910
- throw new Error ( 'Error while running testForAngular: ' + err . message ) ;
911
- } )
912
- . then ( loadMocks , deferred . reject ) ;
913
-
914
- let self = this ;
915
- function loadMocks ( angularVersion : number ) {
916
- if ( angularVersion === 1 ) {
917
- // At this point, Angular will pause for us until angular.resumeBootstrap is called.
918
- let moduleNames : string [ ] = [ ] ;
919
- for ( const { name, script, args} of self . mockModules_ ) {
920
- moduleNames . push ( name ) ;
921
- let executeScriptArgs = [ script , msg ( 'add mock module ' + name ) , ...args ] ;
922
- self . executeScriptWithDescription . apply ( self , executeScriptArgs )
858
+ return this . driver . controlFlow ( )
859
+ . execute ( ( ) => {
860
+ return wdpromise . when ( null ) ;
861
+ } )
862
+ . then ( ( ) => {
863
+ if ( this . bpClient ) {
864
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
865
+ return this . bpClient . setSynchronization ( false ) ;
866
+ } ) ;
867
+ }
868
+ } )
869
+ . then ( ( ) => {
870
+ // Go to reset url
871
+ return this . driver . get ( this . resetUrl ) ;
872
+ } )
873
+ . then ( ( ) => {
874
+ // Set defer label and navigate
875
+ return this . executeScriptWithDescription (
876
+ 'window.name = "' + DEFER_LABEL + '" + window.name;' +
877
+ 'window.location.replace("' + destination + '");' ,
878
+ msg ( 'reset url' ) ) ;
879
+ } )
880
+ . then ( ( ) => {
881
+ // We need to make sure the new url has loaded before
882
+ // we try to execute any asynchronous scripts.
883
+ return this . driver . wait ( ( ) => {
884
+ return this . executeScriptWithDescription ( 'return window.location.href;' , msg ( 'get url' ) )
885
+ . then (
886
+ ( url : any ) => {
887
+ return url !== this . resetUrl ;
888
+ } ,
889
+ ( err : IError ) => {
890
+ if ( err . code == 13 ) {
891
+ // Ignore the error, and continue trying. This is
892
+ // because IE driver sometimes (~1%) will throw an
893
+ // unknown error from this execution. See
894
+ // https://github.com/angular/protractor/issues/841
895
+ // This shouldn't mask errors because it will fail
896
+ // with the timeout anyway.
897
+ return false ;
898
+ } else {
899
+ throw err ;
900
+ }
901
+ } ) ;
902
+ } , timeout , 'waiting for page to load for ' + timeout + 'ms' ) ;
903
+ } )
904
+ . then ( ( ) => {
905
+ // Run Plugins
906
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
907
+ return this . plugins_ . onPageLoad ( ) ;
908
+ } ) ;
909
+ } )
910
+ . then ( ( ) => {
911
+ // Make sure the page is an Angular page.
912
+ return this
913
+ . executeAsyncScript_ (
914
+ clientSideScripts . testForAngular , msg ( 'test for angular' ) ,
915
+ Math . floor ( timeout / 1000 ) , this . ng12Hybrid )
923
916
. then (
924
- null ,
917
+ ( angularTestResult : { ver : number , message : string } ) => {
918
+ let angularVersion = angularTestResult . ver ;
919
+ if ( ! angularVersion ) {
920
+ let message = angularTestResult . message ;
921
+ logger . error ( `Could not find Angular on page ${ destination } : ${ message } ` ) ;
922
+ throw new Error (
923
+ 'Angular could not be found on the page ${destination}.' +
924
+ `If this is not an Angular application, you may need to turn off waiting for Angular.
925
+ Please see
926
+ https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load` ) ;
927
+ }
928
+ return angularVersion ;
929
+ } ,
925
930
( err : Error ) => {
926
- throw new Error (
927
- 'Error while running module script ' + name + ': ' + err . message ) ;
928
- } )
929
- . then ( null , deferred . reject ) ;
930
- }
931
-
932
- self . executeScriptWithDescription (
933
- 'window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' +
934
- 'angular.resumeBootstrap(arguments[0]);' ,
935
- msg ( 'resume bootstrap' ) , moduleNames )
936
- . then ( null , deferred . reject ) ;
937
- } else {
938
- // TODO: support mock modules in Angular2. For now, error if someone
939
- // has tried to use one.
940
- if ( self . mockModules_ . length > 1 ) {
941
- deferred . reject (
942
- 'Trying to load mock modules on an Angular2 app ' +
943
- 'is not yet supported.' ) ;
944
- }
945
- }
946
- }
947
-
948
- if ( this . bpClient ) {
949
- this . driver . controlFlow ( ) . execute ( ( ) => {
950
- return this . bpClient . setSynchronization ( ! this . internalIgnoreSynchronization ) ;
951
- } ) ;
952
- }
953
-
954
- this . driver . controlFlow ( ) . execute ( ( ) => {
955
- return this . plugins_ . onPageStable ( ) . then ( ( ) => {
956
- deferred . fulfill ( ) ;
957
- } , deferred . reject ) ;
958
- } ) ;
931
+ throw new Error ( 'Error while running testForAngular: ' + err . message ) ;
932
+ } ) ;
959
933
960
- return deferred . promise ;
934
+ } )
935
+ . then ( ( angularVersion ) => {
936
+ // Load Angular Mocks
937
+ if ( angularVersion === 1 ) {
938
+ // At this point, Angular will pause for us until angular.resumeBootstrap is called.
939
+ let moduleNames : string [ ] = [ ] ;
940
+ let modulePromise : wdpromise . Promise < void > = wdpromise . when ( null ) ;
941
+ for ( const { name, script, args} of this . mockModules_ ) {
942
+ moduleNames . push ( name ) ;
943
+ let executeScriptArgs = [ script , msg ( 'add mock module ' + name ) , ...args ] ;
944
+ modulePromise = modulePromise . then (
945
+ ( ) => this . executeScriptWithDescription . apply ( this , executeScriptArgs )
946
+ . then ( null , ( err : Error ) => {
947
+ throw new Error (
948
+ 'Error while running module script ' + name + ': ' + err . message ) ;
949
+ } ) ) ;
950
+ }
951
+
952
+ return modulePromise . then (
953
+ ( ) => this . executeScriptWithDescription (
954
+ 'window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = ' +
955
+ 'angular.resumeBootstrap(arguments[0]);' ,
956
+ msg ( 'resume bootstrap' ) , moduleNames ) ) ;
957
+ } else {
958
+ // TODO: support mock modules in Angular2. For now, error if someone
959
+ // has tried to use one.
960
+ if ( this . mockModules_ . length > 1 ) {
961
+ throw 'Trying to load mock modules on an Angular2 app is not yet supported.' ;
962
+ }
963
+ }
964
+ } )
965
+ . then ( ( ) => {
966
+ // Reset bpClient sync
967
+ if ( this . bpClient ) {
968
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
969
+ return this . bpClient . setSynchronization ( ! this . internalIgnoreSynchronization ) ;
970
+ } ) ;
971
+ }
972
+ } )
973
+ . then ( ( ) => {
974
+ // Run Plugins
975
+ return this . driver . controlFlow ( ) . execute ( ( ) => {
976
+ return this . plugins_ . onPageStable ( ) ;
977
+ } ) ;
978
+ } )
979
+ . then ( ( ) => null ) ;
961
980
}
962
981
963
982
/**
@@ -1007,15 +1026,15 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
1007
1026
* page has been changed.
1008
1027
*/
1009
1028
setLocation ( url : string ) : wdpromise . Promise < any > {
1010
- this . waitForAngular ( ) ;
1011
- return this
1012
- . executeScriptWithDescription (
1013
- clientSideScripts . setLocation , 'Protractor.setLocation()' , this . rootEl , url )
1014
- . then ( ( browserErr : Error ) => {
1015
- if ( browserErr ) {
1016
- throw 'Error while navigating to \'' + url + '\' : ' + JSON . stringify ( browserErr ) ;
1017
- }
1018
- } ) ;
1029
+ return this . waitForAngular ( ) . then (
1030
+ ( ) => this . executeScriptWithDescription (
1031
+ clientSideScripts . setLocation , 'Protractor.setLocation()' , this . rootEl , url )
1032
+ . then ( ( browserErr : Error ) => {
1033
+ if ( browserErr ) {
1034
+ throw 'Error while navigating to \'' + url + '\' : ' +
1035
+ JSON . stringify ( browserErr ) ;
1036
+ }
1037
+ } ) ) ;
1019
1038
}
1020
1039
1021
1040
/**
@@ -1029,9 +1048,9 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
1029
1048
* AngularJS.
1030
1049
*/
1031
1050
getLocationAbsUrl ( ) : wdpromise . Promise < any > {
1032
- this . waitForAngular ( ) ;
1033
- return this . executeScriptWithDescription (
1034
- clientSideScripts . getLocationAbsUrl , 'Protractor.getLocationAbsUrl()' , this . rootEl ) ;
1051
+ return this . waitForAngular ( ) . then (
1052
+ ( ) => this . executeScriptWithDescription (
1053
+ clientSideScripts . getLocationAbsUrl , 'Protractor.getLocationAbsUrl()' , this . rootEl ) ) ;
1035
1054
}
1036
1055
1037
1056
/**
@@ -1056,10 +1075,10 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
1056
1075
*/
1057
1076
debugger ( ) {
1058
1077
// jshint debug: true
1059
- this . driver . executeScript ( clientSideScripts . installInBrowser ) ;
1060
- wdpromise . controlFlow ( ) . execute ( ( ) => {
1061
- debugger ;
1062
- } , 'add breakpoint to control flow' ) ;
1078
+ return this . driver . executeScript ( clientSideScripts . installInBrowser )
1079
+ . then ( ( ) => wdpromise . controlFlow ( ) . execute ( ( ) => {
1080
+ debugger ;
1081
+ } , 'add breakpoint to control flow' ) ) ;
1063
1082
}
1064
1083
1065
1084
/**
0 commit comments