How to test a function which has a setTimeout with jasmine?
For anyone googling this, a better answer can be found timer testing
import { fakeAsync, tick, discardPeriodicTasks } from '@angular/core/testing';
it('polls statusStore.refreshStatus on an interval', fakeAsync(() => {
spyOn(mockStatusStore, 'refreshStatus').and.callThrough();
component.ngOnInit();
expect(mockStatusStore.refreshStatus).not.toHaveBeenCalled();
tick(3001);
expect(mockStatusStore.refreshStatus).toHaveBeenCalled();
tick(3001);
expect(mockStatusStore.refreshStatus).toHaveBeenCalledTimes(2);
discardPeriodicTasks();
}));
The overall approach varies based on your Jasmine version.
Jasmine 1.3
You can use waitsFor
:
it( "Disable all submit buttons", function() {
// Get a button
var $button = $( '#ai1ec_subscribe_users' );
// Call the function
utility_functions.block_all_submit_and_ajax( $button.get(0) );
// Wait 100ms for all elements to be disabled.
waitsFor('button to be disabled', function(){
var found = true;
// check that all submit are disabled
$( '#facebook input[type=submit]' ).each( function( i, el ) {
if (!el.prop('disabled')) found = false;
});
return found;
}, 100);
});
You could also use waits
if you know exactly how long it will take:
it( "Disable all submit buttons", function() {
// Get a button
var $button = $( '#ai1ec_subscribe_users' );
// Call the function
utility_functions.block_all_submit_and_ajax( $button.get(0) );
// Wait 20ms before running 'runs' section.
waits(20);
runs(function(){
// check that all submit are disabled
$( '#facebook input[type=submit]' ).each( function( i, el ) {
expect( el ).toHaveProp( 'disabled', true );
});
});
});
There is also a third way of doing this, without the need for waits
, waitsFor
, and runs
.
it( "Disable all submit buttons", function() {
jasmine.Clock.useMock();
// Get a button
var $button = $( '#ai1ec_subscribe_users' );
// Call the function
utility_functions.block_all_submit_and_ajax( $button.get(0) );
jasmine.Clock.tick(10);
// check that all submit are disabled
$( '#facebook input[type=submit]' ).each( function( i, el ) {
expect( el ).toHaveProp( 'disabled', true );
});
});
Jasmine 2.0
You can use done
, the test callback:
it( "Disable all submit buttons", function(done) {
// Get a button
var $button = $( '#ai1ec_subscribe_users' );
utility_functions.block_all_submit_and_ajax( $button.get(0) );
setTimeout(function(){
// check that all submit are disabled
$( '#facebook input[type=submit]' ).each( function( i, el ) {
expect( el ).toHaveProp( 'disabled', true );
});
// Let Jasmine know the test is done.
done();
}, 20);
});
you can mock out the timer behavior:
it( "Disable all submit buttons", function() {
jasmine.clock().install();
// Get a button
var $button = $( '#ai1ec_subscribe_users' );
// Call the function
utility_functions.block_all_submit_and_ajax( $button.get(0) );
jasmine.clock().tick(10);
// check that all submit are disabled
$( '#facebook input[type=submit]' ).each( function( i, el ) {
expect( el ).toHaveProp( 'disabled', true );
});
jasmine.clock().uninstall()
});