@@ -2088,12 +2088,15 @@ describe('$route', function() {
2088
2088
var deferred ;
2089
2089
2090
2090
module ( function ( $provide , $routeProvider ) {
2091
- $routeProvider . when ( '/path' , { template : '' , resolve : {
2092
- a : function ( $q ) {
2093
- deferred = $q . defer ( ) ;
2094
- return deferred . promise ;
2091
+ $routeProvider . when ( '/path' , {
2092
+ template : '' ,
2093
+ resolve : {
2094
+ a : function ( $q ) {
2095
+ deferred = $q . defer ( ) ;
2096
+ return deferred . promise ;
2097
+ }
2095
2098
}
2096
- } } ) ;
2099
+ } ) ;
2097
2100
} ) ;
2098
2101
2099
2102
inject ( function ( $location , $route , $rootScope , $httpBackend , $$testability ) {
@@ -2114,12 +2117,15 @@ describe('$route', function() {
2114
2117
var deferred ;
2115
2118
2116
2119
module ( function ( $provide , $routeProvider ) {
2117
- $routeProvider . when ( '/path' , { template : '' , resolve : {
2118
- a : function ( $q ) {
2119
- deferred = $q . defer ( ) ;
2120
- return deferred . promise ;
2120
+ $routeProvider . when ( '/path' , {
2121
+ template : '' ,
2122
+ resolve : {
2123
+ a : function ( $q ) {
2124
+ deferred = $q . defer ( ) ;
2125
+ return deferred . promise ;
2126
+ }
2121
2127
}
2122
- } } ) ;
2128
+ } ) ;
2123
2129
} ) ;
2124
2130
2125
2131
inject ( function ( $location , $route , $rootScope , $httpBackend , $$testability ) {
@@ -2140,7 +2146,8 @@ describe('$route', function() {
2140
2146
var deferred ;
2141
2147
2142
2148
module ( function ( $provide , $routeProvider ) {
2143
- $routeProvider . when ( '/path' , { template : '' , resolveRedirectTo : function ( $q ) {
2149
+ $routeProvider . when ( '/path' , {
2150
+ resolveRedirectTo : function ( $q ) {
2144
2151
deferred = $q . defer ( ) ;
2145
2152
return deferred . promise ;
2146
2153
}
@@ -2165,7 +2172,8 @@ describe('$route', function() {
2165
2172
var deferred ;
2166
2173
2167
2174
module ( function ( $provide , $routeProvider ) {
2168
- $routeProvider . when ( '/path' , { template : '' , resolveRedirectTo : function ( $q ) {
2175
+ $routeProvider . when ( '/path' , {
2176
+ resolveRedirectTo : function ( $q ) {
2169
2177
deferred = $q . defer ( ) ;
2170
2178
return deferred . promise ;
2171
2179
}
@@ -2187,45 +2195,76 @@ describe('$route', function() {
2187
2195
} ) ;
2188
2196
2189
2197
it ( 'should wait for all route promises before calling callbacks' , function ( ) {
2190
- var redirectDeferred ;
2191
- var localsDeferred ;
2198
+ var deferreds = { } ;
2192
2199
2193
2200
module ( function ( $provide , $routeProvider ) {
2194
- $routeProvider .
2195
- when ( '/foo' , { template : '' , resolveRedirectTo : function ( $q ) {
2196
- redirectDeferred = $q . defer ( ) ;
2197
- return redirectDeferred . promise ;
2198
- } } ) .
2199
- when ( '/bar' , { template : '' , resolve : {
2201
+ // While normally `$browser.defer()` modifies the `outstandingRequestCount`, the mocked
2202
+ // version (provided by `ngMock`) does not. This doesn't matter in most tests, but it does
2203
+ // here:
2204
+ // `$browser.defer()` will be indirectly called as a result of `$locationWatch`'s call to
2205
+ // `$rootScope.$evalAsync()`. In the async function, the `$locationChangeSuccess` event will
2206
+ // be broadcasted, which will in turn trigger `commitRoute()` in `ngRoute`.
2207
+ // `outstandingRequestCount` must not reach 0 during the time between calling
2208
+ // `$rootScope.$evalAsync()` and executing the async function.
2209
+ $provide . decorator ( '$browser' , function ( $delegate ) {
2210
+ var oldDefer = $delegate . defer ;
2211
+ var newDefer = function ( fn , delay ) {
2212
+ var requestCountAwareFn = function ( ) { $delegate . $$completeOutstandingRequest ( fn ) ; } ;
2213
+ $delegate . $$incOutstandingRequestCount ( ) ;
2214
+ return oldDefer . call ( $delegate , requestCountAwareFn , delay ) ;
2215
+ } ;
2216
+
2217
+ $delegate . defer = angular . extend ( newDefer , oldDefer ) ;
2218
+
2219
+ return $delegate ;
2220
+ } ) ;
2221
+
2222
+ addRouteWithAsyncRedirect ( '/foo' , '/bar' ) ;
2223
+ addRouteWithAsyncRedirect ( '/bar' , '/baz' ) ;
2224
+ addRouteWithAsyncRedirect ( '/baz' , '/qux' ) ;
2225
+ $routeProvider . when ( '/qux' , {
2226
+ template : '' ,
2227
+ resolve : {
2200
2228
a : function ( $q ) {
2201
- localsDeferred = $q . defer ( ) ;
2202
- return localsDeferred . promise ;
2229
+ var deferred = deferreds [ '/qux' ] = $q . defer ( ) ;
2230
+ return deferred . promise ;
2231
+ }
2232
+ }
2233
+ } ) ;
2234
+
2235
+ // Helpers
2236
+ function addRouteWithAsyncRedirect ( fromPath , toPath ) {
2237
+ $routeProvider . when ( fromPath , {
2238
+ resolveRedirectTo : function ( $q ) {
2239
+ var deferred = deferreds [ fromPath ] = $q . defer ( ) ;
2240
+ return deferred . promise . then ( function ( ) { return toPath ; } ) ;
2203
2241
}
2204
- } } ) ;
2242
+ } ) ;
2243
+ }
2205
2244
} ) ;
2206
2245
2207
- inject ( function ( $browser , $location , $route , $ rootScope, $httpBackend , $$testability ) {
2246
+ inject ( function ( $browser , $location , $rootScope , $route , $$testability ) {
2208
2247
$location . path ( '/foo' ) ;
2209
2248
$rootScope . $digest ( ) ;
2210
2249
2211
2250
var callback = jasmine . createSpy ( 'callback' ) ;
2212
2251
$$testability . whenStable ( callback ) ;
2213
2252
expect ( callback ) . not . toHaveBeenCalled ( ) ;
2214
2253
2215
- // ngRoute code is wrapped in a $browser.defer call (via $rootScope.evalAsync), which in
2216
- // production would automatically call $$incOutstandingRequestCount and
2217
- // $$completeOutstandingRequest before/after execution. However, ngMock does not call these
2218
- // functions in its $browser.defer implementation, as this logic would make many tests
2219
- // difficult to write. In this one case we need that logic, however, so we call the
2220
- // functions manually.
2221
- $browser . $$incOutstandingRequestCount ( ) ;
2222
- redirectDeferred . resolve ( '/bar' ) ;
2223
- $rootScope . $digest ( ) ;
2224
- $browser . $$completeOutstandingRequest ( ) ;
2254
+ deferreds [ '/foo' ] . resolve ( ) ;
2255
+ $browser . defer . flush ( ) ;
2225
2256
expect ( callback ) . not . toHaveBeenCalled ( ) ;
2226
2257
2227
- localsDeferred . resolve ( ) ;
2228
- $rootScope . $digest ( ) ;
2258
+ deferreds [ '/bar' ] . resolve ( ) ;
2259
+ $browser . defer . flush ( ) ;
2260
+ expect ( callback ) . not . toHaveBeenCalled ( ) ;
2261
+
2262
+ deferreds [ '/baz' ] . resolve ( ) ;
2263
+ $browser . defer . flush ( ) ;
2264
+ expect ( callback ) . not . toHaveBeenCalled ( ) ;
2265
+
2266
+ deferreds [ '/qux' ] . resolve ( ) ;
2267
+ $browser . defer . flush ( ) ;
2229
2268
expect ( callback ) . toHaveBeenCalled ( ) ;
2230
2269
} ) ;
2231
2270
} ) ;
0 commit comments