Phil Phil - 1 year ago 108
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: {{ }}</a>',
link: function(scope) {

Ideally, I would like to pass in some mock data for
, 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
. Here is the test:

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


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=""></hello-world>';
var element = $compile(template)($scope);


Here is the plunker:

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?

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

Answer Source

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.