4

I'm using Jasmine to unit test my Angular App. How can I test form validation in my controller? For example, I have a login function:

$scope.login = function() {
    if($scope.form_login.$valid) {
      //send request with username and password
    };
};

I'm trying to set $valid to true, but I can't access the form here. I got an error TypeError: Cannot set property '$valid' of undefined:

it('should not send request if form validation fails', function() {
    $controller('loginController', {$scope: $scope});
    $scope.form_login.$valid = true;
    $scope.login();
})
WilHall
  • 11,644
  • 6
  • 31
  • 53
vincentf
  • 1,419
  • 2
  • 20
  • 36

2 Answers2

3

Unit test should not really test the form. To test the form and other not controller related things use e2e testing.

However if you really want to test validation in unit test see To test a custom validation angularjs directive or How to unit test angularjs form?

Community
  • 1
  • 1
Alex Ryltsov
  • 2,385
  • 17
  • 25
  • 1
    Correct answer, move as much code logic as possible from view into controller and test controller code with unit tests, use protractor e2e testing for form testing – danday74 Apr 29 '16 at 03:10
  • 1
    @danday74 If use a service to login, I could be testing that service not have been called the method in a unit testing approach, and also, i could be testing in a integration approach using e2e protractor – Gonzalo Pincheira Arancibia Apr 29 '16 at 17:13
1

If you uses a service for save the data

$scope.login = function() {
    if($scope.form_login.$valid) {
      //send request with username and password
      MyService.login();
    };
};

Check if your service have not been called and mock the $scope.form_login.$valid property to false;

var MyService, controllerInjector, rootScope;
beforeEach(inject(function($controller, _MyService_, $rootScope){

  controllerInjector = $controller;
  MyService = _MyService_;
  rootScope = $rootScope;

}))

it('should not send request if form validation fails', function() {
  var scope, controller;
  scope = rootScope.$new();
  scope.form_login = {
    $valid : false;
  }
  var loginController = controllerInjector('loginController', {
    $scope : scope
  });

  spyOn(MyService,'login');

  scope.login();

  expect(MyService.login).not.toHaveBeenCalled();

});