Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I fake-time a jQuery animation using Sinon in a Jasmine unit test?

I have a 1 second jQuery .animate action that launches 5 seconds after page load. I set up a Sinon timer in my Jasmine unit testing code and test after a tick of 7 seconds to see if the post-animation properties are as they should be.

It doesn't work right, so I've placed an instance of the animation itself on my Jasmine HTML test page to better see what's going on.

  • In Firefox and Chrome, the page loads, the animation function is called, the unit test immediately fails, and then (also immediately) the animation visibly occurs.

  • In IE, Opera and Safari, the page loads, the animation function is called, the unit test immediately fails, and the animation never visibly occurs.

What I hoped for was the following (in all browsers):

  • The page loads, the animation function is called, the animation completes instantaneously, and the unit test immediately succeeds.

Looking at Sinon's documentation, it's fake timers cover the following processes: setTimeout, clearTimeout, setInterval, clearInterval, Date

I don't know how jQuery's animation works, but I imagine it is using CSS to transition, and CSS transitions are not covered in Sinon's useFakeTimers, so I imagine this is the problem. However, if I'm right about the problem I still need a solution.

Maybe I should try something other than Sinon? Jasmine's waits() works perfectly in this test, but is incredibly impractical for impatient folks like myself.

Any other suggestions? Please keep in mind that I am new to JS unit testing, so vague answers will confuse me more than help me. ;o)

like image 460
gcdev Avatar asked Sep 06 '11 17:09

gcdev


2 Answers

I think it is possible with SinonJs as it showed here: https://sinonjs.org/releases/latest/fake-timers/

test("should animate element over 500ms", function () {
   var el = jQuery("<div></div>");
   el.appendTo(document.body);

   el.animate({ height: "200px", width: "200px" });
   this.clock.tick(510);

   equals("200px", el.css("height"));
   equals("200px", el.css("width"));
});
like image 137
aliry Avatar answered Sep 21 '22 14:09

aliry


You can use jQuery off to turn off jQuery effects:

jQuery.fx.off = true

This won't solve your problem of the inital 7 second wait for your event to fire but it does mean you can test that the DOM has been changed as you expected.

like image 28
Derek Ekins Avatar answered Sep 19 '22 14:09

Derek Ekins