Phil Phil - 6 months ago 27
AngularJS Question

How to have a mock controller pass data to a directive with Jasmine

I am trying to unit test a directive with Jasmine:

app.directive('helloWorld', function() {
return {
restrict: 'E',
scope: {
messages: '=',
onSelect: '&'
},
template: '<a ng-repeat="message in messages track by $index" href="" ng-click="onSelect({message: message})">Test: {{ message.name }}</a>',
link: function(scope) {
}
}
});


Ideally, I would like to pass in some mock data for
messages
, and ensure that the DOM element in the directive is correctly populated.

But I cannot understand how to get the template to compile with the mock data. Specifically,
messages: '&'
means that the directive is watching whenever the controller updates
messages
. Here is the test:

describe('Directive: HelloWorld', function() {
var $scope, ctrl, $compile, $rootScope;

beforeEach(module('app'));

beforeEach(inject(function(_$rootScope_, $controller, _$compile_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
$scope = $rootScope.$new();

ctrl = $controller('MainCtrl', {
$scope: $scope
});
}));

it('should list three messages', function() {
ctrl.messages = [{name: 'foo'}, {name: 'bar'}, {name: 'foobar'}];
var template = '<hello-world messages="messages" on-select="ctrl.foo(message)"></hello-world>';
var element = $compile(template)($scope);
$rootScope.$digest();

expect(element.children().length).toBe(3);
});
});


Here is the plunker: https://plnkr.co/edit/8Jy4eGXotduGvBsr8jkN?p=preview

I have looked at many SO questions, but I cannot yet make sense of it. How can I pass on data to the mock controller so that the template has access to it?

Update
I modified my Plunker to do this:
$scope.messages = [{name: 'foo'}, {name: 'bar'}, {name: 'foobar'}];
instead of
ctrl.messages = ...
. It works fine now.

Answer

You should be using $scope in your controller and exposing variables that you want to use in your templates by adding them to $scope instead of this.

See this plunk. The relevant changes to make the test pass are in MainCtrl code and line 21 of your test file. Also look at line 18 on index.html to see how to pass the scope variables in html.