I have a directive, which should behave differently, depending on how much time passed since it\'s initialization:
am.directive(\'showText\', () => ({
r
The reason why this happens is that $timeout.cancel(visibilityCheckTimeout)
launches unconditionally and immediately. Instead, it should be
$scope.$on('$destroy', () => $timeout.cancel(visibilityCheckTimeout));
There are things that can be done to improve testability (besides the fact that $timeout
works here as one-time scope watcher and asks to be replaced with the one).
$timeout
can be successfully spied:
beforeEach(module('app', ($provide) => {
$provide.decorator('$timeout', ($delegate) => {
var timeoutSpy = jasmine.createSpy().and.returnValue($delegate);
angular.extend(timeoutSpy, $delegate);
spyOn(timeoutSpy, 'cancel').and.callThrough();
return timeoutSpy;
});
}));
Private $timeout
callback can be exposed to scope.
$scope._visibilityCheckHandler = () => {
if (parseInt($scope.value, 10) < 100) {
$scope.textVisible = true;
}
};
$timeout($scope._visibilityCheckHandler, 330);
This way all of the calls can be spied and get full coverage:
let directiveScope;
...
const element = $compile(`...`)($scope);
directiveScope = element.isolateScope();
spyOn(directiveScope, '_visibilityCheckHandler').and.callThrough();
$scope.$digest();
...
expect($timeout).toHaveBeenCalledWith(directiveScope._visibilityCheckHandler, 330);
expect($timeout.cancel).not.toHaveBeenCalled();
In this case here's no need to have separate specs for '>= 0.33s' and '< 0.33s' with flush
delay argument, $timeout
's inner work was already tested in Angular specs. Also, callback logic can be tested separately from $timeout
spec.