diff options
Diffstat (limited to 'src/angular-mocks.js')
| -rw-r--r-- | src/angular-mocks.js | 167 |
1 files changed, 165 insertions, 2 deletions
diff --git a/src/angular-mocks.js b/src/angular-mocks.js index 73bc4cbd..bc0578f5 100644 --- a/src/angular-mocks.js +++ b/src/angular-mocks.js @@ -21,6 +21,7 @@ angular.module.ngMock = function($provide){ $provide.service('$browser', angular.module.ngMock.$BrowserProvider); $provide.service('$exceptionHandler', angular.module.ngMock.$ExceptionHandlerProvider); $provide.service('$log', angular.module.ngMock.$LogProvider); + $provide.service('$httpBackend', angular.module.ngMock.$HttpBackendProvider); }; angular.module.ngMock.$inject = ['$provide']; @@ -38,8 +39,6 @@ angular.module.ngMock.$inject = ['$provide']; * * The following apis can be used in tests: * - * - {@link #xhr} — enables testing of code that uses - * the {@link angular.module.ng.$xhr $xhr service} to make XmlHttpRequests. * - $browser.defer — enables testing of code that uses * {@link angular.module.ng.$defer $defer} for executing functions via the `setTimeout` api. */ @@ -720,6 +719,170 @@ angular.module.ngMock.dump = function(object){ } }; +/** + * @ngdoc object + * @name angular.module.ngMock.$httpBackend + */ +angular.module.ngMock.$HttpBackendProvider = function() { + this.$get = function() { + var definitions = [], + expectations = [], + responses = []; + + function createResponse(status, data, headers) { + return angular.isNumber(status) ? [status, data, headers] : [200, status, data]; + } + + // TODO(vojta): change params to: method, url, data, headers, callback + function $httpBackend(method, url, data, callback, headers) { + var xhr = new MockXhr(), + expectation = expectations[0], + wasExpected = false; + + if (expectation && expectation.match(method, url)) { + if (!expectation.matchData(data)) + throw Error('Expected ' + method + ' ' + url + ' with different data'); + + if (!expectation.matchHeaders(headers)) + throw Error('Expected ' + method + ' ' + url + ' with different headers'); + + expectations.shift(); + + if (expectation.response) { + responses.push(function() { + xhr.$$headers = expectation.response[2]; + callback(expectation.response[0], expectation.response[1]); + }); + return method == 'JSONP' ? undefined : xhr; + } + wasExpected = true; + } + + var i = -1, definition; + while ((definition = definitions[++i])) { + if (definition.match(method, url, data, headers || {})) { + if (!definition.response) throw Error('No response defined !'); + responses.push(function() { + var response = angular.isFunction(definition.response) ? + definition.response(method, url, data, headers) : definition.response; + xhr.$$headers = response[2]; + callback(response[0], response[1]); + }); + return method == 'JSONP' ? undefined : xhr; + } + } + throw wasExpected ? Error('No response defined !') : + Error('Unexpected request: ' + method + ' ' + url); + } + + $httpBackend.when = function(method, url, data, headers) { + var definition = new MockHttpExpectation(method, url, data, headers); + definitions.push(definition); + return { + then: function(status, data, headers) { + definition.response = angular.isFunction(status) ? status : createResponse(status, data, headers); + } + }; + }; + + $httpBackend.expect = function(method, url, data, headers) { + var expectation = new MockHttpExpectation(method, url, data, headers); + expectations.push(expectation); + return { + respond: function(status, data, headers) { + expectation.response = createResponse(status, data, headers); + } + }; + }; + + $httpBackend.flush = function(count) { + count = count || responses.length; + while (count--) { + if (!responses.length) throw Error('No more pending requests'); + responses.shift()(); + } + }; + + + + $httpBackend.verifyExpectations = function() { + if (expectations.length) { + throw Error('Unsatisfied requests: ' + expectations.join(', ')); + } + }; + + $httpBackend.resetExpectations = function() { + expectations = []; + responses = []; + }; + + return $httpBackend; + }; +}; + +function MockHttpExpectation(method, url, data, headers) { + + this.match = function(m, u, d, h) { + if (method != m) return false; + if (!this.matchUrl(u)) return false; + if (angular.isDefined(d) && !this.matchData(d)) return false; + if (angular.isDefined(h) && !this.matchHeaders(h)) return false; + return true; + }; + + this.matchUrl = function(u) { + if (!url) return true; + if (angular.isFunction(url.test)) { + if (!url.test(u)) return false; + } else if (url != u) return false; + + return true; + }; + + this.matchHeaders = function(h) { + if (angular.isUndefined(headers)) return true; + if (angular.isFunction(headers)) { + if (!headers(h)) return false; + } else if (!angular.equals(headers, h)) return false; + + return true; + }; + + this.matchData = function(d) { + if (angular.isUndefined(data)) return true; + if (data && angular.isFunction(data.test)) { + if (!data.test(d)) return false; + } else if (data != d) return false; + + return true; + }; + + this.toString = function() { + return method + ' ' + url; + }; +} + +function MockXhr() { + + // hack for testing $http + MockXhr.$$lastInstance = this; + + this.getResponseHeader = function(name) { + return this.$$headers[name]; + }; + + this.getAllResponseHeaders = function() { + var lines = []; + + angular.forEach(this.$$headers, function(value, key) { + lines.push(key + ': ' + value); + }); + return lines.join('\n'); + }; + + this.abort = noop; +} + window.jstestdriver && (function(window){ /** * Global method to output any number of objects into JSTD console. Useful for debugging. |
