lundi 24 août 2015

How to $apply without forcing $render on tests

I've extended the angularjs-jquery-timepicker library, which overrides the ngModelController's $render method for a directive's ngModel, and I'm trying to test a $watch(someValue, listener) call. For this, I want to be sure that the listener function is called (trying to break the test before changing the code). Unfortunately, it seems that although the listener is never called, the $render is, either when calling $rootScope.$apply() or $rootScope.$digest().

Is it possible not to force the $render function to be called when running $rootScope.$apply() or $rootScope.$digest() on tests? Is there a better way to test this watcher? Since I don't own this library, should I recommend them not to override the $render function?

In my test:

        var element, aDate;
        aDate = new Date(2010, 12, 1, 14, 15);
        element = $compile("<span ui-timepicker ng-model='x' ng-model-options='{ getterSetter: true }'/>")($rootScope);

        var x = null;
        function getterSetter(value) {
          if (value === undefined) {
            return x;
          } else {
            x = value;
          }
        }

        // Initial call to set the getterSetter function.
        // The listener function will be called.
        // At the end of this $apply, the ngModel will 
        // have the value of null.      
        $rootScope.$apply(function() {
          $rootScope.x = getterSetter;    
        });

        // Using the getterSetter to set a new value.
        $rootScope.$apply(function() {
          $rootScope.x(aDate);
        });

        // I want this to fail
        expect(element.timepicker('getTime', aDate)).toEqual(aDate);

In the library's directive:

// It's called after each $apply
ngModel.$render = function () {
  var date = ngModel.$modelValue;
  ...
};


// It's watching the ngModel directly instead
// of its $modelValue, so the listener function
// isn't called when the getterSetter function
// changes the x's value.
scope.$watch(attrs.ngModel, listener);

I want to make it work like this, and test it properly:

scope.$watch(function() { return ngModel.$modelValue; }, listener);

Aucun commentaire:

Enregistrer un commentaire