@@ -663,6 +663,22 @@ describe('$location', function() {
663
663
} ) ;
664
664
} ) ;
665
665
666
+
667
+ it ( 'should not get caught in infinite digest when replacing path in locationChangeSuccess handler' , function ( ) {
668
+ initService ( { html5Mode :true , supportHistory :false } ) ;
669
+ mockUpBrowser ( { initialUrl :'http://server/base/home' , baseHref :'/base/' } ) ;
670
+ inject (
671
+ function ( $browser , $location , $rootScope , $window ) {
672
+ $rootScope . $on ( '$locationChangeSuccess' , function ( ) {
673
+ if ( $location . path ( ) !== '/' ) {
674
+ $location . path ( '/' ) . replace ( ) ;
675
+ }
676
+ } ) ;
677
+ $rootScope . $digest ( ) ;
678
+ }
679
+ ) ;
680
+ } ) ;
681
+
666
682
it ( 'should not infinitely digest when using a semicolon in initial path' , function ( ) {
667
683
initService ( { html5Mode :true , supportHistory :true } ) ;
668
684
mockUpBrowser ( { initialUrl :'http://localhost:9876/;jsessionid=foo' , baseHref :'/' } ) ;
@@ -672,6 +688,162 @@ describe('$location', function() {
672
688
} ) . not . toThrow ( ) ;
673
689
} ) ;
674
690
} ) ;
691
+
692
+
693
+ function updatePathOnLocationChangeSuccessTo ( newPath ) {
694
+ inject ( function ( $rootScope , $location ) {
695
+ $rootScope . $on ( '$locationChangeSuccess' , function ( event , newUrl , oldUrl ) {
696
+ $location . path ( newPath ) ;
697
+ } ) ;
698
+ } ) ;
699
+ }
700
+
701
+
702
+ describe ( 'location watch for hashbang browsers' , function ( ) {
703
+
704
+ it ( 'should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /Home' , function ( ) {
705
+ initService ( { html5Mode : true , supportHistory : false } ) ;
706
+ mockUpBrowser ( { initialUrl :'http://server/app/' , baseHref :'/app/' } ) ;
707
+ inject ( function ( $rootScope , $location , $browser ) {
708
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
709
+
710
+ updatePathOnLocationChangeSuccessTo ( '/Home' ) ;
711
+
712
+ $rootScope . $digest ( ) ;
713
+
714
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/#/Home' ) ;
715
+ expect ( $location . path ( ) ) . toEqual ( '/Home' ) ;
716
+ expect ( $browserUrl . calls . length ) . toEqual ( 1 ) ;
717
+ } ) ;
718
+ } ) ;
719
+
720
+ it ( 'should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /' , function ( ) {
721
+ initService ( { html5Mode : true , supportHistory : false } ) ;
722
+ mockUpBrowser ( { initialUrl :'http://server/app/Home' , baseHref :'/app/' } ) ;
723
+ inject ( function ( $rootScope , $location , $browser , $window ) {
724
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
725
+
726
+ updatePathOnLocationChangeSuccessTo ( '/' ) ;
727
+
728
+ $rootScope . $digest ( ) ;
729
+
730
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/#/' ) ;
731
+ expect ( $location . path ( ) ) . toEqual ( '/' ) ;
732
+ expect ( $browserUrl . calls . length ) . toEqual ( 1 ) ;
733
+ expect ( $browserUrl . calls [ 0 ] . args ) . toEqual ( [ 'http://server/app/#/' , false , null ] ) ;
734
+ } ) ;
735
+ } ) ;
736
+
737
+ it ( 'should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /Home' , function ( ) {
738
+ initService ( { html5Mode : true , supportHistory : false } ) ;
739
+ mockUpBrowser ( { initialUrl :'http://server/app/' , baseHref :'/app/' } ) ;
740
+ inject ( function ( $rootScope , $location , $browser ) {
741
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
742
+
743
+ updatePathOnLocationChangeSuccessTo ( '/Home' ) ;
744
+ $rootScope . $digest ( ) ;
745
+
746
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/#/Home' ) ;
747
+ expect ( $location . path ( ) ) . toEqual ( '/Home' ) ;
748
+ expect ( $browserUrl . calls . length ) . toEqual ( 1 ) ;
749
+ expect ( $browserUrl . calls [ 0 ] . args ) . toEqual ( [ 'http://server/app/#/Home' , false , null ] ) ;
750
+ } ) ;
751
+ } ) ;
752
+
753
+ it ( 'should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /' , function ( ) {
754
+ initService ( { html5Mode : true , supportHistory : false } ) ;
755
+ mockUpBrowser ( { initialUrl :'http://server/app/' , baseHref :'/app/' } ) ;
756
+ inject ( function ( $rootScope , $location , $browser ) {
757
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
758
+
759
+ updatePathOnLocationChangeSuccessTo ( '/' ) ;
760
+ $rootScope . $digest ( ) ;
761
+
762
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/#/' ) ;
763
+ expect ( $location . path ( ) ) . toEqual ( '/' ) ;
764
+ expect ( $browserUrl . calls . length ) . toEqual ( 1 ) ;
765
+ } ) ;
766
+ } ) ;
767
+ } ) ;
768
+
769
+
770
+ describe ( 'location watch for HTML5 browsers' , function ( ) {
771
+ beforeEach ( initService ( { html5Mode : true , supportHistory : true } ) ) ;
772
+ beforeEach ( inject ( initBrowser ( { basePath : '/app/' } ) ) ) ;
773
+
774
+ it ( 'should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /Home' , function ( ) {
775
+ inject ( function ( $rootScope , $injector , $browser ) {
776
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
777
+
778
+ $browser . url ( 'http://server/app' ) ;
779
+ $browser . poll ( ) ;
780
+
781
+ var $location = $injector . get ( '$location' ) ;
782
+ updatePathOnLocationChangeSuccessTo ( '/Home' ) ;
783
+
784
+ $rootScope . $digest ( ) ;
785
+
786
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/Home' ) ;
787
+ expect ( $location . path ( ) ) . toEqual ( '/Home' ) ;
788
+ expect ( $browserUrl . calls . length ) . toEqual ( 3 ) ;
789
+ } ) ;
790
+ } ) ;
791
+
792
+ it ( 'should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /' , function ( ) {
793
+ inject ( function ( $rootScope , $injector , $browser ) {
794
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
795
+
796
+ $browser . url ( 'http://server/app' ) ;
797
+ $browser . poll ( ) ;
798
+
799
+ var $location = $injector . get ( '$location' ) ;
800
+ updatePathOnLocationChangeSuccessTo ( '/' ) ;
801
+
802
+ $rootScope . $digest ( ) ;
803
+
804
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/' ) ;
805
+ expect ( $location . path ( ) ) . toEqual ( '/' ) ;
806
+ expect ( $browserUrl . calls . length ) . toEqual ( 2 ) ;
807
+ } ) ;
808
+ } ) ;
809
+
810
+ it ( 'should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /Home' , function ( ) {
811
+ inject ( function ( $rootScope , $injector , $browser ) {
812
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
813
+
814
+ $browser . url ( 'http://server/app/' ) ;
815
+ $browser . poll ( ) ;
816
+
817
+ var $location = $injector . get ( '$location' ) ;
818
+ updatePathOnLocationChangeSuccessTo ( '/Home' ) ;
819
+
820
+ $rootScope . $digest ( ) ;
821
+
822
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/Home' ) ;
823
+ expect ( $location . path ( ) ) . toEqual ( '/Home' ) ;
824
+ expect ( $browserUrl . calls . length ) . toEqual ( 2 ) ;
825
+ } ) ;
826
+ } ) ;
827
+
828
+ it ( 'should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /' , function ( ) {
829
+ inject ( function ( $rootScope , $injector , $browser ) {
830
+ var $browserUrl = spyOnlyCallsWithArgs ( $browser , 'url' ) . andCallThrough ( ) ;
831
+
832
+ $browser . url ( 'http://server/app/' ) ;
833
+ $browser . poll ( ) ;
834
+
835
+ var $location = $injector . get ( '$location' ) ;
836
+ updatePathOnLocationChangeSuccessTo ( '/' ) ;
837
+
838
+ $rootScope . $digest ( ) ;
839
+
840
+ expect ( $browser . url ( ) ) . toEqual ( 'http://server/app/' ) ;
841
+ expect ( $location . path ( ) ) . toEqual ( '/' ) ;
842
+ expect ( $browserUrl . calls . length ) . toEqual ( 1 ) ;
843
+ } ) ;
844
+ } ) ;
845
+ } ) ;
846
+
675
847
} ) ;
676
848
677
849
describe ( 'wiring' , function ( ) {
@@ -1040,6 +1212,49 @@ describe('$location', function() {
1040
1212
}
1041
1213
) ;
1042
1214
} ) ;
1215
+
1216
+
1217
+ function mockUpBrowser ( options ) {
1218
+ module ( function ( $windowProvider , $browserProvider ) {
1219
+ $windowProvider . $get = function ( ) {
1220
+ var win = { } ;
1221
+ angular . extend ( win , window ) ;
1222
+ win . addEventListener = angular . noop ;
1223
+ win . removeEventListener = angular . noop ;
1224
+ win . location = {
1225
+ href : options . initialUrl ,
1226
+ replace : function ( val ) {
1227
+ //win.location.href = val;
1228
+ }
1229
+ } ;
1230
+ return win ;
1231
+ } ;
1232
+ $browserProvider . $get = function ( $document , $window , $log , $sniffer ) {
1233
+ /* global Browser: false */
1234
+ var b = new Browser ( $window , $document , $log , $sniffer ) ;
1235
+ b . baseHref = function ( ) {
1236
+ return options . baseHref ;
1237
+ } ;
1238
+ return b ;
1239
+ } ;
1240
+ } ) ;
1241
+ }
1242
+
1243
+
1244
+ it ( 'should not get caught in infinite digest when replacing empty path with slash' , function ( ) {
1245
+ initService ( { html5Mode :true , supportHistory :false } ) ;
1246
+ mockUpBrowser ( { initialUrl :'http://server/base' , baseHref :'/base/' } ) ;
1247
+ inject (
1248
+ function ( $browser , $location , $rootScope , $window ) {
1249
+ $rootScope . $on ( '$locationChangeSuccess' , function ( ) {
1250
+ if ( $location . path ( ) !== '/' ) {
1251
+ $location . path ( '/' ) . replace ( ) ;
1252
+ }
1253
+ } ) ;
1254
+ $rootScope . $digest ( ) ;
1255
+ }
1256
+ ) ;
1257
+ } ) ;
1043
1258
} ) ;
1044
1259
1045
1260
0 commit comments