1

I built a new directive in Angular (1.2.29) and I am trying to test it using karma, however I am having some problems when checking if the field is invalid, it seems it's always valid.

Here is my directive:

var EmailOrUrlValidation = function emailOrUrlValidation() {

        console.log("on directive 0");

        return {
            require: 'ngModel',
            restrict: 'A',
            scope: {
                checkDirty: '=validationCheckDirty'
            },
            link: function (scope, element, attrs, ctrl) {

                console.log("on directive 1");

                scope.$watch(function () {
                    scope.checkDirty = scope.checkDirty ? true : false;
                    element.attr('maxlength', 50);
                    ctrl.$parsers.unshift(validateEmailOrUrl);
                    ctrl.$formatters.unshift(validateEmailOrUrl);
                });

                function validateEmailOrUrl(value) {
                    console.log("on directive 2");
                    var urlRegexp = "myurlregex";
                    var emailPattern = "myemailregex";

                    if (!value) { 
                        ctrl.$setValidity("valid", true);

                    } else if (scope.checkDirty && !ctrl.$dirty) { 
                        ctrl.$setValidity("valid", true);

                    } else { 
                        var emailRegex = new RegExp(emailPattern);

                        var emailOrUrlValid = urlRegexp.test(value) || emailRegex.test(value);
                        ctrl.$setValidity("valid", emailOrUrlValid);
                    }
                    return value;
                }
            }
        };
    };

 this.app = angular.module('shared.validations', [])
                     .directive('emailOrUrlValidation', [emailOrUrlValidation])

Here is my unit testing (I followed this example https://stackoverflow.com/a/22772504/1031021):

describe('EmailOrUrlValidation tests', function () {
    var $scope, form, element;
    beforeEach(module("shared.validations"));
    beforeEach(inject(function ($compile, $rootScope) {
        $scope = $rootScope;
        element = angular.element(
            '<form name="form">' +
                '<input data-ng-model="model.emailorurl" name="emailorurl" email-or-url-validation data-ng-required="true" validation-check-dirty="true" />' +
            '</form>'
        );
        $scope.model = { emailorurl: null }
        $compile(element)($scope);
        form = $scope.form;
    }));
    describe('invalid url', function () {
        it('should pass with valid url', function () {

            form.emailorurl.$setViewValue('www.google.pt');
            $scope.$digest();

            expect(form.emailorurl.$invalid).to.be.false;
        });
        it('should not pass with invalid url', function () {

            form.emailorurl.$setViewValue('testing');
            $scope.$digest();

            expect(form.emailorurl.$invalid).to.be.true;
        });
    });
});

However one of the assertions fail, because $invalid is always false...

I inserted some logs inside the function validateEmailOrUrl and its never shown on my console, however logs outside of function appear, I assume the function its not being triggered.

Can someone help me? What is wrong here?

2
  • The docs suggest that $setViewValue does not trigger a call to the model validators. Try updating the ng-model directly in your test by assigning a value to $scope.model.emailorurl. Also I assume that you've replaced urlRegexp and emailPattern with real regExs? docs.angularjs.org/api/ng/type/… Commented Jan 16, 2018 at 20:55
  • I tried your solution, replacing form.emailorurl.$setViewValue('testing') to $scope.model.emailorurl = "testing" but still didn't work, the function validateEmailOrUrl in my directive is not triggered :( and yes I am using real regExs, I just didnt paste them there because it was irrelevant to the question and would make the question too big... do you have any other solution? thanks Commented Jan 17, 2018 at 9:38

1 Answer 1

0

I made it working, changing my unit test to the following:

describe('EmailOrUrlValidation tests', function() {

    var $scope,
        form,
        element;

    beforeEach(module("shared.validations"));

    beforeEach(inject(function($compile, $rootScope) {
        $scope = $rootScope;
        element = angular.element(
            '<form name="form">' +
            '<input data-ng-model="model.emailorurl" name="emailorurl" email-or-url-validation data-ng-required="true" validation-check-dirty="true" />' +
            '</form>'
        );

        $scope.model = { emailorurl: null }
        $compile(element)($scope);
        form = $scope.form;
    }));

    describe('invalid url', function () {
        it('email address without domain should not be valid', function () {
            $scope.$digest();
            var dirElementInput = element.find('input');
            angular.element(dirElementInput).val('teste@www').trigger('input');
            expect(form.emailorurl.$valid).to.be.false;

        });

        it('email address with domain should be valid', function () {
            $scope.$digest();
            var dirElementInput = element.find('input');
            angular.element(dirElementInput).val('[email protected]').trigger('input');
            expect(form.emailorurl.$valid).to.be.true;

        });

        it('url address starting with http should not be valid', function() {
                $scope.$digest();
                var dirElementInput = element.find('input');
                angular.element(dirElementInput).val('http://www.google.com').trigger('input');
                expect(form.emailorurl.$valid).to.be.false;

        });

        it('url address starting with https should not be valid', function () {
            $scope.$digest();
            var dirElementInput = element.find('input');
            angular.element(dirElementInput).val('https://www.google.com').trigger('input');
            expect(form.emailorurl.$valid).to.be.false;

        });

        it('url address starting without http should be valid', function () {
            $scope.$digest();
            var dirElementInput = element.find('input');
            angular.element(dirElementInput).val('www.google.pt').trigger('input');
            expect(form.emailorurl.$valid).to.be.true;

        });

        it('random text should not be valid', function () {
            $scope.$digest();
            var dirElementInput = element.find('input');
            angular.element(dirElementInput).val('jdsfvdsfg').trigger('input');
            expect(form.emailorurl.$valid).to.be.false;

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