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

feat(ngMock): allow override of when/expect definitions #8352

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 79 additions & 33 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1001,13 +1001,14 @@ angular.mock.dump = function(object) {
```js
// testing controller
describe('MyController', function() {
var $httpBackend, $rootScope, createController;
var $httpBackend, $rootScope, createController, authRequestHandler;

beforeEach(inject(function($injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
// backend definition common for all tests
$httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
authRequestHandler = $httpBackend.when('GET', '/auth.py')
.respond({userId: 'userX'}, {'A-Token': 'xxx'});

// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
Expand All @@ -1033,6 +1034,18 @@ angular.mock.dump = function(object) {
});


it('should fail authentication', function() {

// Notice how you can change the response even after it was set
authRequestHandler.respond(401, '');

$httpBackend.expectGET('/auth.py');
var controller = createController();
$httpBackend.flush();
expect($rootScope.status).toBe('Failed...');
});


it('should send msg to server', function() {
var controller = createController();
$httpBackend.flush();
Expand Down Expand Up @@ -1187,26 +1200,32 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current definition.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*
* - respond –
* `{function([status,] data[, headers, statusText])
* | function(function(method, url, data, headers)}`
* – The respond method takes a set of static data to be returned or a function that can
* return an array containing response status (number), response data (string), response
* headers (Object), and the text for the status (string).
* headers (Object), and the text for the status (string). The respond method returns the
* `requestHandler` object for possible overrides.
*/
$httpBackend.when = function(method, url, data, headers) {
var definition = new MockHttpExpectation(method, url, data, headers),
chain = {
respond: function(status, data, headers, statusText) {
definition.passThrough = undefined;
definition.response = createResponse(status, data, headers, statusText);
return chain;
}
};

if ($browser) {
chain.passThrough = function() {
definition.response = undefined;
definition.passThrough = true;
return chain;
};
}

Expand All @@ -1224,7 +1243,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1237,7 +1257,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1250,7 +1271,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1265,7 +1287,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1280,7 +1303,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1292,7 +1316,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
createShortMethods('when');

Expand All @@ -1312,23 +1337,28 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current expectation.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*
* - respond –
* `{function([status,] data[, headers, statusText])
* | function(function(method, url, data, headers)}`
* – The respond method takes a set of static data to be returned or a function that can
* return an array containing response status (number), response data (string), response
* headers (Object), and the text for the status (string).
* headers (Object), and the text for the status (string). The respond method returns the
* `requestHandler` object for possible overrides.
*/
$httpBackend.expect = function(method, url, data, headers) {
var expectation = new MockHttpExpectation(method, url, data, headers);
var expectation = new MockHttpExpectation(method, url, data, headers),
chain = {
respond: function (status, data, headers, statusText) {
expectation.response = createResponse(status, data, headers, statusText);
return chain;
}
};

expectations.push(expectation);
return {
respond: function (status, data, headers, statusText) {
expectation.response = createResponse(status, data, headers, statusText);
}
};
return chain;
};


Expand All @@ -1342,7 +1372,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* and returns true if the url match the current definition.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled. See #expect for more info.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled. See #expect for more info.
*/

/**
Expand All @@ -1355,7 +1386,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* and returns true if the url match the current definition.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1368,7 +1400,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* and returns true if the url match the current definition.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1384,7 +1417,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1400,7 +1434,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1416,7 +1451,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/

/**
Expand All @@ -1428,7 +1464,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
createShortMethods('expect');

Expand Down Expand Up @@ -1838,7 +1875,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current definition.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*
* - respond –
* `{function([status,] data[, headers, statusText])
Expand All @@ -1849,6 +1887,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* - passThrough – `{function()}` – Any request matching a backend definition with
* `passThrough` handler will be passed through to the real backend (an XHR request will be made
* to the server.)
* - Both methods return the `requestHandler` object for possible overrides.
*/

/**
Expand All @@ -1862,7 +1901,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/

/**
Expand All @@ -1876,7 +1916,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/

/**
Expand All @@ -1890,7 +1931,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/

/**
Expand All @@ -1905,7 +1947,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/

/**
Expand All @@ -1920,7 +1963,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/

/**
Expand All @@ -1935,7 +1979,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/

/**
Expand All @@ -1948,7 +1993,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled.
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*/
angular.mock.e2e = {};
angular.mock.e2e.$httpBackendDecorator =
Expand Down
57 changes: 57 additions & 0 deletions test/ngMock/angular-mocksSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,44 @@ describe('ngMock', function() {
expect(callback.argsForCall[0]).toEqual([200, 'first', '', '']);
expect(callback.argsForCall[1]).toEqual([200, 'second', '', '']);
});

it('should be able to override response of expect definition', function() {
var definition = hb.expect('GET', '/url1');
definition.respond('first');
definition.respond('second');

hb('GET', '/url1', null, callback);
hb.flush();
expect(callback).toHaveBeenCalledOnceWith(200, 'second', '', '');
});

it('should be able to override response of when definition', function() {
var definition = hb.when('GET', '/url1');
definition.respond('first');
definition.respond('second');

hb('GET', '/url1', null, callback);
hb.flush();
expect(callback).toHaveBeenCalledOnceWith(200, 'second', '', '');
});

it('should be able to override response of expect definition with chaining', function() {
var definition = hb.expect('GET', '/url1').respond('first');
definition.respond('second');

hb('GET', '/url1', null, callback);
hb.flush();
expect(callback).toHaveBeenCalledOnceWith(200, 'second', '', '');
});

it('should be able to override response of when definition with chaining', function() {
var definition = hb.when('GET', '/url1').respond('first');
definition.respond('second');

hb('GET', '/url1', null, callback);
hb.flush();
expect(callback).toHaveBeenCalledOnceWith(200, 'second', '', '');
});
});


Expand Down Expand Up @@ -1552,6 +1590,25 @@ describe('ngMockE2E', function() {
expect(realHttpBackend).toHaveBeenCalledOnceWith(
'GET', '/passThrough/23', null, callback, {}, null, true);
});

it('should be able to override a respond definition with passThrough', function() {
var definition = hb.when('GET', /\/passThrough\/.*/).respond('override me');
definition.passThrough();
hb('GET', '/passThrough/23', null, callback, {}, null, true);

expect(realHttpBackend).toHaveBeenCalledOnceWith(
'GET', '/passThrough/23', null, callback, {}, null, true);
});

it('should be able to override a respond definition with passThrough', inject(function($browser) {
var definition = hb.when('GET', /\/passThrough\/.*/).passThrough();
definition.respond('passThrough override');
hb('GET', '/passThrough/23', null, callback, {}, null, true);
$browser.defer.flush();

expect(realHttpBackend).not.toHaveBeenCalled();
expect(callback).toHaveBeenCalledOnceWith(200, 'passThrough override', '', '');
}));
});


Expand Down