0
votes

I followed this post (http://gonehybrid.com/how-to-write-automated-tests-for-your-ionic-app-part-2/) to create a simple unit test using Karma & Jasmine for a Ionic controller, but i keep getting undefined errors while the stated objects have been defined. I'm i missing something obvious? By the way, i'm able to run referenced tests from the blog above successfully which makes me think i'm missing something in mine.

Errora are as follows:

  1. TypeError: undefined is not an object (evaluating 'authMock.login') in /Users/projects/app/tests/unit-tests/login.controller.tests.js (line 65)
  2. TypeError: undefined is not an object (evaluating 'deferredLogin.resolve') in /Users/projects/app/tests/unit-tests/login.controller.tests.js (line 71)
  3. TypeError: undefined is not an object (evaluating 'deferredLogin.reject') in /Users/projects/app/tests/unit-tests/login.controller.tests.js (line 79)

Here's the controller:

    angular.module('app').controller('LoginCtrl', function($scope, $state, $ionicPopup, $auth) {
  $scope.loginData = {};
  $scope.user = {
      email: '',
      password: ''
    };

    $scope.doLogin = function(data) {
      $auth.login(data).then(function(authenticated) {
        $state.go('app.tabs.customer', {}, {reload: true});
      }, function(err) {
        var alertPopup = $ionicPopup.alert({
          title: 'Login failed!',
          template: 'Please check your credentials!'
        });
      });
    };

});

Here's the test:

    describe('LoginCtrl', function() {

    var controller,
        deferredLogin,
        $scope,
        authMock,
        stateMock,
        ionicPopupMock;

    // load the module for our app
    beforeEach(angular.mock.module('app'));

    // disable template caching
    beforeEach(angular.mock.module(function($provide, $urlRouterProvider) {
        $provide.value('$ionicTemplateCache', function(){} );
        $urlRouterProvider.deferIntercept();
    }));

    // instantiate the controller and mocks for every test
    beforeEach(angular.mock.inject(function($controller, $q, $rootScope) {
        deferredLogin = $q.defer();

    $scope = $rootScope.$new();

        // mock dinnerService
        authMock = {
            login: jasmine.createSpy('login spy')
                          .and.returnValue(deferredLogin.promise)
        };

        // mock $state
        stateMock = jasmine.createSpyObj('$state spy', ['go']);

        // mock $ionicPopup
        ionicPopupMock = jasmine.createSpyObj('$ionicPopup spy', ['alert']);

        // instantiate LoginController
        controller = $controller('LoginCtrl', {
            '$scope': $scope,
            '$state': stateMock,
            '$ionicPopup': ionicPopupMock,
                        '$auth': authMock
          });

    }));

    describe('#doLogin', function() {

        // call doLogin on the controller for every test
        beforeEach(inject(function(_$rootScope_) {

            $rootScope = _$rootScope_;

            var user = {
                email: '[email protected]',
                password: 'test'
            };

            $scope.doLogin(user);

        }));

        it('should call login on $auth Service', function() {

            expect(authMock.login).toHaveBeenCalledWith(user);
        });

        describe('when the login is executed,', function() {
            it('if successful, should change state to app.tabs.customer', function() {

                deferredLogin.resolve();
                $rootScope.$digest();

                expect(stateMock.go).toHaveBeenCalledWith('app.tabs.customer');
            });

            it('if unsuccessful, should show a popup', function() {

                deferredLogin.reject();
                $rootScope.$digest();

                expect(ionicPopupMock.alert).toHaveBeenCalled();
            });
        });
    })
});

Here's my Karma config:

    files: [
  '../www/lib/ionic/js/ionic.bundle.js',
  '../www/lib/angular-mocks/angular-mocks.js',
  '../www/js/*.js',
  '../www/js/**/*.js',
  'unit-tests/**/*.js'
],
1
Surprised there is no answer on this. Any testing guru's out there?user3096491

1 Answers

1
votes

I think that your controller for tests is undefined. Try to replace first it function with this and check if is it defined.

it('controller to be defained', function() {
            expect($controller).toBeDefined();
});

If it isn't, try to call controller with:

$controller = _$controller_;