I have a Controller that utilizes a service with a callback function upon success.
Controller Function
itemCtrl.save = function () {
ItemService.save({ username: SessionService.getUsername() }, itemCtrl.item, function (res) {
$scope.$emit('UPDATE_ITEMS');
$modalInstance.close(res);
});
};
spec
it('should close the modal when save is successful', function () {
spyOn(itemSrv, 'save').and.callFake(function () {
deferred = q.defer();
deferred.resolve();
return deferred.promise;
});
spyOn(modalInst, 'close').and.callThrough();
ItemCtrl.save();
scope.$digest();
expect(modalInst.close).toHaveBeenCalled();
});
When I execute this test in karma, it fails because the close function of the modalinstance is not invoked. I believe the issue lies in the spec description, as the functionality is functioning correctly in the application. I have a couple of queries regarding this:
- Is this the optimal way to describe callbacks on service calls within a controller?
- How should I format my specs when using callbacks?
-- EDIT --
I have modified my service calls to handle results as promises:
itemCtrl.save = function () {
ItemService.save({ username: SessionService.getUsername() }, horas.trabajo).$promise.then(function (res) {
$scope.$emit('UPDATE_ITEMS');
$modalInstance.close(res);
});
};
I am assuming my tests are failing because my service does not return a promise (it possesses a promise attribute which I'm utilizing to emit the event and close the modalInstance). However, I am still unsure of how to return a promise using ng-resource.
My solution was to return an object with a $promise attribute, containing the promise provided by q.
spec
it('should close the modal when save is successful', function () {
spyOn(itemSrv, 'save').and.callFake(function () {
deferred = q.defer();
deferred.resolve();
return {$promise: deferred.promise};
});
spyOn(modalInst, 'close').and.callThrough();
ItemCtrl.save();
scope.$digest();
expect(modalInst.close).toHaveBeenCalled();
});