WaitFor in Geb

383 views
Skip to first unread message

Avinash Kumar

unread,
Jun 11, 2020, 10:50:57 AM6/11/20
to geb-...@googlegroups.com
Hi,

I am trying to use waitFor method in different class other than page class.

For example:

class test extends page {


def clickAnElement(ObjName)
{

waitFor(60)
 {
 ObjName.click() 
}
}
}


and clickAnElement, i am calling from one page class .
but code fails at WaitFor() as WaitFor is not working for me in class other than page class.


Can any help me out in this case. Please

Thanks
Regards,
Avinash Kumar

Gordon Freeman

unread,
Jun 11, 2020, 4:43:54 PM6/11/20
to geb-...@googlegroups.com
It doesn`t work in such way (ok, I was not able to setup it). Works perfectly 
waitFor { something.displayed }
or
waitFor { title == 'something' }
Best regards,
SDA


--
You received this message because you are subscribed to the Google Groups "Geb User Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geb-user+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/CAMMvVTQGSi1pUnfqADqRGAmTWZjKNZZV11oEY7zOdS1dcFsmMA%40mail.gmail.com.

Gordon Freeman

unread,
Jun 11, 2020, 4:45:00 PM6/11/20
to geb-...@googlegroups.com
Forgot to add, you can setup interval in Geb.config
waiting {
timeout = 60
retryInterval = 1
}


Best regards,
SDA

Avinash Kumar

unread,
Jun 12, 2020, 1:01:14 AM6/12/20
to geb-...@googlegroups.com
Hi,
Thanks for your reply.
This was not my exact concern. I will explain in little clear way..

I have created a framework and in one package "Pages" i have created all groovy page class (POM) where in all page class under "Pages" package ,
i have used extends page and in this all waitFor method works fine for me.

example:-

package pages

import geb.Browser
import geb.Page
import opt.*



class Login extends Page {


    static at = {title == "Login"}

    static content = {
        // login form...
        usernameField {$('input#username')}
        passwordField {$('input#password')}
        logInButton {$('button#login-submit')}
        logoutButton {$("button", onclick : "logout();")}
        slide { $("div#myCarousel") }
        langField(wait:true) {$('a#lang')}

    }

    def "login To App"(username, password) {
        try {
            OperationUtil operationUtil = new OperationUtil();

            waitFor(60) {
                operationUtil.enterVal(usernameField, username);
                operationUtil.enterVal(passwordField, password);
            }

            operationUtil.clickAnElement(logInButton)

            waitFor(Integer.parseInt(ju.getJsonValue("maxWait"))) { logoutButton.displayed
                slide.displayed }
        }
        catch(Exception e){
            new ExceptionHandler().customizedException("Cannot login into the application");
            e.printStackTrace();
        }
    }
}

In other package, i have created one groovy class "OperationUtil" and i have used extend Page.
 
Example:

package opt

import geb.Page

class OperationUtil extends Page {


    def clickAnElement(objName){
            waitFor(60) {
                objName.click()
            }

        }



}


when i run the code , code fails at waitFor(60) point under OperationUtil class
and waitFor of "Login" class works fine for me.

 i get the below mentioned error:

"2020-06-12 10:24:06 ERROR - Issue with login: Instance of page class modules.OperationUtil has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it.

2020-06-12 10:24:06 ERROR - Issue with login: Instance of page class modules.OperationUtil has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it.

geb.error.PageInstanceNotInitializedException: Instance of page class modules.OperationUtil has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it."


Regards,
Avinash Kumar

Michael Kutz

unread,
Jun 12, 2020, 1:09:47 AM6/12/20
to Geb User Mailing List
The waitFor expects a closure returning a boolean value. Once the value returned is true, the waiting ends.

As Groovy interprets basically any object as an boolean (see http://groovy-lang.org/semantics.html#Groovy-Truth), this works great with Geb's NonEmptyNavigator (true) and EmptyNavigator (false).

In your case, you call click. As click returns null, the result will never be true.

  waitFor(60) { ObjName }.click()

Might work, but you should put the object retrieving inside the closure.

  waitFor(60) {
    ObjName.click()
    true
  }

Might also work if the first line on the closure will throw an exception, which would be catched by Wait. If no exception is thrown, the true will be returned and the waiting will end.

Kind regards,
Micha

--

Michael Kutz

unread,
Jun 12, 2020, 1:14:01 AM6/12/20
to Geb User Mailing List
Can you please give an example, how the page object is called and initialized?

--
You received this message because you are subscribed to the Google Groups "Geb User Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geb-user+u...@googlegroups.com.

Avinash Kumar

unread,
Jun 12, 2020, 2:56:02 AM6/12/20
to geb-...@googlegroups.com
Hi,

i tried with the same way as :

  waitFor(60) {
    ObjName.click()
    true
  }
 
  but it didn't worked
 
 
  My exact issue is that waitFor works find in "Login" class which follows exact geb POM where i have created static at , static url , static content
  and follows with method implementation and same class i have extends from Page(geb.Page),

 
  package pages

import geb.Browser
import geb.Page
import modules.OperationUtil




class Login extends Page {


    static at = {title == "Login"}

    static content = {
        usernameField {$('input#username')}
        passwordField {$('input#password')}
        logInButton {$('button#login-submit')}

    }

    def "login To App"(username, password) {
        try {
            OperationUtil operationUtil = new OperationUtil();

            waitFor(60) {
                operationUtil.enterVal(usernameField, username);
                operationUtil.enterVal(passwordField, password);
            }

            operationUtil.clickAnElement(logInButton)

            waitFor(Integer.parseInt(ju.getJsonValue("maxWait"))) { logoutButton.displayed
                slide.displayed }
        }
        catch(Exception e){
            new ExceptionHandler().customizedException("Cannot login into the application");
            e.printStackTrace();
        }
    }
}
 
  but in other class "OperationUtil" where i have only extends with Page (geb.Page) and does method implementation.
 
  package modules

 
  import geb.Page
 
  class OperationUtil extends Page {


    def clickAnElement(objName){
            waitFor(60) {
                objName.click()
return true
            }

        }



}



so waitFor at OperationUtil doesn't work.
 


2020-06-12 11:53:42 ERROR - Issue with login: Instance of page class modules.OperationUtil has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it.
2020-06-12 11:53:42 ERROR - Issue with login: Instance of page class modules.OperationUtil has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it.
geb.error.PageInstanceNotInitializedException: Instance of page class modules.OperationUtil has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it



Regards,
Avinash Kumar

Marcin Erdmann

unread,
Jun 15, 2020, 3:00:12 PM6/15/20
to geb-...@googlegroups.com
OperationUtil should not extend Page. After that there are two options:

1. You instantiate geb.waiting.Wait by hand and then call waitFor on it:

import geb.waiting.Wait

new Wait(60).waitFor {
    objName.click()
}

2. You pass an instance of configuration to the constructor of OperationUtil and have an instance of geb.waiting.DefaultWaitingSupport which you delegate to:

import geb.waiting.DefaultWaitingSupport
import geb.waiting.WaitingSupport
import geb.Configuration

@Delegate
private final WaitingSupport waitingSupport

OperationUtil(Configuration configuration) {
    this.waitingSupport = new DefaultWaitingSupport(configuration)   
}

void someMethod() {
    waitFor {
        //some condition
    }
}

and then in your page you initiate it like this: 

new OperationUtil(browser.config)

As a side note, please be aware that having code which mutates state, i.e. clicks on things, inside of the waitFor condition is an anti-pattern and I would advise against doing that.

Marcin

Reply all
Reply to author
Forward
0 new messages