Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 362
Chicheng Deng Avatar asked Jul 07 '15 08:07

Chicheng Deng


1 Answers

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>
like image 151
Krzysztof Safjanowski Avatar answered Oct 24 '22 02:10

Krzysztof Safjanowski