Navigator attribute matching

41 views
Skip to first unread message

Ben Frey

unread,
Aug 20, 2020, 10:28:39 AM8/20/20
to Geb User Mailing List
From the concrete example at https://gebish.org/manual/current/#the-code-code-function, it sounds like attribute matching is exact, although it's not super clear that this is indeed the case. Is this a correct assumption?

If matching is exact, is there any way to match with a wildcard? I'm working on automating a page that's built with YUI, and the name attributes for elements are built from Java objects, so for example name="parentobject.childlist[0].thing". Is there a way to select all indices of the childlist, like name="parentobject.childlist[*].thing"?

thok...@gmail.com

unread,
Aug 20, 2020, 1:57:08 PM8/20/20
to Geb User Mailing List

Hello Ben, 

no, you cannot use placeholders like this in CSS selectors, only direct (partial) comparison.

There are two common ways to select WebElements in Selenium (which Geb is built on top of).
1. By CSS selectors, which is the the default in Geb, if you just pass a String to the $-method
2. By XPath, which you can do by passing a Selenium-"By"-object to the $-method, like this: $(By.xpath("//div"))

XPath gives you much more options, as it really is a small programming language, that allows you to traverse the tree of HTML in pretty much any way you could imagine, including matching of regular expressions.

With XPath, it could work like this:

$(By.xpath("//*[matches(@name, ' parentobject.childlist[\\d].thing')]"))

i.e. using "\d", which means "digit" in regular expressions as the wildcard (and escaping that with another backslash because its a Java-String).

Another option, using only CSS selectors, could be to combine a start-of-string with an end-of-string selector, like this:

$("[name^='parentobject.childlist['][name$='].thing']")

Best Regards, 
Thomas

Ben Frey

unread,
Aug 20, 2020, 2:35:57 PM8/20/20
to Geb User Mailing List
Great. And can I then click all of them at once?

Marcin Erdmann

unread,
Aug 21, 2020, 4:22:23 AM8/21/20
to geb-...@googlegroups.com
Yeah, but you have to be explicit that you are expecting multiple elements in the navigator and want to click on all of them by using the spread operator otherwise you will get a SingleElementNavigatorOnlyMethodException:

def navigatorWithMultiplelements = $(....)
navigatorWithMultipleElements*.click()

--
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/f048c375-22eb-4220-b29d-28e019fc86e2n%40googlegroups.com.

Ben Frey

unread,
Aug 21, 2020, 10:49:57 AM8/21/20
to Geb User Mailing List
Cool. Thomas, I tried the CSS selector method and it looks like the compiler is confused by the $ in the end-of-string selector. I think it's colliding with Gstrings.
I tried the XPath selector but Selenium complained that the string isn't a valid XPath expression. From some Googling it sounds like the matches function is XPath 2.0, and still almost nothing supports that version.

Thomas Hirsch

unread,
Aug 21, 2020, 10:54:22 AM8/21/20
to Geb User Mailing List
Hi Ben, 

you can escape a $ in a GString by putting a backslash in front, or alternatively, not use a GString in the first place, by using only single quotes (').
I haven't double checked the XPath version, sorry for that.

Thomas

Ben Frey

unread,
Aug 21, 2020, 11:20:59 AM8/21/20
to Geb User Mailing List
:facepalm: I should have thought of escaping the $. But otherwise there's no getting around it being seen by the compiler as  GString since the CSS expression has single quotes, so you have to use doubles for the outside.

I was able to select the radio buttons I wanted, but it turns out that they aren't interactable, according to Selenium. When I was doing each one individually, I had to set their value (e.g. $('form')['element_name'] = 'N'). Unfortunately, it doesn't seem that I can assign via the spread operator. Is that correct?

Ben Frey

unread,
Aug 21, 2020, 11:31:35 AM8/21/20
to Geb User Mailing List
I solved the problem myself, although it's a bit of a hack since not all radio buttons are visible by default:

$("[name\$='thing']").each {
    if(it.isDisplayed()) {
        it.value('N')
    }
}

Thomas Hirsch

unread,
Aug 21, 2020, 11:36:13 AM8/21/20
to Geb User Mailing List
Hi Ben, 

CSS selectors can be written with single quotes or double quotes. Quotes can also be escaped using a backslash.
In Groovy, you could also use triple single quotes (''') for a multiline String, which could also be just a single line, or triple double quotes (""") for a multiline GString, which could also be just a single line.
Inside triple quotes, you can again use single quotes without escaping.
Have a look at https://groovy-lang.org/syntax.html#all-strings

Thomas 
Reply all
Reply to author
Forward
0 new messages