How can I simulate blur when testing directives in angularjs?

Problem

I am trying to check out some directives (the code for both is below). One of them is the "email" (called "epost" in code (Norwegian)) directive. The solution for this should work for all of them, so I keep it for now.

Technologies: Angularjs, Jasmine, Requirements, (grunting and karma, working in Chrome)

The directive checks email addresses in two ways; when raising and blurring. I can check the raise without any problems, as you can see in the test below, but I can’t figure out how to simulate the blur so that the snapping ("blur") in the directive is done.

What I've done

I tried to catch the compiled element as follows:

elem = angular.element(html); element = $compile(elem)($scope); 

And then in the test, I tried a few permutations to cause blur using the console log only inside the bind function in the directive. None of the below work. This does not work.

 elem.trigger('blur'); element.trigger('blur'); elem.triggerHandler('blur'); element.triggerHandler('blur'); element.blur(); elem.blur(); 

I based injection and customization on this: To check the custom angularjs validation directive

Email directive in angularjs wrapped in requirejs

 define(function() { var Directive = function() { return { require: 'ngModel', link: function(scope, elem, attrs, ctrl) { var pattern = /^[A-Za-z0-9._%+-] +@ [A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/; elem.bind('blur', function() { scope.$apply(function () { if (!elem.val() || pattern.test(elem.val())) { ctrl.$setValidity('epost', true); } else { ctrl.$setValidity('epost', false); } }); }); ctrl.$parsers.unshift(function(viewValue) { if (pattern.test(viewValue)) { ctrl.$setValidity('epost', true); return viewValue; } else { return undefined; } }); } }; }; return Directive; }); 

Test (using jasmine and requirejs)

 define([ 'Angular', 'AngularMocks', ], function () { describe('Directives', function () { var $scope; var form; beforeEach(module('common')); beforeEach(function () { var html = '<form name="form">'; html += '<input type="text" id="epost" name="epost" epost="" ng-model="model.epost"/>'; html += '</form>'; inject(function ($compile, $rootScope) { $scope = $rootScope.$new(); $scope.model = { epost: null }; // Compile the element, run digest cycle var elem = angular.element(html); $compile(elem)($scope); $scope.$digest(); form = $scope.form; }); }); describe('(epost) Given an input field hooked up with the email directive', function () { var validEmail = ' a@b.no '; var invalidEmail = ' asdf@asdf '; it('should bind data to model and be valid when email is valid on upshift', function () { form.epost.$setViewValue(validEmail); expect($scope.model.epost).toBe(validEmail); expect(form.epost.$valid).toBe(true); }); }); }); }); 
+4
source share
2 answers

I managed to figure out where I was wrong after some debugging of the breakpoint.

The "element" element that I get using the approach described at the top of the question is not really its directive. This is an object that wraps form and directive.

Like this

 { 0: // The form { 0: // The directive (input element) { } } } 

To actually simulate the blur in the directive, I did something like this

 var directiveElement = $(element[0][0]); directiveElement.blur(); 

After getting the element that I need and wrapping it in a jQuery object (may be optional), it worked like a charm. Then I used the same approach as in the test in the question with $ setViewValue, and checked the model value as follows.

 form.epost.$setViewValue(' a@b.no '); directiveElement.blur(); expect($scope.model.epost).toBe(' a@b.no '); expect($scope.form.epost.$valid).toBeTruthy(); 

Hope this can help others trying to figure out how to test the directive.

+7
source

I also encountered a similar problem, and it puzzled me. My solution was to use jQuery to input the input, and then use angular.element (input) .triggerHandler ('blur') to make it work. This is strange for me, because I do not need to do this using the click event.

 spyOn(controller, 'setRevenueIsInvalid'); var sugarRow = $(element).find('tr#ve_id_5')[0]; var amount = $(sugarRow).find('input.amount')[0]; angular.element(amount).triggerHandler('blur'); expect(controller.setRevenueIsInvalid).toHaveBeenCalled(); 
0
source

Source: https://habr.com/ru/post/1491441/


All Articles