How can I simulate blur when testing directives in angularjs?


The problem

I am trying to test some directives (code for both below). One of them is an "email" (called "epost" in the code(norwegian)) directive. The solution to this should work for all of them, so I am keeping it to this one for now.

Technologies: Angularjs, Jasmine, Requirejs, (grunt & karma running in Chrome)

The directive validates email addresses in two ways; on upshift and on blur. I can test the upshift without problems as you can see in the test below, but I can't figure out how to simulate a blur so the bind('blur') in the directive runs.

What I have done

I have tried to catch the compiled element like this:

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

And then in the test i tried several permutations to trigger the blur with a console log just inside the bind function in the directive. None of the below works. It does not trigger.


I based the injection and setup on this: To test a custom validation angularjs directive

The 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;


The test (using jasmine and requirejs)

], function () {

describe('Directives', function () {

    var $scope;
    var form;

    beforeEach(function () {

        var html = '<form name="form">';
        html += '<input type="text" id="epost" name="epost" epost="" ng-model=""/>';
        html += '</form>';

        inject(function ($compile, $rootScope) {
            $scope = $rootScope.$new();

            $scope.model = { 
                epost: null

            // Compile the element, run digest cycle
            var elem = angular.element(html);

            form = $scope.form;


    describe('(epost) Given an input field hooked up with the email directive', function () {

        var validEmail = '';
        var invalidEmail = 'asdf@asdf';

        it('should bind data to model and be valid when email is valid on upshift', function () {
Problem courtesy of: lizter


I have been able to figure out where I went wrong after some breakpoint debugging.

The "element" item I get out using the approach described in the top of the question is not actually the directive it self. It's an object which wraps the form and the directive.

Like this

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

To actually simulate a blur on the directive it self, I did something like this

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

After getting the element I wanted, and wrapping it in a jQuery object (may be optional), it worked like a charm. I then used the approach like in the test in the question with $setViewValue and checked the model value like this.$setViewValue('');

Hope this could be of help to others trying to figure the directive testing out.

Solution courtesy of: lizter


I too ran into a similar problem and it mystified me. My solution was to use JQuery to get the input and then use angular.element(input).triggerHandler('blur') to make it work. This is odd to me because I do not have to do this with the click event.

spyOn(controller, 'setRevenueIsInvalid');
var sugarRow = $(element).find('tr#ve_id_5')[0];
var amount = $(sugarRow).find('input.amount')[0];
Discussion courtesy of: Maccurt

This recipe can be found in it's original form on Stack Over Flow.