5

I'm experiencing difficulties trying to invoke document.ready( function() {}) in my unit tests. Suppose I have multiple of them in my javascript file, and one of them called inside a named function i.e.

function myFunction() {
    $(document).ready(function() {
        //...
    });
}

How do I actually invoke them in my unit tests so I can actually test them? I'm using JsTestDriver to unit test my javascripts.

Thanks.

5 Answers 5

6

If it's a unit test, I'm guessing you check the function outputs when given certain inputs?

Here's my opinion:

You should prepare for the case where document.ready is called and the case where it isn't.

So your unit test should run each function twice - once to simulate a pre-ready call and one to simulate a post-ready call. That is, you should have one run-through where anything that happens on document.ready DOES run, and one run-through where it's just ignored (presumably to be called later on in the lifecycle).

EDIT: Just reread the question and understood it a bit more. You could just override $(document).ready to do what you want it to (which is NOT to wait for the DOMLoaded event to fire, but instead to run the functions immediately). This snippet will replace the $(document).ready function with a function that does exactly that. It should run before any unit tests.

var postReady = true; // or false to ignore the function calls.
jQuery.fn.ready = function(fn)
{
    if(postReady && fn) fn();
}

Example test case:

<html><head><title>whatever</title>
    <script type="text/javascript" src="/JS/jquery-1.3.2.js"></script>

    <script type="text/javascript">
        var postReady = true; // or false to ignore the function calls.
        jQuery.fn.ready = function(fn)
        {
            alert("We stole ready!");
            if(postReady && fn) fn();
        }

        $(document).ready(function()
        {
            alert("The function is called.");
        });
    </script>
</head><body></body>
</html>
9
  • @Adam A: thanks. I tried something similar but had no success. I'm not trying to prove document.ready works or not, but rather the code inside it. I'm having a very tough time just trying to invoke it from my unit test. I'm using JsTestDriver, and it doesn't appear to be loading any document.ready functions regardless of whether I put it under a named function or not. I tried delaying it, window.onload, just_call_it, etc... but its just not responding.
    – BeraCim
    Commented Dec 3, 2009 at 4:58
  • I tried out the code snippet I gave, and it seems to work. What it does is override jQuery's document.ready function, since the DOMLoaded event won't fire in your unit test, meaning document.ready will never run. The snippet makes document.ready independent from the DOMLoaded event. If we're in a post-DOMLoaded state (as determined by the postReady variable) then immediately call the function that was passed to document.ready. If we're in a pre-DOMLoaded state, then just ignore any functions that document.ready would have called (and make sure the function still does what it needs to).
    – Adam A
    Commented Dec 3, 2009 at 6:03
  • @Adam A: I tried running with the exact same code snippet, running the test in isolation, plus leaving only 1 document.ready function in my code(I have several of them). Unfortunately nothing happened (I had alert on first line and it didn't pop up at all). I can't figure out what I'm missing or what's wrong.
    – BeraCim
    Commented Dec 4, 2009 at 1:24
  • Edited my answer with what I tried. If I had to guess what your issue is, I'd say that maybe jquery is being included after the code snippet? I think that might cause .ready to be overwritten again with the original function call. Maybe you code do your unit testing against a jquery file that has the snippet included at the very end. That way it'll always overwrite the original implementation. I'll add my quick test example to this answer in a second.
    – Adam A
    Commented Dec 4, 2009 at 3:32
  • I wrote it up and got distracted...so "a second" become "24 hours". Apologies.
    – Adam A
    Commented Dec 5, 2009 at 5:11
5

You know document.ready... works so just start with calling the functions within it. Ideally, if you just have an init function called by the ready function then you call one function, it does what you need, and you can continue with your tests.

1
  • i agree that's how i do it but most people probably don't need an init function.
    – Andrew
    Commented Dec 9, 2012 at 22:22
5

You can take unit testing too far, in this case you need to ask yourself what you are testing, and why. The JQuery document.ready function works, and work well (you know this because it's been tested by many many people).

I would assume the trick would be to, instead of creating an anonymous function, naming one, and using it.

//So instead of this...
$(document).ready(function() {...});

//Do the following
$(document).ready(my_function);

Then you just test my_function and make sure that it is working. Make sure that you test the functions in the order their going to be loaded for an accurate test.

0

I suggest you to refactor the code. Even if you find a way to call it, it will be hard to understand for other developers.

Also (IMHO, I am not quite sure) you have to call the ready handlers even after the pages ready event was triggered, because if you "install" the ready() handler, if the document.ready event was already trigger, jquery calls that handler immediately (so it never loses that event, even if your code added a handler too late - that is, way after document.ready was still done).

Couldn't you just create a user my_on_read() event ? Or something the like?

Well, in the end, please just take care of ready() events and handlers that will be installed after the document.ready() is already done :)

1
  • Another detail to think twice about the design: Can you really always reproduce when this "adding" of a handler happens? In this example it means, will "myFunction" always be called on this or that page? You (or another developer) have to interprete that this function will install a ready handler - not obvious! I see no value in adding ready handlers in "other-than-global" code.. Well, just add the ready handler in global code, and move your global code to a central place. I am sure, this will make you question obsolete then. It looks like you found a major design flaw in the app...
    – Frunsi
    Commented Dec 3, 2009 at 3:54
0

Part of the answer to this question can be found here.

Below is the sample code to answer this question based on the above answer:

myFunction();
$.readyList[1]();

The index assumes that there is only 1 document.ready function in the source file. Index 0 refers to something else which I believe is info on the browser.

Not the answer you're looking for? Browse other questions tagged or ask your own question.