First iteration of this question: Unit testing Angular directive with $http
I created a directive that, when bound to an input, responds to blur/keyup events by calling a service before modifying the DOM. This service relies on $http and is therefore asynchronous. I've written a functional unit test for the service, but for the life of me I can't write a working test for the directive.
describe('SignupForm directives', function () {
var form, // el to which directive is applied
scope,
userService,
el;
beforeEach(function() {
module('signupform.directives');
});
beforeEach(function() {
inject(function ($injector, $rootScope, $compile, $q, $timeout) {
scope = $rootScope.$new();
el = $compile('<input id="username" type="text" name="username" ng-model="user.username" sg-valid-username />')(scope);
userService = $injector.get('userService');
scope.user = { username: 'test_username' };
spyOn(userService, 'checkIfUserExists');
});
});
it('Directive fires on blur', function() {
scope.$digest();
// build blur event and fire it
var blurEvent = $.Event('blur');
angular.element(el).triggerHandler(blurEvent);
expect(userService.checkIfUserExists).toHaveBeenCalled();
});
});
I have proven using the debugger that the service—userService.checkIfUserExists—gets called. It's just the expect() happens before then and fails the test.
I have no clue how to write this asynchronously, though. Jasmine 2.0's done() concept is mind-boggling, and userService does not otherwise need a callback to pass in.
How can I approach this?
scope.$digest()afterangular.element(el).triggerHandler(blurEvent);