I have the following lines in the page object class (to deal with Shadow DOM):

11        headerContent(wait:true) { $("content-header") }
12        shadowRoot0(wait:true) { js.exec("return arguments[0].shadowRoot", headerContent) }

However, when run it in the GebSpock tests, it persistently fails with below exception:

|                      Caused by: java.lang.IllegalArgumentException: The last argument to the js function must be string-like
|                       at geb.js.JavascriptInterface.exec(JavascriptInterface.groovy:53)
|                       at test.ui.modules.RightHandHeader._clinit__closure1$_closure3(RightHandHeader.groovy:12)
...

Above code lines are translated from below codes using JavascriptExecutor with WebElement which just work well when executing:

    WebElement shadowDomHost = driver.findElement(By.cssSelector("content-header"))
    WebElement root0 = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].shadowRoot", shadowDomHost)

There must be something wrong when calling js.exec in GebSpock.

Anyone has any idea about this issue ? What's the correct syntax passing parameters to js.exec() ?

PS:

    def exec(Object[] args) {
        if (args.size() == 0) {
            throw new IllegalArgumentException("there must be a least one argument")
        }

        def script
        def jsArgs
        if (args.size() == 1) {
            script = args[0]
            jsArgs = []
        } else {
            script = args.last()
            jsArgs = args[0..(args.size() - 2)]
        }

        if (!(script instanceof CharSequence)) {
            throw new IllegalArgumentException("The last argument to the js function must be string-like")
        }

        execjs(script.toString(), *jsArgs)
    }
1

There are 1 best solutions below

3
aspok On

I believe you've swapped the order of the arguments in the js.exec() call. Based on the Book of Geb:

The js object also has an exec() method that can be used to run snippets of JavaScript. It is identical to the JavascriptExecutor.executeScript() method, except that it takes its arguments in the other order…

Example: assert js.exec(1, 2, "return arguments[0] + arguments[1];") == 3

This should mean that this should fix your issue:

shadowRoot0 (wait:true) { 
    js.exec(headerContent.singleElement(), "return arguments[0].shadowRoot")
}