无法从Karate Feature文件执行JS实现浏览器元素动态等待
Karate中执行JS实现元素动态等待报错问题
我尝试在Karate Feature文件中执行JavaScript,实现浏览器Web元素的动态等待。按照文档说明,我用script方法定义了如下脚本:
* def waitForElementToDisplay = """ function (selector, checkFrequencyInMs, timeoutInMs) { var startTimeInMs = Date.now(); (function loopSearch() { if (document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue != null) { return ; } else { setTimeout(function () { if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs) return; loopSearch(); }, checkFrequencyInMs); } })(); } """
之后我在Feature文件中通过以下代码直接调用该JS函数:
* script(waitForElementToDisplay("//*[text()='Show card number']",1000,10000))
但执行时出现了如下错误:
109 * script(waitForElementToDisplay("//*[text()='Show card number']",1000,10000)) 14:33:22.972 src/test/java/tests/android/imageText.feature:109 * script(waitForElementToDisplay("//*[text()='Show card number']",1000,10000)) js failed: >>>>>> 01: script(waitForElementToDisplay("//*[text()='Show card number']",1000,10000)) <<<<<< org.graalvm.polyglot.PolyglotException: ReferenceError: "document" is not defined - <js>.loopSearch(Unnamed:4) src/test/java/tests/android/imageText.feature:109
问题原因及解决办法
报错document is not defined是因为你写的JS函数跑在Karate的服务器端JS引擎里,根本碰不到浏览器的document对象——Karate的script方法默认是在自身上下文执行代码,不是在浏览器里。
其实Karate本身就有原生的元素等待能力,完全不用自己写JS:
- 最简单的写法,直接等待元素出现:
* waitFor('//*[text()="Show card number"]')
- 要自定义轮询间隔(1000ms)和超时时间(10000ms),先配置再调用:
* configure waitFor = { interval: 1000, timeout: 10000 } * waitFor('//*[text()="Show card number"]')
如果非要用自定义JS逻辑,得把整个函数和调用逻辑作为字符串传给script,让它在浏览器环境里执行,而不是提前定义在Karate的上下文:
* script(""" function waitForElementToDisplay(selector, checkFrequencyInMs, timeoutInMs) { var startTimeInMs = Date.now(); (function loopSearch() { if (document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue != null) { return; } else { setTimeout(function () { if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs) return; loopSearch(); }, checkFrequencyInMs); } })(); } waitForElementToDisplay("//*[text()='Show card number']", 1000, 10000) """)
内容的提问来源于stack exchange,提问作者abdul khan
相关产品推荐
相关产品推荐

