Reputation: 11752
I'm trying to test a timeout, but I'm having trouble with the scope of the element. I'm new to writing JS tests.
In the it( 'should have timer defined at start' )
test, my variable logs as undefined. Why is that?
I thought isolateScope() would pull the scope of the directive in?
My test looks like this:
https://plnkr.co/edit/IMrPd9g6HFSkgHizFF9p?p=preview
describe( 'Testing timeout', function(){
var scope, $timeout, element;
beforeEach(inject( function ($rootScope, $compile, _$timeout_, $injector ){
scope = $rootScope.$new();
$timeout = _$timeout_;
scope.onWarning = function(){
scope.warned = true;
};
element = '<div timeout on-warning="onWarning" on-timeout="onTimeout"></div>';
element = $compile(element)(scope);
scope.$apply();
scope.$digest();
}));
it( 'should have timer defined at start', function(){
console.log( element.isolateScope() , scope )
expect( element.isolateScope().timeoutService.timer ).not.toBeFalsy;
});
it( 'should have run warning function', function(){
$timeout.flush( 5000 );
expect( scope.warned ).toBe( true );
});
});
My directive looks like this:
app.directive( 'timeout', function( timeoutService ){
return {
restrict: "A",
scope: {
onWarning: "&", // what function to fire when showing a warning
},
link: function( scope, elem, attr ){
scope.timeoutService = timeoutService;
if( !scope.onWarning ){
throw new Error( "Must provide on-warning for timeout directive." );
}
//console.log( scope.onWarning, scope.onTimeout );
// register timeouts and warnings with the service
timeoutService.onWarning = scope.onWarning;
}
}
});
app.service( 'timeoutService', function( $timeout ){
var _this = this;
var timer = null;
var time = 5000;
this.startTimer = function(){
timer = $timeout( function(){
if( _this.onWarning ){
_this.onWarning()();
}
}, time)
}
this.startTimer();
})
Maybe I'm testing incorrectly?
Upvotes: 1
Views: 639
Reputation: 6961
I would just look at scope, since the angular team has already tested the $compile service well enough you know that this is what's being used for the directive's scope. To tell the truth, I usually just use a Controller defined outside the directive and test that. There doesn't seem to be anything in your directive that needs you to compile it to test it, except that you're using the link function instead of a controller.
Your directive is not attaching the timeoutService to its scope, which is good. So you can't look at it (and you shouldn't!).
AngularJS already has the $timer service. Wrapping it again in your own service is both unnecessary and error prone, so I wouldn't do this. Plus, it has no idea about the onWarning function passed to your directive. Instead, just call $timeout from your directive and check that it has no pending calls or that the data is in the right state after $timeout.flush(); Make sure to test that you canceled any pending timeouts on $destroy.
Upvotes: 0
Reputation: 18523
You need to call
beforeEach(module('plunker'));
In your 'Testing timeout' describe block. You were only calling it in the other describe block
Upvotes: 1