2

Inside a directive of mine called by data-type-ahead I have the following, in a series of events:

$scope.test = 5;

// Bind blur event and clear the value of 
element.bind('blur', function(){
    $scope.test = 0;
});

I have tried a multitude of things to use in a unit test to correctly test the functionality of this blur event however I have not been successful. I have seen mention of the function triggerHandler. Here is my attempt at the unit test:

//Inject $compile and $rootScope before each test.
beforeEach(inject(function(_$compile_, _$rootScope_) {
    $compile = _$compile_;
    $rootScope = _$rootScope_;

    $scope = $rootScope.$new();
    $scope.test = 5

    html = angular.element('<input type="text" data-type-ahead/>');

    //Apply $scope to directive html.
    directive = $compile(html)($scope);

    //Trigger digest cycle.
    $scope.$digest();
}));

it('should trigger the events bound to the blur event on the directive', function() {
    html.triggerHandler('blur')
    expect($scope.test).toEqual(0);
});

However this is failing because $scope.test is remaining on 5. Is it the html element is incorrect, do I need another $digest or $apply for after I trigger the event?

1 Answer 1

2

You have 2 ways of getting this to work. The first is adding a timeout to your method (docs):

// somewhere above add - 
var originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

// in your beforeEach

beforeEach(function(){
 html.triggerHandler('blur');
  setTimeout(function(){
  done();
 }, 1000);
});

it('should trigger the events bound to the blur event on the directive',  
   function() {
    expect($scope.test).toEqual(0);
   }
);

I believe this to be "less good" practice (bad or worse is too negative a word for testing - the moment you test, you are already better :)). In general, I try to avoid testing async, because eventually my methods (a.k.a. units) are sync inside.

The "better practice" would be to write the method that changes the value like this:

// in the directive's ctrl
this.changeValue = function changeValue{
  $scope.test = 0;
}

// later on set the watcher
// Bind blur event and clear the value of 
$element.bind('blur', this.changeValue);

And then test the method itself instead of testing it async. You could test the $element.bind (via the spyOn(element, 'bind')) if you like to see that your ctrl/link methods create the binding.

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.