Skip to content

Commit 01a91d8

Browse files
wbyokogkalpak
authored andcommitted
fix($http): properly increment/decrement $browser.outstandingRequestCount
Calling `$http` will not increment `$browser.outstandingRequestCount` until after all (potentially) asynchronous request interceptors have been processed and will decrement it before any (potentially) asynchronous response interceptors have been processed. This can lead to `$browser.notifyWhenNoOutstandingRequests` firing prematurely, which can be problematic in end-to-end tests. This commit fixes this, by synchronizing the increment/decrement operations with `$http`'s internal interceptor promise chain. Fixes angular#13782 Closes angular#13862
1 parent 267ee9c commit 01a91d8

File tree

6 files changed

+93
-5
lines changed

6 files changed

+93
-5
lines changed

src/ng/http.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ function $HttpProvider() {
374374
**/
375375
var interceptorFactories = this.interceptors = [];
376376

377-
this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
378-
function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
377+
this.$get = ['$browser', '$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
378+
function($browser, $httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
379379

380380
var defaultCache = $cacheFactory('$http');
381381

@@ -981,7 +981,7 @@ function $HttpProvider() {
981981
};
982982

983983
var chain = [serverRequest, undefined];
984-
var promise = $q.when(config);
984+
var promise = initiateOutstandingRequest(config);
985985

986986
// apply interceptors
987987
forEach(reversedInterceptors, function(interceptor) {
@@ -1000,6 +1000,8 @@ function $HttpProvider() {
10001000
promise = promise.then(thenFn, rejectFn);
10011001
}
10021002

1003+
promise.finally(completeOutstandingRequest);
1004+
10031005
if (useLegacyPromise) {
10041006
promise.success = function(fn) {
10051007
assertArgFn(fn, 'fn');
@@ -1025,6 +1027,15 @@ function $HttpProvider() {
10251027

10261028
return promise;
10271029

1030+
function initiateOutstandingRequest(config) {
1031+
$browser.$$incOutstandingRequestCount();
1032+
return $q.when(config);
1033+
}
1034+
1035+
function completeOutstandingRequest() {
1036+
$browser.$$completeOutstandingRequest(noop);
1037+
}
1038+
10281039
function transformResponse(response) {
10291040
// make a copy since the response must be cacheable
10301041
var resp = extend({}, response);

src/ng/httpBackend.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ function $HttpBackendProvider() {
5555
function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
5656
// TODO(vojta): fix the signature
5757
return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) {
58-
$browser.$$incOutstandingRequestCount();
5958
url = url || $browser.url();
6059

6160
if (lowercase(method) === 'jsonp') {
@@ -162,7 +161,6 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
162161
jsonpDone = xhr = null;
163162

164163
callback(status, response, headersString, statusText);
165-
$browser.$$completeOutstandingRequest(noop);
166164
}
167165
};
168166

test/e2e/fixtures/http/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html ng-app="test">
3+
<body>
4+
<div ng-controller="TestController">
5+
<p>{{text}}</p>
6+
</div>
7+
8+
<script src="angular.js"></script>
9+
<script src="script.js"></script>
10+
</body>
11+
</html>

test/e2e/fixtures/http/script.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
angular.
2+
module('test', []).
3+
config(function($httpProvider) {
4+
$httpProvider.interceptors.push(function($q) {
5+
return {
6+
request: function(config) {
7+
return $q(function(resolve) {
8+
setTimeout(resolve, 100, config);
9+
});
10+
},
11+
response: function(response) {
12+
return $q(function(resolve) {
13+
setTimeout(resolve, 100, response);
14+
});
15+
}
16+
};
17+
});
18+
}).
19+
controller('TestController', function($cacheFactory, $http, $scope) {
20+
var url = '/some/url';
21+
22+
var cache = $cacheFactory('test');
23+
cache.put(url, 'Hello, world!');
24+
25+
$http.
26+
get(url, {cache: cache}).
27+
then(function(response) { $scope.text = response.data; });
28+
});

test/e2e/tests/httpSpec.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
describe('$http', function() {
2+
beforeEach(function() {
3+
loadFixture('http');
4+
});
5+
6+
it('should correctly update the outstanding request count', function() {
7+
expect(element(by.binding('text')).getText()).toBe('Hello, world!');
8+
});
9+
});

test/ng/httpSpec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,37 @@ describe('$http', function() {
18961896
expect(paramSerializer({foo: 'foo', bar: ['bar', 'baz']})).toEqual('bar=bar&bar=baz&foo=foo');
18971897
});
18981898
});
1899+
1900+
describe('$browser\'s outstandingRequestCount', function() {
1901+
var incOutstandingRequestCountSpy, completeOutstandingRequestSpy;
1902+
1903+
beforeEach(inject(function($browser) {
1904+
incOutstandingRequestCountSpy
1905+
= spyOn($browser, '$$incOutstandingRequestCount').andCallThrough();
1906+
completeOutstandingRequestSpy
1907+
= spyOn($browser, '$$completeOutstandingRequest').andCallThrough();
1908+
}));
1909+
1910+
it('should update $browser outstandingRequestCount on success', function() {
1911+
$httpBackend.when('GET').respond(200);
1912+
1913+
expect(incOutstandingRequestCountSpy).not.toHaveBeenCalled();
1914+
$http.get('');
1915+
expect(incOutstandingRequestCountSpy).toHaveBeenCalledOnce();
1916+
$httpBackend.flush();
1917+
expect(completeOutstandingRequestSpy).toHaveBeenCalledOnce();
1918+
});
1919+
1920+
it('should update $browser outstandingRequestCount on error', function() {
1921+
$httpBackend.when('GET').respond(500);
1922+
1923+
expect(incOutstandingRequestCountSpy).not.toHaveBeenCalled();
1924+
$http.get('');
1925+
expect(incOutstandingRequestCountSpy).toHaveBeenCalledOnce();
1926+
$httpBackend.flush();
1927+
expect(completeOutstandingRequestSpy).toHaveBeenCalledOnce();
1928+
});
1929+
});
18991930
});
19001931

19011932

0 commit comments

Comments
 (0)