Here are a couple of directives, and unit tests.
Here is the first directive:
directive('myTestDirective', function() {
return {
link: function(scope, element, attrs) {
element.on("click", function(e) {
scope.clicked = true;
console.log("clicked");
}
}
});
And the unit test:
describe('my test directive', function() {
beforeEach(function() {
.....
inject($compile, $rootScope) {
scope = $rootScope.$new();
html = '<div my-test-directive></div>';
elem = angular.element(html);
compiled = $compile(elem);
compiled(scope);
scope.$digest();
}
});
it('should set clicked to true when click() is called', function() {
elem[0].click();
expect(scope.clicked).toBe(true);
});
});
When the above unit test is run, the test passes and clicked
is logged to the console.
However, consider this directive with restrict: E
added:
directive('myDirective', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
element.on("click", function(e) {
scope.clicked = true;
console.log("clicked");
}
}
});
And the unit test:
describe('my directive', function() {
beforeEach(function() {
.....
inject($compile, $rootScope) {
scope = $rootScope.$new();
html = '<my-directive></my-directive>';
elem = angular.element(html);
compiled = $compile(elem);
compiled(scope);
scope.$digest();
}
});
it('should set clicked to true when click() is called', function() {
elem[0].click();
expect(scope.clicked).toBe(true);
});
});
This test fails. clicked
is not logged to the console. From debugging I can see that the function bound the click()
binding for the directive is not being executed.
How can I continue to use restrict : 'E'
, while still retaining the ability to simulate clicks in unit tests?
Update: I have it working, thanks to Michal's plunkr.
I changed the inject() function to be:
inject(function($compile, $rootScope, $document) {
scope = $rootScope.$new();
html = '<my-test-directive-element></my-test-directive-element>';
elem = angular.element(html);
$compile(elem)(scope);
scope.$digest();
});
After this, both clicking using restrict attribute and restrict element work.
Plukr is here: http://plnkr.co/edit/fgcKrYUEyCJAyqc4jj7P
Using jqLite on('click') is not very Angular-ish and I don't think it would be processed by Angular digest cycle (thus whatever you would add to your scope within that callback wouldn't be rendered in your DOM unless you do it manually). You should prefer using the built-in ng-click directive within yours, so the html code becomes:
<my-directive ng-click="onClick()"></my-directive>
and your directive:
directive('myDirective', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
scope.onClick = function() {
scope.clicked = true;
console.log("clicked");
}
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With