0

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)
Mark
  • 37
  • 6

1 Answers1

1

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] }
}
Leonard Brünings
  • 12,408
  • 1
  • 46
  • 66
  • This solved the issue, thank you. I am really curious why you advise against using the JS lookup. ZKoss randomises id values on each client load but guarantees every html element with an id has a unique value, so while the app is being developed, i figured calling the ZK client engine to get the id was better than selecting something else that might change from build to build and then cause test failures that would then need time to refactor. – Mark Sep 28 '17 at 17:57
  • I'm not familiar with ZKoss, but generally it is preferable to use a constant css/xpath selector, e.g. `$('.login-form input[name="username"]')` as this reduces error sources and thus makes your test more reliable. Furthermore, it is one less request to the browser and thus speeds up your tests. This may be negligible when running tests locally, but if you use a cloud service the delay is quite noticeable. – Leonard Brünings Sep 28 '17 at 20:55