I want to test an interaction between child and parent directive: My example :
app.directive('foo', function() {
return {
restrict: 'AE',
template: '<div><div ng-transclude></div></div>',
transclude: true,
controller: function($scope) {
this.add = function(x, y) {
return x + y;
}
}
};
});
app.directive('bar', function() {
return {
restrict: 'AE',
require: '^foo',
template: '<div></div>',
replace: true,
link: function(scope, element, attrs, foo) {
console.log('link directive bar')
scope.callFoo = function(x, y) {
scope.sum = foo.add(x, y);
}
}
};
});
I want to test an interaction between boo and test, I do not want to mock child directive (boo) here is my test:
it('ensures callFoo does whatever it is supposed to', function() {
// Arrange
var element = $compile('<div foo><bar></bar></div>')($scope);
var ele = element.find('bar')
var barScope = element.find('bar').scope();
console.log('parent element :',element)
console.log('child element :',ele)
// Act Undefined :(
barScope.callFoo(1, 2);
// Assert
expect(barScope.sum).toBe(3);
});
full example: http://plnkr.co/edit/vYNFwpkbbHi4lsgwJkA9?p=preview
Your directives are already compiled, and since you have replace: true
on the bar
directive you'd no longer find bar
in the DOM. You can see this by looking at element.html()
, which would show something like this in your case:
<div><div ng-transclude=""><div class="ng-scope"></div></div></div>
If you remove replace: true
your test would work.
Otherwise, when jQuery is not loaded, jqLite is limited and its find
method can only search tag names. So I tried to find your scope quickly like this:
var barScope = element.find("div").eq(2).scope()
Do you have jQuery loaded in your app? If so, you could load it in your test too, and then add some more info to the bar
element like:
var element = $compile('<div foo><bar id="bar"></bar></div>')($scope);
Then you could find it like:
var barScope = element.find('#bar').scope();