I am getting this error when I do the following test:
it('should call pauseAnimationInterval if in focus', inject(function(SearchBoxData, intervalManager, $timeout){
SearchBoxData.init_array = [];
SearchBoxData.inFocus = true;
SearchBoxData.init(intervalManager);
console.log(intervalManager.pauseTimeout);
console.log(intervalManager.pauseTimeoutTime);
console.log($timeout);
$timeout.flush(intervalManager.pauseTimeoutTime+1);
expect(rootScope.$broadcast).toHaveBeenCalledWith('onPauseInterval', intervalManager.loopIndex);
}));
It breaks on $timeout.flush(intervalManager.pauseTimeoutTime+1);
The $timeout method is called in the intervalManager.pauseAnimationInterval()
which is inside SearchBoxData.init(intervalManager)
:
intervalManager.pauseAnimationInterval = function (){
intervalManager.safeCancel(intervalManager.continueInterval);
intervalManager.safeCancel(intervalManager.initInterval);
intervalManager.initInterval = null;
intervalManager.continueInterval = null;
intervalManager.pauseTimeout = $timeout(function () {
if(intervalManager.inFocus === true){
intervalManager.loopIndex += 1;
if(intervalManager.loopIndex >= intervalManager.maxLoopIndex){
intervalManager.loopIndex = 0;
}
$rootScope.$broadcast("onPauseInterval", intervalManager.loopIndex);
intervalManager.continueAnimationInterval();
}else{
// Important condition: retry after the timeout if no focus
// main reason of glitch
intervalManager.pauseAnimationInterval();
}
}, intervalManager.pauseTimeoutTime);
};
I was not getting this error before, I am not sure what I did wrong.
Update: Here is a stacktrace with unminified version of angularJS:
at /Users/foo/projects/bar/vendor/assets/javascripts/angular.js:9268:88
at Scope.$eval (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:11986:28)
at Scope.$digest (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:11812:31)
at Scope.$apply (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:12092:24)
at Object.fn (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:13627:36)
at Function.self.defer.flush (/Users/foo/projects/bar/spec/javascripts/lib/angular/angular-mocks.js:126:32)
at Function.$delegate.flush (/Users/foo/projects/bar/spec/javascripts/lib/angular/angular-mocks.js:1689:20)
at null.<anonymous> (/Users/foo/projects/bar/spec/javascripts/unit/services/searchboxdata_service_spec.js:71:16)
Update 2: I traced it back to the injection of the SearchBoxData
factory. I am not sure what is wrong with it. Simply injecting it causes the error whenever I create a $timeout instance and use the flush method.
Update 3: I noticed this happens if I inject either $location or $route in one of the dependencies (indirect ones, it happens with some basic service that I use everywhere).
Update 4: Here is a plunker to reproduce it! http://plnkr.co/edit/7XweXI?p=info
Scope events which are $broadcast()'d or $emit()'d are synchronous, and return the event object when they're finished.
Some things in Angular depend on the returned event object, such as ngRoute.
So what you can do to fix this is simply add andCallThrough()
when you create your spy, so that it calls the original function and yields a return value.
Alternatively, if you don't want to use the real $broadcast, you can use andCallFake()
to supply a fake function which can return anything you want.
Example:
beforeEach(function(){
module('MyApp');
inject(function($injector){
rootScope = $injector.get('$rootScope');
spyOn(rootScope,'$broadcast').andCallThrough(); // will prevent the reference error
})
});
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