Autotesting QUnit

I was watching a video on performance code kata and I was intrigued by the use of autotest. Basically, it's just a tool that watches the filesystem for changes and re-runs your test-suite when stuff changes. I thought it was a neat idea and wanted to try it out, but I don't really write any Ruby. Instead I turned to the world's most popular dynamic language: JavaScript. I've used QUnit to do some test driven development in JavScript, so tried the simplest thing that could possibly work, a meta-refresh:

<meta http-equiv="refresh" content="5"/>

... and that kind of worked. It was kind of cool, but the constant refreshing gets in the way of of using the JavaScript console to poke at things. Which, when you're writing JavaScript, is kind of an important thing to do. So... meta-refresh with a pause button?

$(function(){
    function startPaused(){
        return location.hash.indexOf("autotest=true") == -1;
    }

    function enable(){
        button.removeAttr("disabled");
        $("body").unbind("mousemove", enable);
    }

    var paused = startPaused();
    var button = $('<input type="button" value="{title}" id="auto-refresh">'.replace("{title}",
        (paused ? "autotest" : "pause")
    ));
    $("body").prepend(button);

    button.click(function(){
        paused = !paused;
        button.attr("value", (paused ? "resume" : "pause"));
        button.attr("disabled", "disabled");

        if(paused){
            location.hash = "";
        }

        $("body").mousemove(enable);
    });


    setInterval(function(){
        if(!paused){
            location.hash = "#autotest=true"
            location.reload(true);
        }
    }, 5000);
});
#auto-refresh {
    float: right;
    background-color: #D2E0E6;
    border: 2px solid #2B81AF;
    color: #2B81AF;
    margin-right: 1em;
    margin-top: 1em;
    border-radius: 5px;
}

#auto-refresh[disabled] {
    opacity: 0.75;
}

There you go. Thirty-odd lines to implement meta-refresh a pause button sigh.

It is actually pretty neat. If I used QUnit more and was in a better position to judge the actually usefulness of such a feature I might try hacking this into core QUnit and seeing if I could get it merged upstream. I mean, there are entire projects built around adding this kind of functionality to other tools, and it's so easy to do in a browser. I'm not planning on it though, because I've only actually used QUnit for fun-zies, and can't really judge how useful this kind of functionality would be on an actual test suite.

May I Bring Your Attention To...

One of the cool things I ended up implementing was Chrome-style disable-enable behaviour for the pause/resume button. Basically, as part of the click handler, it disabled the button and attached a mousemove event handler on the body. The handler then enables the button and unbinds itself when a mousemove event fires. The cool part is that while the button is disabled and your cursor is over it, moving your mouse doesn't fire any mousemove events, but the second your cursor leaves the button, a mousemove event fires and the button gets enabled. You get to safely reuse the pause/resume button without worrying about double clicks doing the wrong thing. Pretty spiffy, huh?