Categories
Grails Moving to Grails

Geb testing – revisited

I have now written a couple of domain geb tests and overcome the first practical obstacles.

Internationalization

Firefox and chrome browsers language is Norwegian, while htmlUnit is English. This means that labels et.c. will change with the configured language of the browser.

Starting with this EmployeeListPage:

class EmployeeListPage extends Page {

    static url = '/employee/index'

    static at = {
        title == "Employeelist"
    }

}

And then change the title:

class EmployeeListPage extends BasePage {

    static url = '/employee/index'

    static at = {
        title == getMessage('employee.index.label')
    }

}

I put code used for many Page tests in a new BasePage class which you will find at the bottom.

Collapsible menus

Firefox and chrome does not see collapsed menu-items, so trying to click on a collapsed item will fail the test.

When opening a collapsed menu there’s a time delay. While you have to waitFor Firefox and Chrome to open Trying to open, htmlUnit will fail.

This means that the tests must take these differences into account if you want to test for all browsers.

class EmployeeCRUD extends GebReportingSpec implements BaseCRUD {
    public static final String SHOW = 'show'
    def setup() {
        setupBaseCRUD()
    }
    def 'open employee list'() {
        homePage = to HomePage
        homePage.menuItemClick('menuEmployee')
        if (browser) {
            waitFor(10, 1) {
                $(id: 'collapseEmployee').hasClass(SHOW)
            }
        }

        when:
        homePage.linkClick(EmployeeListPage.url)

        then:
        waitFor { at EmployeeListPage }
    }
}

The BaseCRUD trait can be found at the bottom.

homePage.menuItemClick(‘menuEmployee’) will open the Employee sub-menu. You will have to “waitFor” the sub-menu having the class show in firefox/chrome, while htmlUnit will fail on waitFor. Therefore BaseCRUD.isBrowser() return true for firefox/chrome.

BasePage class

@Slf4j
class BasePage extends Page {

    @SuppressWarnings('FieldTypeRequired')
    static content = {
        link { $(A, href: it) }
        menuItem { $('li', id: it) }
    }

    public static final String A = 'a'
    MessageSource messageSource

    void linkClick(String href) {
        link(href).click()
    }
    void menuItemClick(String id) {
        interact {
            click(menuItem(id))
        }
    }
    String getMessage(String msgToGet, Object[] args = null) {
        if (messageSource == null) {
            messageSource = (MessageSource) grails.util.Holders.grailsApplication.mainContext.getBean('messageSource')
        }
        String result = messageSource.getMessage(msgToGet, args, LocaleContextHolder.locale)
        log.debug("getMessage(${msgToGet}, ${args}) == ${result}, locale: ${LocaleContextHolder.locale}")
        result
    }

}

BaseCRUD trait

trait BaseCRUD {

    boolean isBrowser() {
        String gebEnv = System.getProperty('geb.env')
        boolean result = (gebEnv) ? gebEnv != 'htmlunit' : false
        log.debug("isBrowser() == ${result}, gebConfEnv == ${gebConfEnv}")
        result
    }

    void setupBaseCRUD() {
        if (!browser) {
            LocaleContextHolder.locale = Locale.ENGLISH
        }
    }

}