How to Unit Test Isolated Scope Directive in AngularJS
See angular element api docs. If you use element.scope() you get the element's scope that you defined in the scope property of your directive. If you use element.isolateScope() you get the entire isolated scope. For example, if your directive looks something like this :
scope : {
myScopeThingy : '='
},
controller : function($scope){
$scope.myIsolatedThingy = 'some value';
}
Then calling element.scope() in your test will return
{ myScopeThingy : 'whatever value this is bound to' }
But if you call element.isolateScope() you'll get
{
myScopeThingy : 'whatever value this is bound to',
myIsolatedThingy : 'some value'
}
This is true as of angular 1.2.2 or 1.2.3, not sure exactly. In previous versions you had only element.scope().
You can do var isolateScope = myDirectiveElement.scope()
to get the isolate scope.
You don't really need to test that $watch was called though.. that's more testing angularjs than testing your app. But I guess it's just an example for the question.
move the logic to a separate controller, ie:
//will get your isolate scope
function MyCtrl($scope)
{
//non-DOM manipulating ctrl logic here
}
app.controller(MyCtrl);
function MyDirective()
{
return {
scope : {},
controller: MyCtrl,
link : function (scope, element, attrs)
{
//moved non-DOM manipulating logic to ctrl
}
}
}
app.directive('myDirective', MyDirective);
and test latter as you would any controller - passing the scope object in directly (see Controllers section here for an example).
if you need to trigger $watch in your test do:
describe('MyCtrl test', function ()
{
var $rootScope, $controller, $scope;
beforeEach(function ()
{
inject(function (_$rootScope_, _$controller_)
{
// The injector unwraps the underscores (_) from around the parameter names when matching
$rootScope = _$rootScope_;
$controller = _$controller_;
});
$scope = $rootScope.$new({});
$scope.foo = {x: 1}; //initial scope state as desired
$controller(MyCtrl, {$scope: $scope}); //or by name as 'MyCtrl'
});
it('test scope property altered on $digest', function ()
{
$scope.$digest(); //trigger $watch
expect($scope.foo.x).toEqual(1); //or whatever
});
});