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);
});
});