I need to write a test for a function that has a setTimeout()
call inside, but i can't find how i should do.
This is the function
// Disables all submit buttons after a submit button is pressed. var block_all_submit_and_ajax = function( el ) { // Clone the clicked button, we need to know what button has been clicked so that we can react accordingly var $clone = $( el ).clone(); // Change the type to hidden $clone.attr( 'type', 'hidden' ); // Put the hidden button in the DOM $( el ).after( $clone ); // Disable all submit button. I use setTimeout otherwise this doesn't work in chrome. setTimeout(function() { $( '#facebook input[type=submit]' ).prop( 'disabled', true ); }, 10); // unbind all click handler from ajax $( '#facebook a.btn' ).unbind( "click" ); // Disable all AJAX buttons. $( '#facebook a.btn' ).click( function( e ) { e.preventDefault(); e.stopImmediatePropagation(); } ); };
And this is my test
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) ); // check that all submit are disabled $( '#facebook input[type=submit]' ).each( function( i, el ) { console.log( 'f' ); expect( el ).toHaveProp( 'disabled', true ); } ); } );
I've tried using jasmine.Clock.useMock();
and jasmine.Clock.tick(11);
but i couldn't get things to work, the test never pass
The overall approach varies based on your Jasmine version.
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 ); }); });
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() });
Since Jasmine 2 the syntax has changed: http://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support
You now can simply pass a done
callback to beforeEach
, it
, and afterEach
:
it('tests something async', function(done) { setTimeout(function() { expect(somethingSlow).toBe(true); done(); }, 400); });
Update: Since writing this it's now also possible to use async/await
which would be my preferred approach.
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