diff options
| author | Vojta Jina | 2012-01-11 11:15:00 -0800 | 
|---|---|---|
| committer | Vojta Jina | 2012-01-11 22:11:01 -0800 | 
| commit | 28114de8dcf86c69f533b924ce205533bc265786 (patch) | |
| tree | e4b76616205ea0f377f57123521076635506a403 | |
| parent | c6ea1be0536b9d4564f028554fd1762feba58994 (diff) | |
| download | angular.js-28114de8dcf86c69f533b924ce205533bc265786.tar.bz2 | |
refactor(mock.$httpBackend): split (e2e/unit testing version of $httpBackend mock)
| -rw-r--r-- | src/angular-mocks.js | 90 | ||||
| -rw-r--r-- | test/angular-mocksSpec.js | 86 | 
2 files changed, 108 insertions, 68 deletions
diff --git a/src/angular-mocks.js b/src/angular-mocks.js index 9cc0db43..25d7c7e7 100644 --- a/src/angular-mocks.js +++ b/src/angular-mocks.js @@ -3,6 +3,8 @@   * @license AngularJS v"NG_VERSION_FULL"   * (c) 2010-2011 AngularJS http://angularjs.org   * License: MIT + * + * TODO(vojta): wrap whole file into closure during build   */  /** @@ -578,16 +580,34 @@ angular.mock.dump = function(object){   * @ngdoc object   * @name angular.module.ngMock.$httpBackend   * @describe - * Fake HTTP backend used by the $http service during testing. This implementation can be used to - * respond with static or dynamic responses via the `expect` and `when` apis and their shortcuts - * (`expectGET`, `whenPOST`, etc). + * Fake version of `$httpBackend` service used by the `$http` service during unit testing. + * + * This implementation can be used to respond with static or dynamic responses via the `expect` and + * `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).   */ -angular.mock.$httpBackendDecorator = function($delegate, $defer) { +angular.mock.$HttpBackendProvider = function() { +  this.$get = [createHttpBackendMock]; +}; + +/** + * General factory function for $httpBackend mock. + * Returns instance for unit testing (when no arguments specified): + *   - passing through is disabled + *   - auto flushing is disabled + * + * Returns instance for e2e testing (when `$delegate` and `$defer` specified): + *   - passing through (delegating request to real backend) is enabled + *   - auto flushing is enabled + * + * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) + * @param {Object=} $defer Auto-flushing enabled if specified + * @return {Object} Instance of $httpBackend mock + */ +function createHttpBackendMock($delegate, $defer) {    var definitions = [],        expectations = [],        responses = [], -      responsesPush = angular.bind(responses, responses.push), -      autoflush = false; +      responsesPush = angular.bind(responses, responses.push);    function createResponse(status, data, headers) {      if (angular.isFunction(status)) return status; @@ -638,7 +658,8 @@ angular.mock.$httpBackendDecorator = function($delegate, $defer) {      while ((definition = definitions[++i])) {        if (definition.match(method, url, data, headers || {})) {          if (definition.response) { -          (autoflush ? $defer : responsesPush)(function() { +          // if $defer specified, we do auto flush all requests +          ($defer ? $defer : responsesPush)(function() {              var response = definition.response(method, url, data, headers);              xhr.$$respHeaders = response[2];              callback(response[0], response[1], xhr.getAllResponseHeaders()); @@ -656,17 +677,21 @@ angular.mock.$httpBackendDecorator = function($delegate, $defer) {    }    $httpBackend.when = function(method, url, data, headers) { -    var definition = new MockHttpExpectation(method, url, data, headers); -    definitions.push(definition); -    return { -      respond: function(status, data, headers) { -        definition.response = createResponse(status, data, headers); -      }, - -      passThrough: function() { +    var definition = new MockHttpExpectation(method, url, data, headers), +        chain = { +          respond: function(status, data, headers) { +            definition.response = createResponse(status, data, headers); +          } +        }; + +    if ($defer) { +      chain.passThrough = function() {          definition.passThrough = true; -      } -    }; +      }; +    } + +    definitions.push(definition); +    return chain;    };    createShortMethods('when'); @@ -701,15 +726,6 @@ angular.mock.$httpBackendDecorator = function($delegate, $defer) {      $httpBackend.verifyNoOutstandingExpectation();    }; - -  $httpBackend.autoflush = function(val) { -    if (arguments.length) { -      autoflush = !!val; -    } else { -      return autoflush; -    } -  } -    $httpBackend.verifyNoOutstandingExpectation = function() {      if (expectations.length) {        throw Error('Unsatisfied requests: ' + expectations.join(', ')); @@ -836,11 +852,27 @@ function MockXhr() {  angular.module('ngMock', ['ng']).service({    '$browser': angular.mock.$BrowserProvider,    '$exceptionHandler': angular.mock.$ExceptionHandlerProvider, -  '$log': angular.mock.$logProvider -}).init(function($provide) { -  $provide.decorator('$httpBackend', angular.mock.$httpBackendDecorator); +  '$log': angular.mock.$logProvider, +  '$httpBackend': angular.mock.$HttpBackendProvider +}); + + + +/** + * @ngdoc overview + * @name angular.module.ngMockE2E + * @description + * + * The `ngMockE2E` is an angular module which contains mock for `$httpBackend`. This mock allows you + * to either respond with fake data or delegate to real backend. + */ +angular.module('ngMockE2E', ['ng']).init(function($provide) { +  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);  }); +angular.mock.e2e = {}; +angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$defer', createHttpBackendMock]; +  window.jstestdriver && (function(window){ diff --git a/test/angular-mocksSpec.js b/test/angular-mocksSpec.js index 248bb108..fbdd3b91 100644 --- a/test/angular-mocksSpec.js +++ b/test/angular-mocksSpec.js @@ -1,6 +1,6 @@  'use strict'; -describe('mocks', function() { +describe('ngMock', function() {    describe('$browser', function() { @@ -373,19 +373,12 @@ describe('mocks', function() {    describe('$httpBackend', function() { -    var hb, callback, realBackendSpy; - -    beforeEach(inject( -        function($provide) { -          realBackendSpy = jasmine.createSpy('realBackend'); -          $provide.value('$httpBackend', realBackendSpy); -          $provide.decorator('$httpBackend', angular.mock.$httpBackendDecorator) -        }, -        function($httpBackend) { -          callback = jasmine.createSpy('callback'); -          hb = $httpBackend; -        } -    )); +    var hb, callback; + +    beforeEach(inject(function($httpBackend) { +      callback = jasmine.createSpy('callback'); +      hb = $httpBackend; +    }));      it('should respond with first matched definition', function() { @@ -681,31 +674,8 @@ describe('mocks', function() {      }); -    describe('definitions with passThrough delegation', function() { -      it('should delegate requests to the real backend when passThrough is invoked', function() { -        hb.when('GET', /\/passThrough\/.*/).passThrough(); - -        expect(hb('GET', '/passThrough/23', null, callback)); -        expect(realBackendSpy). -            toHaveBeenCalledOnceWith('GET', '/passThrough/23', null, callback, undefined); -      }); -    }); - - -    describe('autoflush', function() { -      it('should flush responses via $defer when autoflush is turned on', inject( -          function($browser) { -        expect(hb.autoflush()).toBe(false); -        hb.autoflush(true); -        expect(hb.autoflush()).toBe(true); - -        hb.when('GET', '/foo').respond('bar'); -        hb('GET', '/foo', null, callback); - -        expect(callback).not.toHaveBeenCalled(); -        $browser.defer.flush(); -        expect(callback).toHaveBeenCalledOnce(); -      })); +    it('should not have passThrough method', function() { +      expect(hb.passThrough).toBeUndefined();      }); @@ -856,3 +826,41 @@ describe('mocks', function() {      });    });  }); + + +describe('ngMockE2E', function() { +  describe('$httpBackend', function() { +    var hb, realHttpBackend, callback; + +    beforeEach(inject(function($provide, $injector) { +      callback = jasmine.createSpy('callback'); +      realHttpBackend = jasmine.createSpy('real $httpBackend'); +      $provide.value('$httpBackend', realHttpBackend); +      $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); +      hb = $injector.get('$httpBackend'); +    })); + + +    describe('passThrough()', function() { +      it('should delegate requests to the real backend when passThrough is invoked', function() { +        hb.when('GET', /\/passThrough\/.*/).passThrough(); +        hb('GET', '/passThrough/23', null, callback); + +        expect(realHttpBackend). +            toHaveBeenCalledOnceWith('GET', '/passThrough/23', null, callback, undefined); +      }); +    }); + + +    describe('autoflush', function() { +      it('should flush responses via $defer', inject(function($browser) { +        hb.when('GET', '/foo').respond('bar'); +        hb('GET', '/foo', null, callback); + +        expect(callback).not.toHaveBeenCalled(); +        $browser.defer.flush(); +        expect(callback).toHaveBeenCalledOnce(); +      })); +    }); +  }); +});  | 
