jeudi 13 août 2015

Angular unit testing $interval for a "clock" directive

I have an Angular directive "clock" and I'm trying to write a unit test to see if the clock actually $interval advances to a future time (ie: 2 minutes by looking at element.text()). I have a passing test of the current time, now I want to test if it will show a future time via $interval.flush. It appears to me $interval.flush isn't really advancing the clock.

Sure, there may be other strategies to test if $interval fires, but it would be helpful to the community (and my sanity) to answer why $interval.flush doesn't seem to be doing what I think it should be doing.

I'm following guidelines from these posts:

A related post suggested using Jasmine mocks, which I don't think is necessary anymore.

HTML

  <mydatething format="EEEE, MMMM d" interval="1000" timezone="notused"></mydatething>

DIRECTIVE

myApp.directive('mydatething', ['$interval', 'dateFilter', function ($interval, dateFilter) {
  return {
    restrict: "AE",
    scope: {
      format: '@',
      interval: '@'
    },
    template: '', // the template is the Date() output
    link: function (scope, element, attrs) {

      // scope expects format, interval and timezone
      var clockid;
      var clockinterval = scope.interval;
      var dateformat = scope.format;
      var clocktimezone = scope.timezone;

      // DOM update function
      function updateClock() {
        element.text(dateFilter(new Date(), dateformat));
      }

      // Instantiate clock
      updateClock();
      clockid = $interval(updateClock(), clockinterval);

      // For cancelling 
      scope.$on('$destroy', function () {
        $interval.cancel(clockid);
      });

      // Separate listener for locale change, manually refresh clock format
      scope.$on('$localeChangeSuccess', function () {
        updateClock();
      })
    }
  };
}]);

UNIT TEST

describe("tsdate directive", function(){
  var elem, scope, $interval, dateFilter;
    beforeEach(module('tsApp'));
    beforeEach(inject(function(_$rootScope_, _$interval_, _$compile_, _dateFilter_){
    $compile = _$compile_;
    dateFilter = _dateFilter_;
    $interval = _$interval_;
    $rootScope = _$rootScope_;
    scope = $rootScope.$new();

    elem = angular.element('<mydatething format="h:mm a" interval="15000"></mydatething>');
    elem = $compile(elem)(scope);
    scope.$digest();

    }));
    describe('on clock start', function() {
    it('to show the current date', function() {
      var currentdate = dateFilter(new Date(), elem.isolateScope().format);
      expect(elem.text()).toBe(currentdate);
      // this passes
    });
    it('that it updates the clock', function() {
      var futurems = 120000; // 2 minutes
      var futuredate = dateFilter(new Date().getTime() + futurems, elem.isolateScope().format)
      $interval.flush(futurems);
      expect(elem.text()).toBe(futuredate);
     // this fails
    });
    });

});

TERMINAL

PhantomJS 1.9.8 (Mac OS X) mydatething directive on clock start that it updates the clock FAILED
    Expected '3:55' to be '3:57'.

Console.log reveals, the futuredate var is 2 minutes incremented, but that the elem.text() remains the current time.



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire