Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
365 views
in Technique[技术] by (71.8m points)

javascript - How to Unit Test Isolated Scope Directive in AngularJS

What is a good way to unit test isolated scope in AngularJS

JSFiddle showing unit test

Directive snippet

    scope: {name: '=myGreet'},
    link: function (scope, element, attrs) {
        //show the initial state
        greet(element, scope[attrs.myGreet]);

        //listen for changes in the model
        scope.$watch(attrs.myGreet, function (name) {
            greet(element, name);
        });
    }

I want to ensure the directive is listening for changes - this does not work with an isolated scope:

    it('should watch for changes in the model', function () {
        var elm;
        //arrange
        spyOn(scope, '$watch');
        //act
        elm = compile(validHTML)(scope);
        //assert
        expect(scope.$watch.callCount).toBe(1);
        expect(scope.$watch).toHaveBeenCalledWith('name', jasmine.any(Function));
    });

UPDATE: I got it to work by checking if the expected watchers were added to the child scope, but it's very brittle and probably using the accessors in an undocumented way (aka subject to change without notice!).

//this is super brittle, is there a better way!?
elm = compile(validHTML)(scope);
expect(elm.scope().$$watchers[0].exp).toBe('name');

UPDATE 2: As I mentioned this is brittle! The idea still works but in newer versions of AngularJS the accessor has changed from scope() to isolateScope():

//this is STILL super brittle, is there a better way!?
elm = compile(validHTML)(scope);                       
expect(elm.isolateScope().$$watchers[0].exp).toBe('name');
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...