Marcin Erdmann

Groovy, Grails, Geb...

Mocking browser timers in Geb tests

Functional tests are usually slow enough and you want to avoid any unnecessary waiting in them. But what should you do if the site you're testing is using animated elements? By simply putting waitFor {} blocks to wait for the animation to finish you're just wasting precious time.

But there is a simple solution - you can easily mock browser timers using sinon.js. Let's see how we can use it in Geb tests to make them faster when testing an example Grails application that contains a carousel.

Assuming that we're using Resources plugin, we'll first need to define a resource module that contains sinon.js and a simple Javascript file that will trigger timer mocking:

modules = {
    fakeTimer {
        resource '/js/test/sinon.js'
        resource '/js/test/fakeTimer.js'
    }
}

In fakeTimer.js file we need to assign the mocked timer to a global variable so that we can then reference it from Geb tests:

var fakeTimer = sinon.useFakeTimers();

The next step is to add the fakeTimer resource module to the head of the tested page. It is important to load it before any other Javascript so that any code that's using timers will not schedule any callbacks before the timers are mocked. We also want to make sure that the timers are mocked only in test environment:

<html>
    <head>
        <g:if env="test"><r:require module="fakeTimer"/></g:if>
        ...
    </head>
    ...
</html>

And finally we can write our test:

class TimeeMockingSpec extends GebSpec {
    void tick(milis) {
        js.exec "fakeTimer.tick($milis)"
    }

    void 'fake time in browser'() {
        when:
        to HomePage

        then:
        activeSlide == 1

        when:
        tick(2100)

        then:
        activeSlide == 2
    }
}

In tick() we are using Geb's js object that allows us to work with Javascript in the browser to call a method on the global object holding the mocked timer. Then it's just a matter of using the tick() method to control the time in the browser in functional tests.