rossoneri rossoneri - 3 months ago 9
AngularJS Question

how to test function in controller scope executed by event

function in controller:

angular.module('myApp').controller('MyController', function(){

$scope.f = function($event){
$event.preventDefault();
//logic
return data;
}
})

describe('MyController', function(){
'use strict';
var MyController,
$scope;

beforeEach(module('myApp'));

beforeEach($inject(function($rootScope, $controller){
$scope = $rootScope.$new();
MyController = $controller('MyController', {
$scope: $scope
})
}));
})
it('should...', function(){
//fire event and expect data
})


$scope.f
function is used in directive, it can be executed by
ng-click="f($event)"


what is right way for fire event in unit test?

Answer

Short Answer

You don't need to fire the event. You have access to the scope, which has the function you want to test. This means you just execute the function, then assert. It will look something like this:

it('should call preventDefault on the given event', function(){
  var testEvent = $.Event('someEvent');
  $scope.f(testEvent);
  expect(testEvent.isDefaultPrevented()).toBe(true);
});

See the following:

Full Spec

Also - your it block should be inside your describe block, so that it has access to the $scope field. It should look more like this:

describe('MyController', function(){
  'use strict';
  var MyController,
      $scope;

  beforeEach(module('myApp'));

  beforeEach($inject(function($rootScope, $controller){
    $scope = $rootScope.$new();
    MyController = $controller('MyController', {
      $scope: $scope
    })
  }));

  it('should call preventDefault on the given event', function(){
    var testEvent = $.Event('someEvent');
    $scope.f(testEvent);
    expect(testEvent.isDefaultPrevented()).toBe(true);
  });
})

A Note About Structure

Don't be afraid to use the describe blocks to structure your tests. Imagine you had another function on the $scope called f2, then you would probably want to partition your spec file up more like this:

describe('MyController', function(){
  'use strict';
  var MyController,
      $scope;

  beforeEach(module('myApp'));

  beforeEach($inject(function($rootScope, $controller){
    $scope = $rootScope.$new();
    MyController = $controller('MyController', {
      $scope: $scope
    })
  }));

  describe('$scope', function() {
    describe('.f()', function() {
      // tests related to only the .f() function
    });

    describe('.f2()', function() {
      // tests related to only the .f2() function
    });
  });
})

This has the benefit that when a test fails, the error message you see is constructed based on the hierarchy of describe blocks. So it would be something like:

MyController $scope .f() should call preventDefault on the given event

Comments