Unit testing promises attached to AngularJS scope
One of the many bits of magic AngularJS makes an automatic promise for you so that you can write code like this:
function SomeCtrl($scope, Resource) {
$scope.items = Resource.query();
}
However, the service I'm working with functions with via JSON-RPC and ngResource doesn't seem to play well with it. I had to mock the backend to respond appropriately, but for some reason I can't figure out how to validate the response at the controller level.
"use strict";
describe('controllers', function() {
describe('LibraryCtrl', function() {
var scope, ctrl;
beforeEach(inject(function($rootScope, $controller) {
JsonRpc.respondWith({ some : data });
scope = $rootScope.$new();
ctrl = $controller(LibraryCtrl, { $scope : scope });
// controller does `$scope.items = RPCService.get()`
}));
it("should create a `items` model with data fetched via JSON-RPC", function() {
// here where I'm very confused
// JsonRpc does $httpBackend.flush()
JsonRpc.respond();
// now I want to inspect the property on the controller
expect(scope.items).toEqualData( { some : data } );
});
});
});
The problem is what scope.items
the promise is. This particular property will remain a promise because it $digest()
does not appear to resolve the promise and does not attach the return value as a model value. I cannot make a simple equality statement.
My workaround is to use a promise layout:
var result = {
capture : function(v) { result.value = v; },
value : null,
};
and then try this:
scope.items.then(result.capture);
expect(result.value).toEqualData(...);
It works (but somehow wrong). As a by-product (not a real question for brown dots), replacing the string result.capture
with JsonRpc.respond()
causes the test to fail ( result.value
being null).
Here are the questions: what is the correct way to test promises as model models? Is this result the result. What am I doing ok, or is there a better way to do this? Also, I would love to know why reversing the binding of promises with a reaction flush results in the response not resolving or capturing ...?
source to share
mockResource = {query: jasmine.createSpy('query').andReturn([{id: 1, name: foo}])
module(function ($provide) {
$provide.value('Resource', mockResource);
...
expect(mockResource.find).toHaveBeenCalled()
expect(scope.items)....
This allows you to isolate the controller.
source to share