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

Commit

Permalink
feat(ngMock, ngMockE2E): add option to match latest definition for $h…
Browse files Browse the repository at this point in the history
…ttpBackend request

Closes #16251
Closes #11637
Closes #16560
  • Loading branch information
Narretz authored and petebacondarwin committed May 21, 2018
1 parent 7d121ac commit 773f39c
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 3 deletions.
47 changes: 45 additions & 2 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,7 @@ angular.mock.$httpBackendDecorator =
function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
var definitions = [],
expectations = [],
matchLatestDefinition = false,
responses = [],
responsesPush = angular.bind(responses, responses.push),
copy = angular.copy,
Expand Down Expand Up @@ -1430,8 +1431,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
wasExpected = true;
}

var i = -1, definition;
while ((definition = definitions[++i])) {
var i = matchLatestDefinition ? definitions.length : -1, definition;

while ((definition = definitions[matchLatestDefinition ? --i : ++i])) {
if (definition.match(method, url, data, headers || {})) {
if (definition.response) {
// if $browser specified, we do auto flush all requests
Expand Down Expand Up @@ -1507,6 +1509,47 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
return chain;
};

/**
* @ngdoc method
* @name $httpBackend#matchLatestDefinition
* @description
* This method can be used to change which mocked responses `$httpBackend` returns, when defining
* them with {@link ngMock.$httpBackend#when $httpBackend.when()} (and shortcut methods).
* By default, `$httpBackend` returns the first definition that matches. When setting
* `$http.matchLatestDefinition(true)`, it will use the last response that matches, i.e. the
* one that was added last.
*
* ```js
* hb.when('GET', '/url1').respond(200, 'content', {});
* hb.when('GET', '/url1').respond(201, 'another', {});
* hb('GET', '/url1'); // receives "content"
*
* $http.matchLatestDefinition(true)
* hb('GET', '/url1'); // receives "another"
*
* hb.when('GET', '/url1').respond(201, 'onemore', {});
* hb('GET', '/url1'); // receives "onemore"
* ```
*
* This is useful if a you have a default response that is overriden inside specific tests.
*
* Note that different from config methods on providers, `matchLatestDefinition()` can be changed
* even when the application is already running.
*
* @param {Boolean=} value value to set, either `true` or `false`. Default is `false`.
* If omitted, it will return the current value.
* @return {$httpBackend|Boolean} self when used as a setter, and the current value when used
* as a getter
*/
$httpBackend.matchLatestDefinitionEnabled = function(value) {
if (isDefined(value)) {
matchLatestDefinition = value;
return this;
} else {
return matchLatestDefinition;
}
};

/**
* @ngdoc method
* @name $httpBackend#whenGET
Expand Down
74 changes: 73 additions & 1 deletion test/ngMock/angular-mocksSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ describe('ngMock', function() {
});


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

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


describe('matchLatestDefinitionEnabled()', function() {

it('should be set to false by default', function() {
expect(hb.matchLatestDefinitionEnabled()).toBe(false);
});


it('should allow to change the value', function() {
hb.matchLatestDefinitionEnabled(true);
expect(hb.matchLatestDefinitionEnabled()).toBe(true);
});


it('should return the httpBackend when used as a setter', function() {
expect(hb.matchLatestDefinitionEnabled(true)).toBe(hb);
});


it('should respond with the first matched definition when false',
function() {
hb.matchLatestDefinitionEnabled(false);

hb.when('GET', '/url1').respond(200, 'content', {});
hb.when('GET', '/url1').respond(201, 'another', {});

callback.and.callFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('content');
});

hb('GET', '/url1', null, callback);
expect(callback).not.toHaveBeenCalled();
hb.flush();
expect(callback).toHaveBeenCalledOnce();
}
);


it('should respond with latest matched definition when true',
function() {
hb.matchLatestDefinitionEnabled(true);

hb.when('GET', '/url1').respond(200, 'match1', {});
hb.when('GET', '/url1').respond(200, 'match2', {});
hb.when('GET', '/url2').respond(204, 'nomatch', {});

callback.and.callFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('match2');
});

hb('GET', '/url1', null, callback);

// Check if a newly added match is used
hb.when('GET', '/url1').respond(201, 'match3', {});

var callback2 = jasmine.createSpy();

callback2.and.callFake(function(status, response) {
expect(status).toBe(201);
expect(response).toBe('match3');
});

hb('GET', '/url1', null, callback2);
expect(callback).not.toHaveBeenCalled();
hb.flush();
expect(callback).toHaveBeenCalledOnce();
}
);
});


it('should respond with a copy of the mock data', function() {
var mockObject = {a: 'b'};

Expand Down

0 comments on commit 773f39c

Please sign in to comment.