我试图在页面加载后执行的javascript中调用基本内容。我正在为Selenium这样做。为什么?我听到你问,这是因为我正在制作一个简单的等待工具,等到一个页面加载,如果点击或“使用”一个webelement导致所述页面重新加载。这个'工具'只是使用main的一个线程来尝试webelement,等待它的引用过时,并等待'onload事件'在javascript中发生。如果这些事情都发生在一些超时条件之前,那么我知道A:webelement导致页面重新加载而B:我已经适当地等待页面重新加载。这很有用,因为我可以编程方式确定给定的webelement是否只是通过尝试重新加载页面并自动等待它。
为了做到这一点,我需要在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一起运行的线程内。简单的目的是等到我们单击的元素过时并且触发了页面onload事件。如果这两件事都没有发生,我们点击的webelement不会导致页面重新加载。如果元素变得陈旧,我们知道元素发生了变化,但页面没有重新加载。如果两件事都发生,那么我们就知道webelement会重新加载页面。一切都在适当地等待,下一个webelement就可以找到了。这对Selenium很有用,因为我不必担心页面重新加载或删除自身的元素,但不重新加载页面或任何其他可能导致StaleReference异常抛出的奇怪边缘情况。现在运行此代码块会返回此堆栈跟踪:
在端口30355上启动ChromeDriver 2.41.578737(49da6702b16031c40d63e5618de03a32ff6c197e)仅允许本地连接。 2018年9月17日下午3:59:11 org.openqa.selenium.remote.ProtocolHandshake createSession INFO:检测到的方言:OSS sendKeys [[ChromeDriver:Chrome on XP(1c2e7600f13bc56ff3b60f9a2de6ee93)] - > name:q] [Ljava.lang.CharSequence ; @ 6dd2f3a9页面是静态提交[[ChromeDriver:Chrome on XP(1c2e7600f13bc56ff3b60f9a2de6ee93)] - > name:q] null
javascript的事情失败了
javax.script.ScriptException:ReferenceError:在第1行的>中未定义“window”
页面重新加载
at jdk.scripting.nashorn / jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:469)at jdk.scripting.nashorn / jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:453) at jdk.scripting.nashorn / jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:405)at jdk.scripting.nashorn / jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:401)在seleniumTest.isPageReloaded.run的java.scripting / javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)的jdk.scripting.nashorn / jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:154) (isPageReloaded.java:48)在java.base / java.lang.Thread.run(Thread.java:844)引起的:: 1 ReferenceError:“window”未在jdk.scripting.nashorn / jdk.nashorn中定义。 internal.runtime.ECMAErrors.error(ECMAErrors.java:57)at jdk.scripting.nashorn / jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:3) 19)at jdk.scripting.nashorn / jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291)at jdk.scripting.nashorn / jdk.nashorn.internal.objects.Global.noSuchProperty(Global.java: 1615)at jdk.scripting.nashorn.scripts / jdk.nashorn.internal.scripts.Script $ Recompilation $ 1 $ \ ^ eval_ / 1394969414。:program(:1)at jdk.scripting.nashorn / jdk.nashorn.internal.runtime .ScriptFunctionData.invoke(ScriptFunctionData.java:655),位于jdk.scripting.nashorn / jdk.nashorn.internal.runtime的jdk.scripting.nashorn / jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) .ScriptRuntime.apply(ScriptRuntime.java:527)at jdk.scripting.nashorn / jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:448)... 6更多
进程以退出代码0结束
请注意堆栈跟踪中的粗线,这些是我添加到某些错误状态中打印的内容。 “页面重新加载的消息”也在正常情况下作为状态消息打印。它反映了代码的if else状态。 javascript失败是捕获javascript异常并且更明显地看到它确实失败了。我只是想知道我应该做什么来定义窗口,以便这个javascript代码(和未来的js代码)将为我运行。考虑到我对java有经验但对javascript没有经验。
ScriptEngineManager
只在JVM中执行javascript,而不是在浏览器中执行。
但是'window'是浏览器中的全局变量,而不是JVM中的全局变量。这就是为什么你得到window is undefined.
你应该使用executeScript()
Selenium api在浏览器中执行javascript。
String script = "window.addEventListener('load', function() {" +
" alert('ok'); " +
"})";
JavascriptExecutor js =(JavascriptExecutor)driver;
js.executeScript(script);