title: Unit Test Angular Form Validation With $validators
body: <p>My webapp is using <strong>Angular 1.4.8</strong>. I have a directive that validates a form input using <strong>$validators</strong>. Only input that starts with number 5, 6 and 9 and contains 8 numbers are valid.</p>
  
  <pre><code>angular
      .module('directive.customNumber', [])
      .directive('customNumber', customNumber);
  
  function customNumber() {
      var REGEXP = /^([569][0-9]{7})/;
  
      return {
          require: ['ngModel', '^form'],
          link: function(scope, elm, attrs, ctrl) {
              ctrl.$validators.customNumber = function(modelValue, viewValue) {
                  if(ctrl.$isEmpty(modelValue)) {
                      // consider empty models to be valid
                      return true;
                  }
                  return REGEXP.test(viewValue);
              };
          }
      };
  }
  </code></pre>
  
  <p>Usage:</p>
  
  <pre><code>&lt;form name="form"&gt;
      &lt;input type="text" name="myInput" custom-number&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>Now I want to write a unit test for this directive using <strong>Jasmine</strong>. This is my test case:</p>
  
  <pre><code>describe('Directive', function() {
      var $scope;
  
      beforeEach(function() {
          module('directive.customNumber');
          inject(function($rootScope, $compile) {
              $scope = $rootScope;
              var template = '&lt;form name="form"&gt;&lt;input type="text" name="myInput" custom-number&gt;&lt;/form&gt;';
              $compile(template)($scope);
              $scope.digest();
          });
      });
  
      it('should not accept invalid input', function() {
          var form = $scope.form;
          form.myInput.$setViewValue('abc');
  
          expect(form.$valid).toBeFalsy();
          expect(form.myInput.$error.mobile).toBeDefined();
      });
  });
  </code></pre>
  
  <p>Running this throws an error <code>"TypeError: Cannot set property 'customNumber' of undefined</code> at this line:</p>
  
  <pre><code>ctrl.$validators.customNumber = function(....
  </code></pre>
  
  <p>I am not sure why <code>$validators</code> become undefined in the test but works fine in normal environment. Even if I get rid of this error by manually creating <code>$validators</code> object before use, the test fails because the <code>customNumber</code> validator is never being run (know by logging), so <code>form.$valid</code> is always true.</p>
  
  <p><strong>How can I properly test this directive?</strong></p>