I have an AngularJS app where I need to test a workflow and guarantee that the correct values are set after an event is broadcasted.
In 1.3 I would do this:
it('should have the correct match workflow', function() {
// matchMaking event
runs(function() {
scope.$broadcast('matchMaking', gameId);
});
waitsFor(function() {
return (scope.match && scope.match.game);
}, 'A game should be defined', 3000);
runs(function() {
expect(scope.match.game).toBeDefined();
});
// matchCreate event
runs(function() {
scope.$broadcast('matchCreate', gameId, {}, {});
});
waitsFor(function() {
return scope.match.status === 'CREATED';
}, 'Match status should be \'CREATED\'', 3000);
runs(function() {
expect(scope.match.id).toBeDefined();
expect(scope.match.player).toBeDefined();
expect(scope.match.opponent).toBeDefined();
});
// matchPrepare event
runs(function() {
scope.$broadcast('matchPrepare');
});
waitsFor(function() {
return scope.match.status === 'PREPARED';
}, 'Match status should be \'PREPARED\'', 3000);
runs(function() {
expect(scope.match.id).toBeDefined();
});
// ... continues
});
With Jasmine 2.0, it seems that the only solution to test a workflow is to chain setTimeout
functions inside each other (all expectations must be inside the same spec in order to use the same scope):
beforeEach(inject(function($rootScope, $compile) {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
scope = $rootScope;
element = angular.element('<pg-match-making></pg-match-making>');
$compile(element)($rootScope);
$rootScope.$digest();
}));
it('should have the correct match workflow', function(done) {
var timeoutTick = 100;
scope.$broadcast('matchMaking', gameId);
setTimeout(function(){
expect(scope.match.game).toBeDefined();
scope.$broadcast('matchCreate', gameId, {}, {});
setTimeout(function(){
expect(scope.match.status).toEqual('CREATED');
expect(scope.match.id).toBeDefined();
expect(scope.match.player).toBeDefined();
expect(scope.match.opponent).toBeDefined();
scope.$broadcast('matchPrepare');
setTimeout(function(){
expect(scope.match.status).toEqual('PREPARED');
expect(scope.match.id).toBeDefined();
// ... call done() on the last setTimeout()
}, timeoutTick);
}, timeoutTick);
}, 6000);
});
I ended up with a pile of 7 setTimeout
which make the source code a lot harder to read and the test terribly slow to run.
Isn't there a better way to test a workflow with Jasmine 2.0?