AngularJS, Jasmine, Karma: Testing Directives
If you haven’t yet experienced using ngMock with Jasmine, you don’t know what you’re missing — it’s all wonderful and powerful. Keep reading, let’s go!
As I mentioned at the end of the article AngularJS: Creating Tests with Jasmine and Karma, you can use Angular’s $injector to call everything you need to work with your modules from anywhere. In this guide we’ll use the following dependencies:
$injector$rootScope$compile
Importing the dependencies
Let’s start by calling our dependencies inside our test:
describe('app module', function () {
var $compile, $rootScope;
beforeEach(module('app'));
beforeEach(inject(function ($injector) {
$compile = $injector.get('$compile');
$rootScope = $injector.get('$rootScope');
}));
});
Above, we’ve imported the dependencies that will be reused by the upcoming suites. Now let’s import the dependencies for our directive:
describe('app module', function () {
var $compile, $rootScope;
beforeEach(module('app'));
beforeEach(inject(function ($injector) {
$compile = $injector.get('$compile');
$rootScope = $injector.get('$rootScope');
}));
describe('replacer directive', function () {
var element, scope, form;
beforeEach(inject(function ($injector) {
scope = $rootScope.$new();
}));
});
});
Now we need to compile our element inside the replacer directive suite. We’ll do it like this:
describe('replacer directive', function () {
var element, scope, form;
beforeEach(inject(function ($injector) {
scope = $rootScope.$new();
element = '<form>' + '<input ng-model="text" name="text" replacer-directive>' + '</form>';
element = angular.element(element);
element = $compile(element)(scope);
}));
});
Now you might be wondering:
How on earth am I going to get my input? Do I have to do gymnastics with jQuery or
document.querySelector?Answer: NO! Just assign a value to the only variable we haven’t defined yet inside the
replacer directivesuite:beforeEach(inject(function ($injector) { scope = $rootScope.$new(); element = '<form>' + '<input ng-model="text" name="text" replacer-directive>' + '</form>'; element = angular.element(element); element = $compile(element)(scope); form = scope.form; scope.$digest(); }));Now we can access our input through the
formvariable, like this:form.textNote that we used a new method on the second-to-last line:
scope.$digest(). It takes care of updating the scope — any modifications you make to the scope should be followed by ascope.$digest()so that all changes are applied to the DOM.
Now we can write our tests:
it('should replace 2 with 3', function () {
scope.text = 252;
scope.$digest();
expect(form.text).toBe(352);
});
From here on, we can live happily ever after and test our directives in every possible way to make sure everything works exactly as expected.
As always, leave your questions in the comments. Cheers everyone and until next time!