Search code examples
groovyspockfunctional-testinggeb

refactored geb login spec to module resulting in "not initialized" error


I am new to writing geb specs for funcational testing and appreciate your help with this issue. I am also new to Groovy, and the "Not Initialized" error might be to do with basic inexperience in that. I am trying to build a module to log me in automatically, at which point I can proceed with further tests, but I receive a geb.error.ModuleInstanceNotInitializedException. Previously, not using a module, I was able to log in to my page using only a spec. I was refactoring this to a module approach based on the answer on rcgeorge23's response here: How to refactor common Geb test sequences.

The spec:

import spock.lang.Unroll

class FlowSpecs extends GebReportingSpec {

    @Unroll
    def "setup Spec"() {
        given:
            to QUserPage
        when:    
            authModule.signIn("mwalle","password")
        then:
            assert { $("span", "class":"login-text z-label")[3].text() == "mwalle" }
    }

the page:

package pages.app

import geb.Page
import AuthModule

class QUserPage extends Page {

    static url = "/qsystem/quser"
    static at = { title == "QSystem" }

    static content = {
        authModule { module AuthModule }
    }
}

and the module:

import geb.Module 

class AuthModule extends Module {

    def idUser = js."zk.Widget.\$('\$usr').uuid" + "-real"
    def idPass = js."zk.Widget.\$('\$pwd').uuid"

    static content = {
        loginUser { $("input", id:idUser) }
        loginPass { $("input", id:idPass) }
        loginButton { $("button",class:"login-button z-button")[0] }
    }

    void signIn(String username = "mwalle", String password = "password") {
        loginUser.value(user)
        loginPass.value(pass)
        loginButton.click()
    }
}

The full error is:

geb.error.ModuleInstanceNotInitializedException: Instance of module class AuthModule has not been initialized. Please pass it to Navigable.module() or Navigator.module() before using it.
    at geb.Module.uninitializedException(Module.groovy:757)
    at geb.Module.getJs(Module.groovy:96)
    at AuthModule.<init>(AuthModule.groovy:5)
    at geb.navigator.AbstractNavigator.module(AbstractNavigator.groovy:356)
    at geb.content.NavigableSupport.module(NavigableSupport.groovy:207)
    at geb.content.PageContentTemplateFactoryDelegate.module(PageContentTemplateFactoryDelegate.groovy:31)
    at pages.app.QUserPage._clinit__closure2$_closure3(QUserPage.groovy:12)
    at pages.app.QUserPage._clinit__closure2$_closure3(QUserPage.groovy)
    at geb.content.PageContentTemplate.invokeFactory(PageContentTemplate.groovy:97)
    at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy:59)
    at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy)
    at geb.content.PageContentTemplate.create(PageContentTemplate.groovy:82)
    at geb.content.PageContentTemplate.get(PageContentTemplate.groovy:54)
    at geb.content.DefaultPageContentSupport.getContent(DefaultPageContentSupport.groovy:42)
    at geb.content.PageContentSupport.propertyMissing(PageContentSupport.groovy:39)
    at geb.Page.propertyMissing(Page.groovy:112)
    at geb.Browser.propertyMissing(Browser.groovy:216)
    at geb.spock.GebSpec.propertyMissing(GebSpec.groovy:60)
    at FlowSpecs.setup Spec(FlowSpecs.groovy:23)

Solution

  • The problem are these lines

    def idUser = js."zk.Widget.\$('\$usr').uuid" + "-real"
    def idPass = js."zk.Widget.\$('\$pwd').uuid"
    

    js needs an initialized navigator, as you can see with at geb.Module.getJs(Module.groovy:96)

    I would strongly advise to use another selector (css or otherwise) if you can instead of using javascript to lookup the id. If you cannot then move the lookup code into the content block.

    static content = {
        loginUser { $("input", id: js."zk.Widget.\$('\$usr').uuid" + "-real") }
        loginPass { $("input", id: js."zk.Widget.\$('\$pwd').uuid") }
        loginButton { $("button",class:"login-button z-button")[0] }
    }