I've got a Controller that uses a service that has a callback function on 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 on successful save', 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 run this test in karma is failing because the close function of the modalinstance is not called. I think the problem is on the spec description, because the functionality is working in the app. I have a few questions about this:
- Is this the best way of describing callbacks on service calls in a controller?
- How should I describe my specs using callbacks?
-- EDIT --
I've changed my service calls to make them 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 guess I'm not passing the tests because my service does not return a promise (it has a promise attribute which I'm calling to emit the event and close the modalInstance). But still I'm getting confused about how to return a promise using ng-resource.
My attempt to solve it was returning an object with a $promise attribute, which contains the promise that q provides.
spec
it('should close the modal on successful save', 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();
});