Выполнение js.exec в GebSpock заканчивается на «java.lang.Исключение IllegalArgumentException: Последний аргумент функции js должен быть строковым»

#groovy #spock #geb

Вопрос:

У меня есть следующие строки в классе объектов страницы (для работы с Shadow DOM):

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

Однако, когда вы запускаете его в тестах GebSpock, он постоянно терпит неудачу с приведенным ниже исключением:

 |                      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)
...

 

Приведенные выше строки кода переводятся из нижеприведенных кодов с помощью JavascriptExecutor с WebElement, которые просто хорошо работают при выполнении:

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

Должно быть, что-то не так при вызове js.exec в GebSpock.

У кого-нибудь есть какие-либо идеи по этому поводу ? Каков правильный синтаксис передачи параметров js.exec() ?

пс:

     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. В Geb строка 11 имеет тип объекта Navigator. Я попытался передать «headerContent.FirstElement()» в js.exec(). Однако все равно наблюдалось одно и то же исключение. Попробовал также преобразовать его в строковый тип, но он жаловался на символы «- amp;gt » в параметрах и т. Д. Не уверены, поддерживает ли Geb элементы shadow DOM?

Ответ №1:

Я полагаю, что вы поменяли порядок аргументов в js.exec() вызове. На основе Книги Геба:

Объект js также имеет метод exec (), который можно использовать для запуска фрагментов JavaScript. Он идентичен методу JavascriptExecutor.executeScript (), за исключением того, что он принимает свои аргументы в другом порядке…

Пример: assert js.exec(1, 2, "return arguments[0] arguments[1];") == 3

Это должно означать, что это должно устранить вашу проблему:

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

Комментарии:

1. Привет, аспок, большое тебе спасибо за твою помощь ! Да, теперь это работает, когда передаете параметры в другом порядке. Функция js.exec() возвращает значение shadowRoot0 правильно. Однако возвращенный shadowRoot0 становится типом RemoteWebElement. В классе объектов страницы строка » Смена(ожидание:истина) { shadowRoot0.find(«сатурн-меню») } » перестает работать (вызвано: groovy.lang.missingmethod Исключение: Нет подписи метода: org.openqa.selenium.remote. RemoteWebElement.find() ). Есть ли способ перевести его в тип навигатора и продолжать использовать тот же синтаксис поиска Geb в объекте страницы ?

2. Вы можете создать a Navigator из a WebElement , передав его $() методу, доступному в content блоках. Так что в вашем случае это было бы $(js.exec(headerContent.singleElement(), "return arguments[0].shadowRoot"))

3. @Guoping, я предлагаю вам принять правильный ответ здесь, чтобы закрыть вопрос. Он по-прежнему указан как открытый. Это тоже вопрос вежливости. Пожалуйста, нажмите на серую галочку, сделав ее зеленой. Спасибо.