I'm unit testing an Angular controller that uses a Rails Resource factory to handle GETing and POSTing model data from and to a Rails app. POSTing is done via a method on the model, e.g. (with a model $scope.resource
):
$scope.resource.update().then(successHandler, failureHandler);
I have a spy on this method to stub out the Ajax calls so I can unit test the controller:
resUpdateSpy = spyOn($scope.resource, 'update').and.callFake(function() {
return {then: function(success, failure){ success(resUpdateResponse); }};
});
In one of my controller methods, I expect the resource to be POSTed with certain data (Stripe data in particular). The data will be overridden after the POST in the same method, so I cannot test the state of the model afterwards. Ideally, I would like to something like:
expect($scope.resource.update).toHaveBeenCalled().whileValueOf($scope.resource.stripeKey).isEqualTo('tok123');
Obviously, this method doesn't exist in vanilla Jasmine. Is there a way in Jasmine (either vanilla or through a third-party project) to test the state of a value when a given spy is called? or is there another way to test this situation – specifically, the state of a model before its data POSTs – that I'm missing?
I'm running Jasmine 2.2.0 with Teaspoon 1.0.2 on an Angular 1.3.14 app.
you can add your own jasime matchers, the one you need would be
jasmine.Matchers.prototype.toBeResolvedWith = function() {
var done, expectedArgs;
expectedArgs = jasmine.util.argsToArray(arguments);
if (!this.actual.done) {
throw new Error('Expected a promise, but got ' + jasmine.pp(this.actual) + '.');
}
done = jasmine.createSpy('done');
this.actual.done(done);
this.message = function() {
if (done.callCount === 0) {
return ["Expected spy " + done.identity + " to have been resolved with " + jasmine.pp(expectedArgs) + " but it was never resolved.", "Expected spy " + done.identity + " not to have been resolved with " + jasmine.pp(expectedArgs) + " but it was."];
} else {
return ["Expected spy " + done.identity + " to have been resolved with " + jasmine.pp(expectedArgs) + " but was resolved with " + jasmine.pp(done.argsForCall), "Expected spy " + done.identity + " not to have been resolved with " + jasmine.pp(expectedArgs) + " but was resolved with " + jasmine.pp(done.argsForCall)];
}
};
return this.env.contains_(done.argsForCall, expectedArgs);
};
more available here https://gist.github.com/gr2m/2191748
updated after comment:
basically jasmine supports custom matchers. some in built matchers are toBe, toEqual, etc. You can add your own custom matcher to check the promise.
var customMatchers = {
toHaveBeenResolved: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var result = {};
// do you comparison logic here
result.pass = true/false;
result.message = 'some message about test result';
return result;
}
}
this.actual is a promise and you can resolve it like this
result = {};
promise.then(function(value){
result.value = value;
result.status = 'Resolved';
}, function(value){
result.value = value;
result.status = 'Rejected';
});
once you have declared you custom matcher use it in you test case in beforeEach callback.
beforeEach(function() {
jasmine.addMatchers(customMatchers);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With