"window"未在java中为Selenium定义ScriptEngine



我在做什么

我试图在javascript中调用一些在页面加载后执行的基本内容。我这样做是为了硒。为什么?我听到你问,这是因为我正在制作一个简单的等待工具,如果点击或以其他方式"使用"网络元素会导致所述页面重新加载,它会等待页面加载。这个"工具"只是使用main的一个线程来尝试web元素,等待它的引用过时,还等待javascript中发生"onload事件"。如果这两件事都发生在某个超时条件之前,那么我知道A:web元素导致页面重新加载,B:我已经适当地等待页面重新加载。这很有用,因为我可以通过程序确定给定的网络元素是否会导致页面重新加载,只需尝试并自动等待

问题

为了做到这一点,我需要在java中运行一个javascript onload事件。我是javascript的新手,但我研究了java附带的ScriptEngine API。我决定使用它,并尝试在onload事件发生时运行一个简单的javascript函数。问题是我一直得到一个"窗口"没有定义的异常。由于我用来运行javascript的ScriptEngine对象只接收我正在运行的字符串,所以我无法很好地检查错误。

我尝试过的

我试着研究关于这个错误的文档,并在谷歌上搜索堆栈溢出,但我似乎找不到以java为中心的答案,也找不到一个能很好地解释它的答案。我从研究中了解到,我可能需要指定一个URL作为窗口对象或其他什么,但其他来源让我相信,如果我使用的是浏览器窗口,那么应该已经定义了窗口对象。我不知道该相信什么。有问题的代码是:

WebDriverWait wait = new WebDriverWait(driver, timeoutSeconds);
//initialize a wait for a page to reload
try {
//wait untill our element we clicked is stale
wait.until(ExpectedConditions.stalenessOf(webElement));
//try running javascript to do something (here i tried a popup)
//later I want this code to wait until the page is loaded and
//then send something BACK to the javacode that I can wait for
//so that Basically I wait until the page onload event has fired
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine javascript = manager.getEngineByName("javascript");
try {
javascript.eval("window.addEventListener('load', function() 
{" +
" alert(ok); " +
"})");
} catch (ScriptException e) {
e.printStackTrace();
System.out.println("javascript thing failed");
}
} catch (TimeoutException e) {
//page remained static and webelement doesn't cause a page 
//reload
}

请注意,此代码位于与main并行运行的线程内。简单的目的是等待,直到我们单击的元素过时,页面加载事件被触发。如果这两件事都没有发生,那么我们单击的web元素不会导致页面重新加载。如果元素变得陈旧,我们知道元素发生了更改,但页面不会重新加载。如果这两种情况都发生了,那么我们知道web元素会重新加载页面。一切都在等待中,下一个web元素就可以找到了。这对Selenium很有用,因为我不必担心页面重新加载或元素本身删除但不重新加载页面,也不必担心任何其他奇怪的边缘情况,这些情况可能会导致在不应该的时候抛出StaleReference异常

启动ChromeDriver 2.41.578737端口30355上的(49da6702b16031c40d63e5618de03a32ff6c197e)仅本地允许连接。2018年9月17日下午3:59:11org.openqa.selenium.remote.Protocol握手创建会话信息:检测到的方言:OSS sendKeys[[ChromeDriver:XP上的chrome(1c2e7600f13bc56ff3b60f9a2de6ee93)]->名称:q] [Ljava.lang.CharSequence;@6dd2f3a9页面是静态的提交[[ChromeDriver:XP上的chrome(1c2e7600f13bc56ff3b60f9a2de6ee93)]->name:q]空

javascript东西失败

javax.script.ScriptException:ReferenceError:"window"未在>中的第1行中定义

页面已重新加载

在jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.sthrowAsScriptException(NashornSScriptEngine.java:469)在jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornSscriptEngine.java:453)在jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornSscriptEngine.java:405)在jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornSscriptEngine.java:401)在jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornSscriptEngine.java:154)在java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)在SeleniumTest.isPageReloaded.run(isPageReloaded.java:48)java.base/java.lang.Thread.run(Thread.java:844)由以下原因引起:1ReferenceError:未在定义"窗口"jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)在jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319)在jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291)在jdk.scripting.nashorn/jdk.nashorn.internal.objects.Global.noSuchProperty(Global.java:1615)在jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$重新编译$1$\^eval_/13394969414.:程序(:1)在jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.ioke(ScriptFunctionData.java:655)在jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.ioke(ScriptFunction.java:513)在jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:527)在jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornSscriptEngine.java:448)…还有6个

进程已完成,退出代码为0

附加说明

请注意stacktrace中的粗体行,这些是我添加的内容,以便在某些错误状态下打印。在正常情况下,"页面重新加载消息"也会打印为状态消息。它反映了代码的if-else状态。javascript失败是为了捕捉javascript异常,并更明显地看到它确实失败了。我只想知道我应该做些什么来定义窗口,这样这个javascript代码(以及未来的js代码)就会为我运行。考虑到我对java有经验,但对javascript没有经验。

ScriptEngineManager仅在JVM中执行javascript,而不在浏览器中执行。

但"窗口"是浏览器中的全局变量,而不是JVM中的。这就是为什么你得到window is undefined.

您应该使用executeScript()Selenium api在浏览器中执行javascript。

String script = "window.addEventListener('load', function() {" +
"  alert('ok'); " +
"})";
JavascriptExecutor js =(JavascriptExecutor)driver;
js.executeScript(script);

最新更新