4

My webapp is using Angular 1.4.8. I have a directive that validates a form input using $validators. Only input that starts with number 5, 6 and 9 and contains 8 numbers are valid.

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);
            };
        }
    };
}

Usage:

<form name="form">
    <input type="text" name="myInput" custom-number>
</form>

Now I want to write a unit test for this directive using Jasmine. This is my test case:

describe('Directive', function() {
    var $scope;

    beforeEach(function() {
        module('directive.customNumber');
        inject(function($rootScope, $compile) {
            $scope = $rootScope;
            var template = '<form name="form"><input type="text" name="myInput" custom-number></form>';
            $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();
    });
});

Running this throws an error "TypeError: Cannot set property 'customNumber' of undefined at this line:

ctrl.$validators.customNumber = function(....

I am not sure why $validators become undefined in the test but works fine in normal environment. Even if I get rid of this error by manually creating $validators object before use, the test fails because the customNumber validator is never being run (know by logging), so form.$valid is always true.

How can I properly test this directive?

4
  • I think that your ctrl is an array where ctrl[0] is the ngModel and ctrl[1] is the formController Commented Jan 28, 2016 at 10:07
  • Or could be because $digest is triggered twice as you are inside the inject function. I believe i already had this problem before. Commented Jan 28, 2016 at 10:24
  • @Raulucco Simply changing all access from ctrl to ctrl[0] works! I have also tested $digest, it seems that it is unrelated to my issue here. You can post the answer and I will accept it. Thanks! Commented Feb 1, 2016 at 5:49
  • Well, I posted it at first but then I was confused because you said that worked on the normal env. I'm glad to help Commented Feb 1, 2016 at 8:28

1 Answer 1

2

On your directive ctrl is an array whare ctrl[0] is the ngModel and ctrl[1] is the formController

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.