Below is a simplified version of the code I am trying to test: a simple queue that is periodically emptied. For each number in the queue, an HTTP POST is made to send it to an (in this example fictional) API address. If the POST is successful, the number is shifted off the queue and the next number considered.
class Queue {
queue: Array<number>;
processingQueue: boolean;
constructor(public $http: angular.IHttpService) {
this.queue = new Array<number>();
this.processingQueue = false;
}
startQueueProcessor() {
this.processingQueue = false;
setInterval(() => {
if (!this.processingQueue)
this.processQueue();
}, 1000);
}
postNumber(number: number): angular.IHttpPromise<{}> {
return this.$http.post('http://mydummyurl.com/givemeanumber', number);
}
processQueue(): void {
this.processingQueue = true; // we are currently processing a queue, so make sure setInterval does not trigger another processing run
if (this.queue.length !== 0) { // are there any numbers to deal with?
const item = this.queue[0]; // get the first number in the queue
this.postNumber(item) // POST it (returns a promise)
.then(
() => { // if successful...
this.queue.shift(); // we've dealt with this item, so remove it from the queue
this.processQueue(); // check the queue again (recurses until all items have been dealt with)
},
() => { // if unsuccessful...
this.processingQueue = false; // something went wrong, so stop
}
);
} else {
this.processingQueue = false; // queue is empty, stop processing
}
}
enqueue(number: number): void { // add a number to the queue
this.queue.push(number);
}
}
The test I wish to create will check that, after having three items added to the queue, a single call to processQueue()
will empty it.
Something like this (mocked up in Jasmine):
describe('queueing', () => {
var queueService;
beforeEach(inject((_$httpBackend_, $injector) => {
httpBackend = _$httpBackend_;
httpBackend.whenPOST().respond(200);
queueService = $injector.get('queue');
}));
it('should clear queue completely when processQueue() is called once', () => {
queueService.enqueue(1);
queueService.enqueue(2);
queueService.enqueue(3);
expect(queueService.queue.length).toBe(3);
queueService.processQueue();
// somehow wait for processQueue() to complete
expect(queueService.queue.length).toBe(0);
});
});
My issue is that the second expect()
always fails with the message Expected 3 to be 0
. I assume this is due to the promises being returned by postNumber()
not being waited for, hence the queue is not empty by the time the second expect()
is called.
How do I wait for processQueue()
to complete before attempting to assert that the queue has been emptied?