How can I test two-way binding with isolateScope directive in jasmine + angular?

I want to check that the parent scope gets a new value after the directive has changed it, but it doesn't work for some reason.

This is my directive

angular.module('myModule').directive('myDirective', function(){
    return {
        template: 'just a template',
        restrict: 'A',
        scope: {
            'model' : '=myDirective'
        }, 
        link: function postLink( scope ){
            scope.changeModelValue = function( value ){
                scope.model = value;
            }
        }
    }
});

      

This is my test

describe('the test', function(){

    var scope, isolateScope, element;

    var reset = function(){
        scope = null;
        isolateScope = null;
        element = null;
    };

    beforeEach( inject(function( $rootScope ){
        scope = $rootScope.new();
        reset();
    }));

    var setup = inject(function( $compile ){
        element = angular.element('<div my-directive="item"></div>');
        element = $compile(element)(scope);
        scope.$digest();
        isolateScope = element.children().scope();
    });

    it('should work', inject(function( $timeout ){
        scope.item = null; 
        setup();
        expect(typeof(isolateScope.changeModelValue)).toBe('function'); // works!
        isolateScope.changeModelValue('new value');
        expect(isolateScope.model).toBe('new value'); // works!

        // tried all the of this - but didn't help..
        waitsFor(function(){
            try{ $timeout.flush(); } catch (e) { }
            try{ scope.$digest.flush(); } catch (e) { }
            try{ isolateScope.$digest(); } catch (e) { }

            return scope.reportLesson !== null;
        });

        runs(function(){
            expect(scope.item).toBe('new value'); //fails!!
        });

    }));
});

      

As you can see, I tried to blush a little and so, thinking maybe there are some asynchronous actions that need to happen for it to work, but that didn't help.

The test timed out on expectations.

How can I get it to work?

+3


source to share


2 answers


It turns out that $digest

and $timeout.flush

will not affect the binding.



To make it work I had to call isolateScope.$apply()

. I would like to explain it anyway.

+1


source


I may be wrong, but it looks like you're doing the binding there doesn't make sense.

// 2-way-bind the value of 'model' in this scope to the myDirective attribute in the parent scope
scope: {
    'model' : '=myDirective'
},

      

If it was "= item" then it makes sense given what you want, so try that.

Another thing is that you are a little strange:

// Give my directive an attribute which is the 'item' element from the scope
element = angular.element('<div my-directive="item"></div>');

      



So, a little weird, read this SO answer: Directular Significance for AngularJS

You overload your directive declaration with an attribute, and you mix scope variables with attributes (which can be accessed through your link function, but not what you do).

Edit:

As a final note, you should probably trust that AngularJS does the binding correctly. It takes a long time to write tests like this and you should focus on the programming logic instead.

-1


source







All Articles