There is probably too many of this sort of question on here, but none that I have found come up with one good solution. The problem, in my view, should be too common. dirty pseudocode: Acontroller
app.controller('Acontroller',function($scope,$q, Aservice){
$scope.someScopeVariable = null;
function refresh(){
$q.all([
Aservice.getCollectionA().then(function(results){
return $scope.collectionA = results}),
Aservice.getCollectionB().then(function(results){
return $scope.collectionB = results})
]);
};
$scope.someScopeFunction = function(){
Aservice.someServerUpdateCall().then(function(){
refresh().then(function(){
$scope.someScopeVariable = 'woot'
}
}
}
})
Is this really just really poorly written? I am tearing out my remaining stubble of hair on my bald head trying to test that someScopeFunction.
How would you test this? (Jasmine (1.3) on Karma)
I can test the first tier of the promise, but I cant simply assert that refresh function is called. I can mock the service but am having a hell of a time getting a spy on that refresh function. I would assume I have to instantiate the controller (a found a solution like that), though that does seem a little mad.
So (pardon the coffeescript):
describe 'Acontroller', ->
mockService = {}
aResponseObject =
a:1
b:2
beforeEach -> module('app')
beforeEach inject ($controller,$q, $rootScope) ->
emptyPromise = ->
defer = $q.defer
defer.resolve()
defer.promise
responsePromise = ->
defer = $q.defer()
defer.resolve([aResponseObject],[aResponseObject])
defer.promise
mockService.getCollectionA = jasmine.createSpy('getCollectionA').andReturn responsePromise()
mockService.getCollectionB = jasmine.createSpy('getCollectionB').andReturn responsePromise()
mockService.someServerUpdateCall = jasmine.createSpy('someServerUpdateCall').andReturn emptyPromise()
scope = $rootScope.$new()
$controller 'Acontroller',
$scope: scope
Aservice: mockService
$rootScope.$apply ## resolve promises
describe 'someScopeFunction', ->
it 'should call Aservice with someServerUpdateCall', ->
scope.someScopeFunction()
scope.$digest
expect(Aservice.someSererUpdateCall).toHaveBeenCalled() ##this should work
That expectation works fine, though confirming the the next call to refresh is where I'm at a loss. Seeing as its not tied to the scope, I would assume I have to instantiate the Controller?
I've played around with other strategies including something like:
done = false
refresh = jasmine.createSpy('refresh')
scope.someScopeFunction().then() -> done = true
waitsFor -> done
runs ->
scope.$apply ->
expect(refresh).toHaveBeenCalled()
To no avail though, promise is not resolved.
I heard Mocha makes async calls a little more straightforward, though I really dread trying to start over.