Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 773f39c

Browse files
Narretzpetebacondarwin
authored andcommitted
feat(ngMock, ngMockE2E): add option to match latest definition for $httpBackend request
Closes #16251 Closes #11637 Closes #16560
1 parent 7d121ac commit 773f39c

File tree

2 files changed

+118
-3
lines changed

2 files changed

+118
-3
lines changed

src/ngMock/angular-mocks.js

+45-2
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,7 @@ angular.mock.$httpBackendDecorator =
13421342
function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
13431343
var definitions = [],
13441344
expectations = [],
1345+
matchLatestDefinition = false,
13451346
responses = [],
13461347
responsesPush = angular.bind(responses, responses.push),
13471348
copy = angular.copy,
@@ -1430,8 +1431,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
14301431
wasExpected = true;
14311432
}
14321433

1433-
var i = -1, definition;
1434-
while ((definition = definitions[++i])) {
1434+
var i = matchLatestDefinition ? definitions.length : -1, definition;
1435+
1436+
while ((definition = definitions[matchLatestDefinition ? --i : ++i])) {
14351437
if (definition.match(method, url, data, headers || {})) {
14361438
if (definition.response) {
14371439
// if $browser specified, we do auto flush all requests
@@ -1507,6 +1509,47 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
15071509
return chain;
15081510
};
15091511

1512+
/**
1513+
* @ngdoc method
1514+
* @name $httpBackend#matchLatestDefinition
1515+
* @description
1516+
* This method can be used to change which mocked responses `$httpBackend` returns, when defining
1517+
* them with {@link ngMock.$httpBackend#when $httpBackend.when()} (and shortcut methods).
1518+
* By default, `$httpBackend` returns the first definition that matches. When setting
1519+
* `$http.matchLatestDefinition(true)`, it will use the last response that matches, i.e. the
1520+
* one that was added last.
1521+
*
1522+
* ```js
1523+
* hb.when('GET', '/url1').respond(200, 'content', {});
1524+
* hb.when('GET', '/url1').respond(201, 'another', {});
1525+
* hb('GET', '/url1'); // receives "content"
1526+
*
1527+
* $http.matchLatestDefinition(true)
1528+
* hb('GET', '/url1'); // receives "another"
1529+
*
1530+
* hb.when('GET', '/url1').respond(201, 'onemore', {});
1531+
* hb('GET', '/url1'); // receives "onemore"
1532+
* ```
1533+
*
1534+
* This is useful if a you have a default response that is overriden inside specific tests.
1535+
*
1536+
* Note that different from config methods on providers, `matchLatestDefinition()` can be changed
1537+
* even when the application is already running.
1538+
*
1539+
* @param {Boolean=} value value to set, either `true` or `false`. Default is `false`.
1540+
* If omitted, it will return the current value.
1541+
* @return {$httpBackend|Boolean} self when used as a setter, and the current value when used
1542+
* as a getter
1543+
*/
1544+
$httpBackend.matchLatestDefinitionEnabled = function(value) {
1545+
if (isDefined(value)) {
1546+
matchLatestDefinition = value;
1547+
return this;
1548+
} else {
1549+
return matchLatestDefinition;
1550+
}
1551+
};
1552+
15101553
/**
15111554
* @ngdoc method
15121555
* @name $httpBackend#whenGET

test/ngMock/angular-mocksSpec.js

+73-1
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,7 @@ describe('ngMock', function() {
10901090
});
10911091

10921092

1093-
it('should respond with first matched definition', function() {
1093+
it('should respond with first matched definition by default', function() {
10941094
hb.when('GET', '/url1').respond(200, 'content', {});
10951095
hb.when('GET', '/url1').respond(201, 'another', {});
10961096

@@ -1106,6 +1106,78 @@ describe('ngMock', function() {
11061106
});
11071107

11081108

1109+
describe('matchLatestDefinitionEnabled()', function() {
1110+
1111+
it('should be set to false by default', function() {
1112+
expect(hb.matchLatestDefinitionEnabled()).toBe(false);
1113+
});
1114+
1115+
1116+
it('should allow to change the value', function() {
1117+
hb.matchLatestDefinitionEnabled(true);
1118+
expect(hb.matchLatestDefinitionEnabled()).toBe(true);
1119+
});
1120+
1121+
1122+
it('should return the httpBackend when used as a setter', function() {
1123+
expect(hb.matchLatestDefinitionEnabled(true)).toBe(hb);
1124+
});
1125+
1126+
1127+
it('should respond with the first matched definition when false',
1128+
function() {
1129+
hb.matchLatestDefinitionEnabled(false);
1130+
1131+
hb.when('GET', '/url1').respond(200, 'content', {});
1132+
hb.when('GET', '/url1').respond(201, 'another', {});
1133+
1134+
callback.and.callFake(function(status, response) {
1135+
expect(status).toBe(200);
1136+
expect(response).toBe('content');
1137+
});
1138+
1139+
hb('GET', '/url1', null, callback);
1140+
expect(callback).not.toHaveBeenCalled();
1141+
hb.flush();
1142+
expect(callback).toHaveBeenCalledOnce();
1143+
}
1144+
);
1145+
1146+
1147+
it('should respond with latest matched definition when true',
1148+
function() {
1149+
hb.matchLatestDefinitionEnabled(true);
1150+
1151+
hb.when('GET', '/url1').respond(200, 'match1', {});
1152+
hb.when('GET', '/url1').respond(200, 'match2', {});
1153+
hb.when('GET', '/url2').respond(204, 'nomatch', {});
1154+
1155+
callback.and.callFake(function(status, response) {
1156+
expect(status).toBe(200);
1157+
expect(response).toBe('match2');
1158+
});
1159+
1160+
hb('GET', '/url1', null, callback);
1161+
1162+
// Check if a newly added match is used
1163+
hb.when('GET', '/url1').respond(201, 'match3', {});
1164+
1165+
var callback2 = jasmine.createSpy();
1166+
1167+
callback2.and.callFake(function(status, response) {
1168+
expect(status).toBe(201);
1169+
expect(response).toBe('match3');
1170+
});
1171+
1172+
hb('GET', '/url1', null, callback2);
1173+
expect(callback).not.toHaveBeenCalled();
1174+
hb.flush();
1175+
expect(callback).toHaveBeenCalledOnce();
1176+
}
1177+
);
1178+
});
1179+
1180+
11091181
it('should respond with a copy of the mock data', function() {
11101182
var mockObject = {a: 'b'};
11111183

0 commit comments

Comments
 (0)