Chicheng Deng Chicheng Deng - 4 months ago 13
AngularJS Question

how to test 'ng-click' event in directive with jasmine

I want to test the 'ng-click' event in angular with jasmine,But I don't know how

My directive file is like this (headbarDirective.js):

(function () {
angular.module('app.widgets.homeHeadbar',[])
.directive('homeHeadbar', homeHeadbar);

function homeHeadbar() {
return {
restrict: 'EAC',
replace: true,
transclude: false,
scope: {
name: '@',
role: '@',
},
templateUrl: 'app/widgets/headbar/headbarView.html',
link: function(scope, ele, attrs) {
if (!scope.name) {
scope.logined = false;
} else {
scope.logined = true;
}
scope.logout = function() {
UserService.logout();
$location.path('/login');
};
}
};
}
})();


my template file like this (headbarView.html):

<nav>
<div>
<div class="navbar-right" ng-show="logined">

<div class="dib fr ml20">
<div class="user-name cwh">{{name}}</div>
<div class="user-position cgray">{{role}}</div>
</div>

<a class="logout" href="javascript:;" ng-click="logout()">Log Out</a>

</div>
</div>
</nav>


and my test file is like this(test.js):

describe('test the headbarDirective',function(){

beforeEach(module('templates','app','app.widgets.homeHeadbar'));

var scope,ele,compile,simpleHtml,UserService,location;

beforeEach(inject(function(_$rootScope_,_$compile_,_UserService_,_$location_){
compile = _$compile_;
scope = _$rootScope_.$new();
location = _$location_;
UserService = _UserService_;
}));

it('test the logout click',function(){
simpleHtml = '<home-headbar name="John" role=2></home-headbar>';
ele = compile(angular.element(simpleHtml))(scope);
scope.$digest();

spyOn(UserService,'logout').and.callThrough();

$(ele).find('.logout').click();
scope.$digest();

expect(UserService.logout).toHaveBeenCalled();
});
});


and the test failed, console result like this :

Chrome 43.0.2357 (Windows 7 0.0.0) test the headbarDirective test the logout cli
ck FAILED
Expected spy logout to have been called.
at Object.<anonymous> (C:/Users/IBM_ADMIN/desk/workspace/WaterFundWe
b/WebContent/test/unit/widgets/headbar/headbarDirective.js:48:30)
Chrome 43.0.2357 (Windows 7 0.0.0): Executed 11 of 11 (1 FAILED) (0 secs / 0.124
Chrome 43.0.2357 (Windows 7 0.0.0): Executed 11 of 11 (1 FAILED) (0.125 secs / 0
.124 secs)


means that the logout function hasn't been called.
is there something wrong with my code ?how could I test the ng-click event?

Answer

Let me test if for you, please feel free to "run code snippet"

angular.module('app.widgets.homeHeadbar', [])
  .directive('homeHeadbar', function homeHeadbar($location, UserService) {
    return {
      restrict: 'EAC',
      replace: true,
      transclude: false,
      scope: {
        name: '@',
        role: '@',
      },
      templateUrl: 'app/widgets/headbar/headbarView.html',
      link: function(scope, ele, attrs) {
        scope.logout = function() {
          UserService.logout();
          $location.path('/login');
        };
      }
    };
  });

describe('test the headbarDirective', function() {

  var scope, el, $compile, $location, simpleHtml, UserService;

  beforeEach(module('app.widgets.homeHeadbar'));

  /* stub as I don't know implementations for UserService */
  beforeEach(function() {
    var _stubUserService_ = {
      logout: jasmine.createSpy('UserService.logout')
    };

    angular.module('app.widgets.homeHeadbar')
      .value('UserService', _stubUserService_);
  });

  beforeEach(inject(function($rootScope, $templateCache, _$compile_, _$location_, _UserService_) {
    $templateCache.put('app/widgets/headbar/headbarView.html', [
      '<nav>',
      '  <div>',
      '    <div class="navbar-right" ng-show="logined">',
      '      <div class="dib fr ml20">',
      '        <div class="user-name cwh">{{name}}</div>',
      '        <div class="user-position cgray">{{role}}</div>',
      '      </div>',
      '      <a class="logout" href="javascript:;" ng-click="logout()">Log Out</a>',
      '    </div>',
      '  </div>',
      '</nav>'
    ].join(''));
    $location = _$location_;
    $compile = _$compile_;
    scope = $rootScope.$new();
    UserService = _UserService_;
  }));

  it('clicks on "logout" redirects to /login page', function() {
    spyOn($location, 'path')

    simpleHtml = '<home-headbar name="John" role=2></home-headbar>';
    el = $compile(angular.element(simpleHtml))(scope);
    scope.$digest();

    el.find('.logout').click();

    expect(UserService.logout).toHaveBeenCalled();
    expect($location.path).toHaveBeenCalledWith('/login');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>