I'm trying to unit test a directive like the one below. I want to be able to call the functions defined in the directive's controller ($scope.save
), but my tests can't seem to access that scope at all.
I also tried isolateScope()
, but that didn't return the inner $scope object like I expected. Maybe I did that wrong.
How can I get myDir
's $scope in the example below? (or at this fiddle if you prefer: http://jsfiddle.net/lalanl/8fkdsme3/)
angular.module('app', []).directive([
function(myService) {
return {
restrict: 'E',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function($scope) {
$scope.someVal = 'porcupine';
$scope.save = function() { /* ... */ };
}
}
}
]);
describe('myDir', function() {
var $compile, $http, $httpBackend, $scope, $rootScope, $q;
var element;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
$compile = _$compile_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$q = _$q_;
});
$scope.data = "some data";
element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
$rootScope.$digest();
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
});
it('should let me see its guts', function() {
expect($scope.save).toBeTruthy();
expect(typeof $scope.save).toBe("function");
});
});
<html>
<head>
<style type="text/css">
@charset "UTF-8";
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak,
.ng-hide:not(.ng-hide-animate) {
display: none !important;
}
ng\:form {
display: block;
}
</style>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>SO question - jsFiddle demo</title>
<script type="text/javascript" src="/js/lib/dummy.js"></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine.js"></script>
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine-html.js"></script>
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/boot.js"></script>
<link rel="stylesheet" type="text/css" href="http://jasmine.github.io/2.0/lib/jasmine.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-mocks.js"></script>
<style type="text/css">
</style>
<script type="text/javascript">
//<![CDATA[
angular.module('app', []).directive([
function(myService) {
return {
restrict: 'E',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function($scope) {
$scope.someVal = 'porcupine';
$scope.save = function() { /* ... */ };
}
}
}
]);
describe('myDir', function() {
var $compile, $http, $httpBackend, $scope, $rootScope, $q;
var element;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
$compile = _$compile_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$q = _$q_;
});
$scope.data = "some data";
element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
});
it('should let me see its guts', function() {
expect($scope.save).toBeTruthy();
expect(typeof $scope.save).toBe("function");
});
});
//]]>
</script>
</head>
<body>
</body>
</html>
Here is an updated jsfiddle with your tests working with an inline directive template.
EDIT: Managed to get it work with external templates. I forgot to flush my http request. I have updated the full answer and you can see the updated jsfiddle here
There were a few problems with your test:-
There are some more other minor changes that I did to make it work.
P.S. If you are using karma in your project, I use karma-ng-html2js-preprocessor for testing directives using external templates. Have a look here.