Sleep in Jasmine

Viewed 11315

Usecase: For my angularJS(1.6.4) application, I am writing unit test in jasmine.

In my test case, I call a poll() function which keeps calling another function CheckTaskStatus() repeatedly using $interval. I am spy-ing CheckTaskStatus() and want to check that it has been called a certain number of times. So after calling poll(), I want to be able to wait for some time and then check the the number of times CheckTaskStatus() is called using expect().

Problem: I have been unable to find a way to make jasmine wait after call to poll() and before expect().

After poll() I have tried using below options, but those do not cause jasmine to sleep:

  • $timeout
  • settimeout
  • async function which calls await on function returning promise. Service import * as angular from 'angular';

export class Polling { public static $inject = ['$q', '$http', '$interval'];

constructor(private $q: ng.IQService, private $http, private $interval) {}

public poll(interval: number, pollFn: () => ng.IPromise<any>, until?: (any) => boolean, cancel?: ng.IPromise<any>) {
    let intervalPromise = null;
    const done = this.$q.defer();

    const intervalFn = () => {
        pollFn().then((pollFnResult) => {
            if (until && until(pollFnResult)) {
                this.$interval.cancel(intervalPromise);
                done.resolve();
            }
        }).catch(() => {});  
    };

    // Set up an interval to execute the pollFunction
    intervalPromise = this.$interval(intervalFn, interval);
    intervalPromise.catch(() => {});

    intervalFn();

    if (cancel) {
        cancel.then(() => {
            this.$interval.cancel(intervalPromise);
            done.resolve();
        })
            .catch(() => {}); 
    }

    return done.promise;
}

}

export default angular.module('myPolling', []) .service('polling', Polling).name;

Jasmine test

fdescribe('myPolling module tests', () => {
    'use strict';
    let $rootScope,
        $q: ng.IQService,
        $http,
        $interval,
        $timeout;

    beforeEach(mockModule('myPolling'));
    beforeEach(() => {
        jasmine.clock().install();
    });
    beforeEach(inject((_$rootScope_, _$q_, _$http_, _$interval_, _polling_, _$timeout_) => {
        this.$rootScope = _$rootScope_;
        this.$q = _$q_;
        this.$http = _$http_;
        this.$interval = _$interval_;
        this.polling = _polling_;
        $timeout = _$timeout_;


    }));

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function SleepForASecond() {
        await sleep(1050);
    }

    it('blah', () => {

        let pollCount = 0;
        let pollObj = {
            pollFn: () => {
                pollCount++;
                return this.$q.when(pollCount);
            }
        };
         // jasmine.createSpy('pollFn');
        spyOn(pollObj, 'pollFn').and.callThrough();

        let cancel = this.$q.defer();
        this.polling.poll(100, pollObj.pollFn, () => false, cancel.promise);
  
  // Need a mechanism to wait for a second.
  // SleepForASecond().then(() => { cancel.resolve(); });
  
        expect(pollObj.pollFn).toHaveBeenCalledTimes(10);

    });

});

2 Answers
Related