'Refreshing' stale modules from within the module itself

86 views
Skip to first unread message

Martin de laat

unread,
Dec 19, 2018, 5:28:00 AM12/19/18
to Geb User Mailing List
Hi there,

TLDR: Is there a way to call this.refresh() or something from within a geb module itself to re-instantiate it the module when its reference is stale?

I have a dynamic web element on my page. A geb module is made for this web element, based on a class name.

Single clicking selects the element (gets class 'selected' added to it in DOM)
When it's selected, and you doubleclick on this element, it  'opens'/unfolds. 
In reality, whenever the element is selected, or opened, they disappear for a split-second from the page, then reappear.
So, I see it as the same module, but the geb module is now a stale reference whenever it's selected or opened.

In my test, the way to deal with this, is to first select (click) on the element matching my identifiers, wait a bit, then search for it again and doubleclick it.
But I wish to hide all this from the test itself, that's what geb is for right?

If I wish to abstract this and just have a custom method 'open()' in this geb module that:
- if element is not selected (it has classname: 'selected'): then click it. wait a bit
- then if it's selected, double click it

Then in between I need to 'refresh' it, search for the element again. But I don't want to have to do this behaviour from 

I see two options
1) Use some sort of this.refresh() command (does it exist?)
2) Move this method to the page object, and re-'instantiate' the geb module from there inbetween.

Any advice?


Marcin Erdmann

unread,
Dec 20, 2018, 6:37:18 AM12/20/18
to geb-...@googlegroups.com
Hi Martin,

The problem you describe is quite common, at least I come across it quite frequently, especially in single page apps.

The way I deal with it is to not use the element that is removed from the DOM as the base for the module but use the closest parent element which is not removed from DOM as part of interactions with the module in question. So I would have something like:

class DynamicModule extends Module {
    static content = {
        root { /*whatever selects what is now your module base and what gets removed from the DOM after clicking it*/  }
    }

    void open() {
        root.click()
        waitFor { root }
        // double click root, however that's implemented
        waitFor { root }
    }
}

But I wish to hide all this from the test itself, that's what geb is for right?

That is indeed the intent. It makes me very happy that others see it as well. 
 
1) Use some sort of this.refresh() command (does it exist?)

No, it doesn't exist. And it would not be possible the way things are implemented. But your need for it makes me think that we should have auto-refresh modules in Geb - ones for which the base element is calculated every time base is requested and not only at module creation time and then cached. This will be a significant change to how things are structured in Geb so it might be a while until it's implemented. I've created an issue for this: https://github.com/geb/issues/issues/557
 
2) Move this method to the page object, and re-'instantiate' the geb module from there inbetween.

That's indeed another approach but it suffers from bad encapsulation - the page object shouldn't now about the internals of the module and if you need to use the same module from another page you will have to duplicate that code. 

Martin de laat

unread,
Dec 20, 2018, 7:55:42 AM12/20/18
to Geb User Mailing List
I will give your suggestion a go, thank you. the root element is actually something that contains multiple of these dynamic modules so that might cause some problems. (i created a geb Module for that as well, and it stores these dynamic modules in a moduleList. )

Your idea for auto-refresh modules I think would be great because just using the $() selector in the test is doing that as well.
Although I'm wondering how this would work with multiple modules in a moduleList. If you are interacting with the first dynamic module, and it disappears briefly, you wish to wait for it to re-appear instead of it now selecting the second dynamic module (the 'new' first one in the list)
So maybe a waitFor all javascript stuff to be finished might help here before refreshing, I don't know.

For what it's worth, so far Geb is really helping with keeping the tests clean, DRY (no redundancy) and implementation-independent so far whilst still keeping things programmer-friendly

I agree with your comment regarding the bad encapsulation 

Marcin Erdmann

unread,
Dec 20, 2018, 2:33:29 PM12/20/18
to geb-...@googlegroups.com
If the root element is something that contains multiple of these dynamic modules then you might need to use parametrised modules (there is a small entry about what a parameterised module is as part of the manual section on modules at http://gebish.org/manual/current/#modules). You could maybe use element index as a parameter of your module. Not sure if that helps but it should give you ideas.

Thanks for pointing out that moduleList() might me an issue with regards to auto-refreshing. It did not come to my mind initially that it will be something that will need special handling.

The problem with "waitFor all javascript to be finished" is how do you define when it's finished? So far I've not found a generic answer to that as I believe that it's different from framework to framework (angular vs react) and sometimes even from action performed to action performed...

I'm very glad that you're finding Geb helpful in writing your browser tests.

--
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 post to this group, send email to geb-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/1b23f42f-0cf1-4e8d-aa41-0d59a77329f9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages