vendredi 20 novembre 2015

Mocking ng-token-auth for unit testing a controller

I am relatively new to both AngularJS and unit testing.

I am attempting to mock ng-token-auth's $auth.requestResetPassword method, based on what I read in this SitePoint article for mocking methods that return promises http://ift.tt/1MqO0kz and unit testing Angular controllers http://ift.tt/1HkWgzo.

I get the following error regarding Unknown Provider: $q

PhantomJS 1.9.8 (Mac OS X 0.0.0) ForgotPasswordController Initiating forgot password issue a request to the correct API endpoint FAILED
    Error: [$injector:modulerr] Failed to instantiate module function ($provide) due to:
    Error: [$injector:unpr] Unknown provider: $q
    http://ift.tt/1I1vT4t
        at /Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13495
        at getService (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13643)
        at invoke (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13675)
        at instantiate (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13692)
        at provider (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13526)
        at /Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13518
        at /Users/palcisto/Sites/IMS-Admin/src/app/ims/authentication/forgot/forgot.controller.spec.js:25
        at invoke (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13684)
        at /Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13601
        at forEach (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:9547)
        at loadModules (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13622)
        at createInjector (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13505)
        at workFn (/Users/palcisto/Sites/IMS-Admin/bower_components/angular-mocks/angular-mocks.js:2415)
      http://ift.tt/1Xey3PR...
      ...
        at forEach (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:9547)
        at loadModules (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13622)
        at createInjector (/Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13505)
        at workFn (/Users/palcisto/Sites/IMS-Admin/bower_components/angular-mocks/angular-mocks.js:2415)
        at /Users/palcisto/Sites/IMS-Admin/test/assets/js/vendor.js:13620
    TypeError: 'undefined' is not an object (evaluating 'ForgotPasswordController.requestReset')
        at /Users/palcisto/Sites/IMS-Admin/src/app/ims/authentication/forgot/forgot.controller.spec.js:56
PhantomJS 1.9.8 (Mac OS X 0.0.0): Executed 73 of 75 (2 FAILED) (skipped 2) (1.224 secs / 1.647 secs)

Here is my ForgotPassword controller jasmine specs file, which includes my mocked ng-token-auth:

'use strict';

describe('ForgotPasswordController', function() {
  var mockAuth,
    rootScope,
    ForgotPasswordController;

  beforeEach(function() {

    module(function($provide) {
      $provide.provider('$auth', function($q) {
        var requestPasswordReset = jasmine.createSpy('requestPasswordReset').andCallFake(function(forgotObject) {
          var success = {'success':true,'message':'An email has been sent to john@doe.com containing instructions for resetting your password.'};

          if (passPromise) {
            return $q.when(success);
          } else {
            return $q.reject('something went wrong');
          }
        });

        return {
          requestPasswordReset: requestPasswordReset
        };
      });
    });

    module('ims');
  })

  beforeEach(inject(function($controller, $rootScope, $auth){
    mockAuth     = $auth;
    rootScope    = $rootScope;
    ForgotPasswordController = $controller('ForgotPasswordController', {
      $auth: mockAuth
    });
  }));

  describe('Instantiating the controller', function() {
    it('should initialize vm.user<object>', function() {
      expect(ForgotPasswordController.user).toBe(jasmine.any(object));
    });
  });

  describe('Initiating forgot password', function() {
    it('issue a request to the correct API endpoint', function() {
      var received;
      var passPromise = true;
      var message = 'An email has been sent to palcisto@qsfllc.com containing instructions for resetting your password.';
      var user = {
        subdomain: 'investments',
        email: 'palcisto@qsfllc.com',
        ims_admin: true
      }

      ForgotPasswordController.requestReset(user).then(function(data) {
        recieved = data.message;
      });
      rootScope.$digest();

      expect(mockAuth.requestPasswordReset).toHaveBeenCalled();
      expect(message).toEqual(message);
    });
  });
});

Here is my controller file:

(function() {
  'use strict';

  angular
    .module('ims.authentication.forgot.controllers', [])
    .controller('ForgotPasswordController', ForgotPasswordController);

  /* @ngInject */
  function ForgotPasswordController($q, $state, $log, $mdToast, $auth) {
    var vm = this;
    vm.user = {
      subdomain: '',
      email: '',
      ims_admin: true
    };
    vm.requestReset = requestReset;

    ////////////////
    function requestReset(forgotObj) {
      var deferred = $q.defer();

      $auth.requestPasswordReset(forgotObj)
        .then(function(resp) {
          $mdToast.show(
            $mdToast.simple()
            .content(resp.data.message)
            .position('top right')
            .action('Login')
            .highlightAction(true)
            .hideDelay(0)
          ).then(function() {
            $state.go('authentication.login');
          });
          deferred.resolve(resp);
        })
        .catch(function(resp) {
          $mdToast.show(
            $mdToast.simple()
            .content(resp.data.errors[0])
            .position('top right')
            .hideDelay(5000)
          );
          $log.error('Error', resp);
          deferred.reject(resp);
        });

      return deferred.promise;
    }
  }
})();

What am I doing wrong? I've searched and haven't come up with much around mocking ng-token-auth. Please let me know if any more info is needed to properly answer this question.

Aucun commentaire:

Enregistrer un commentaire