@@ -495,6 +495,55 @@ describe('browser', function() {
495495 browser . url ( current ) ;
496496 expect ( fakeWindow . location . href ) . toBe ( 'dontchange' ) ;
497497 } ) ;
498+
499+ it ( 'should not read out location.href if a reload was triggered but still allow to change the url' , function ( ) {
500+ sniffer . history = false ;
501+ browser . url ( 'http://server/someOtherUrlThatCausesReload' ) ;
502+ expect ( fakeWindow . location . href ) . toBe ( 'http://server/someOtherUrlThatCausesReload' ) ;
503+
504+ fakeWindow . location . href = 'http://someNewUrl' ;
505+ expect ( browser . url ( ) ) . toBe ( 'http://server/someOtherUrlThatCausesReload' ) ;
506+
507+ browser . url ( 'http://server/someOtherUrl' ) ;
508+ expect ( browser . url ( ) ) . toBe ( 'http://server/someOtherUrl' ) ;
509+ expect ( fakeWindow . location . href ) . toBe ( 'http://server/someOtherUrl' ) ;
510+ } ) ;
511+
512+ it ( 'assumes that changes to location.hash occur in sync' , function ( ) {
513+ // This is an asynchronous integration test that changes the
514+ // hash in all possible ways and checks
515+ // - whether the change to the hash can be read out in sync
516+ // - whether the change to the hash can be read out in the hashchange event
517+ var realWin = window ,
518+ $realWin = jqLite ( realWin ) ,
519+ hashInHashChangeEvent = [ ] ;
520+
521+ runs ( function ( ) {
522+ $realWin . on ( 'hashchange' , hashListener ) ;
523+
524+ realWin . location . hash = '1' ;
525+ realWin . location . href += '2' ;
526+ realWin . location . replace ( realWin . location . href + '3' ) ;
527+ realWin . location . assign ( realWin . location . href + '4' ) ;
528+
529+ expect ( realWin . location . hash ) . toBe ( '#1234' ) ;
530+ } ) ;
531+ waitsFor ( function ( ) {
532+ return hashInHashChangeEvent . length > 3 ;
533+ } ) ;
534+ runs ( function ( ) {
535+ $realWin . off ( 'hashchange' , hashListener ) ;
536+
537+ forEach ( hashInHashChangeEvent , function ( hash ) {
538+ expect ( hash ) . toBe ( '#1234' ) ;
539+ } ) ;
540+ } ) ;
541+
542+ function hashListener ( ) {
543+ hashInHashChangeEvent . push ( realWin . location . hash ) ;
544+ }
545+ } ) ;
546+
498547 } ) ;
499548
500549 describe ( 'urlChange' , function ( ) {
@@ -573,15 +622,15 @@ describe('browser', function() {
573622 beforeEach ( function ( ) {
574623 sniffer . history = false ;
575624 sniffer . hashchange = false ;
576- browser . url ( "http://server. current" ) ;
625+ browser . url ( "http://server/# current" ) ;
577626 } ) ;
578627
579628 it ( 'should fire callback with the correct URL on location change outside of angular' , function ( ) {
580629 browser . onUrlChange ( callback ) ;
581630
582- fakeWindow . location . href = 'http://server. new' ;
631+ fakeWindow . location . href = 'http://server/# new' ;
583632 fakeWindow . setTimeout . flush ( ) ;
584- expect ( callback ) . toHaveBeenCalledWith ( 'http://server. new' ) ;
633+ expect ( callback ) . toHaveBeenCalledWith ( 'http://server/# new' ) ;
585634
586635 fakeWindow . fire ( 'popstate' ) ;
587636 fakeWindow . fire ( 'hashchange' ) ;
@@ -645,33 +694,134 @@ describe('browser', function() {
645694
646695 describe ( 'integration tests with $location' , function ( ) {
647696
648- beforeEach ( module ( function ( $provide , $locationProvider ) {
649- spyOn ( fakeWindow . history , 'pushState' ) . andCallFake ( function ( stateObj , title , newUrl ) {
650- fakeWindow . location . href = newUrl ;
697+ function setup ( options ) {
698+ module ( function ( $provide , $locationProvider ) {
699+ spyOn ( fakeWindow . history , 'pushState' ) . andCallFake ( function ( stateObj , title , newUrl ) {
700+ fakeWindow . location . href = newUrl ;
701+ } ) ;
702+ spyOn ( fakeWindow . location , 'replace' ) . andCallFake ( function ( newUrl ) {
703+ fakeWindow . location . href = newUrl ;
704+ } ) ;
705+ $provide . value ( '$browser' , browser ) ;
706+ browser . pollFns = [ ] ;
707+
708+ sniffer . history = options . history ;
709+ $provide . value ( '$sniffer' , sniffer ) ;
710+
711+ $locationProvider . html5Mode ( options . html5Mode ) ;
651712 } ) ;
652- $provide . value ( '$browser' , browser ) ;
653- browser . pollFns = [ ] ;
713+ }
654714
655- sniffer . history = true ;
656- $provide . value ( '$sniffer ', sniffer ) ;
715+ describe ( 'update $location when it was changed outside of Angular in sync ' +
716+ 'before $digest was called ', function ( ) {
657717
658- $locationProvider . html5Mode ( true ) ;
659- } ) ) ;
718+ it ( 'should work with no history support, no html5Mode' , function ( ) {
719+ setup ( {
720+ history : false ,
721+ html5Mode : false
722+ } ) ;
723+ inject ( function ( $rootScope , $location ) {
724+ $rootScope . $apply ( function ( ) {
725+ $location . path ( '/initialPath' ) ;
726+ } ) ;
727+ expect ( fakeWindow . location . href ) . toBe ( 'http://server/#/initialPath' ) ;
660728
661- it ( 'should update $location when it was changed outside of Angular in sync ' +
662- 'before $digest was called' , function ( ) {
663- inject ( function ( $rootScope , $location ) {
664- fakeWindow . history . pushState ( null , '' , 'http://server/someTestHash' ) ;
729+ fakeWindow . location . href = 'http://server/#/someTestHash' ;
665730
666- // Verify that infinite digest reported in #6976 no longer occurs
667- expect ( function ( ) {
668731 $rootScope . $digest ( ) ;
669- } ) . not . toThrow ( ) ;
670732
671- expect ( $location . path ( ) ) . toBe ( '/someTestHash' ) ;
733+ expect ( $location . path ( ) ) . toBe ( '/someTestHash' ) ;
734+ } ) ;
672735 } ) ;
736+
737+ it ( 'should work with history support, no html5Mode' , function ( ) {
738+ setup ( {
739+ history : true ,
740+ html5Mode : false
741+ } ) ;
742+ inject ( function ( $rootScope , $location ) {
743+ $rootScope . $apply ( function ( ) {
744+ $location . path ( '/initialPath' ) ;
745+ } ) ;
746+ expect ( fakeWindow . location . href ) . toBe ( 'http://server/#/initialPath' ) ;
747+
748+ fakeWindow . location . href = 'http://server/#/someTestHash' ;
749+
750+ $rootScope . $digest ( ) ;
751+
752+ expect ( $location . path ( ) ) . toBe ( '/someTestHash' ) ;
753+ } ) ;
754+ } ) ;
755+
756+ it ( 'should work with no history support, with html5Mode' , function ( ) {
757+ setup ( {
758+ history : false ,
759+ html5Mode : true
760+ } ) ;
761+ inject ( function ( $rootScope , $location ) {
762+ $rootScope . $apply ( function ( ) {
763+ $location . path ( '/initialPath' ) ;
764+ } ) ;
765+ expect ( fakeWindow . location . href ) . toBe ( 'http://server/#/initialPath' ) ;
766+
767+ fakeWindow . location . href = 'http://server/#/someTestHash' ;
768+
769+ $rootScope . $digest ( ) ;
770+
771+ expect ( $location . path ( ) ) . toBe ( '/someTestHash' ) ;
772+ } ) ;
773+ } ) ;
774+
775+ it ( 'should work with history support, with html5Mode' , function ( ) {
776+ setup ( {
777+ history : true ,
778+ html5Mode : true
779+ } ) ;
780+ inject ( function ( $rootScope , $location ) {
781+ $rootScope . $apply ( function ( ) {
782+ $location . path ( '/initialPath' ) ;
783+ } ) ;
784+ expect ( fakeWindow . location . href ) . toBe ( 'http://server/initialPath' ) ;
785+
786+ fakeWindow . location . href = 'http://server/someTestHash' ;
787+
788+ $rootScope . $digest ( ) ;
789+
790+ expect ( $location . path ( ) ) . toBe ( '/someTestHash' ) ;
791+ } ) ;
792+ } ) ;
793+
673794 } ) ;
674795
796+ it ( 'should not reload the page on every $digest when the page will be reloaded due to url rewrite on load' , function ( ) {
797+ setup ( {
798+ history : false ,
799+ html5Mode : true
800+ } ) ;
801+ fakeWindow . location . href = 'http://server/some/deep/path' ;
802+ var changeUrlCount = 0 ;
803+ var _url = browser . url ;
804+ browser . url = function ( newUrl , replace ) {
805+ if ( newUrl ) {
806+ changeUrlCount ++ ;
807+ }
808+ return _url . call ( this , newUrl , replace ) ;
809+ } ;
810+ spyOn ( browser , 'url' ) . andCallThrough ( ) ;
811+ inject ( function ( $rootScope , $location ) {
812+ $rootScope . $digest ( ) ;
813+ $rootScope . $digest ( ) ;
814+ $rootScope . $digest ( ) ;
815+ $rootScope . $digest ( ) ;
816+
817+ // from $location for rewriting the initial url into a hash url
818+ expect ( browser . url ) . toHaveBeenCalledWith ( 'http://server/#/some/deep/path' , true ) ;
819+ // from the initial call to the watch in $location for watching $location
820+ expect ( browser . url ) . toHaveBeenCalledWith ( 'http://server/#/some/deep/path' , false ) ;
821+ expect ( changeUrlCount ) . toBe ( 2 ) ;
822+ } ) ;
823+
824+ } ) ;
675825 } ) ;
676826
677827 describe ( 'integration test with $rootScope' , function ( ) {
0 commit comments