Search code examples
geb

Is there a Gebish way of selecting elements between two elements?


I'm trying to write a Geb Module that gets all div elements between two elements and can't see a nice way of doing that.

I can probably do some sort of groovy list manipulation or iterative method but thought I'd check first to see if I am missing a Gebish way.

The html is roughly structured like this

<div id="theParent">
    <div class="v-gridlayout-slot">
        <div id="sectionHeader">Header 1</div>
    </div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">
        <div id="anotherSectionHeader">Header 2</div>
    </div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">
        <div id="yetAnotherSectionHeader">Header 3</div>
    </div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">...</div>
    <div class="v-gridlayout-slot">
        <div id="actionButton"></div>
</div>

The content section of my module looks like

static content = {
    headerOne { $("#sectionHeader")}
    headerTwo { $("#anotherSectionHeader")}
    headerThree { $("#yetAnotherSectionHeader")}
    ...
}

I was hoping there is a Gebish way of collecting all $("div.v-gridlayout-slot") that are between headerOne and headerTwo but can't see anything appropriate.

Solution from erdi:

    Navigator getElementsBetween(def fromElement, def toElement) {
        String nextId = toElement.attr('id')
        def betweenElements = fromElement.parent().nextAll("div.v-gridlayout-slot").takeWhile {
            !it.has(id: nextId)
        }
        $(*betweenElements)
    }

Solution

  • To be precise, according to the html structure you posted you are not looking for $("div.v-gridlayout-slot") that are between headerOne and headerTwo but are between the parrents of headerOne and headerTwo. I'd write it this way:

    def nextHeaderId = headerTwo.attr('id')
    def betweenHeaders = headerOne.parent.nextAll("div.v-gridlayout-slot").takeWhile { it.hasNot(id: nextHeaderId) }
    

    betweenHeaders will end up being a Collection<Navigator> (because of use of until which is a default Groovy method on Iterable with Navigator being Iterable<Navigator> and not a method on Navigator) so if you need to turn it into a navigator you'll have to call sum() on it:

    betweenHeaders.sum()
    

    or spread it and pass it to $():

    $(*betweenHeaders)