我在做什么
我正在尝试在javascript中调用一些在页面加载后执行的基本代码。我这样做是为了Selenium。为什么?我听到你在问,这是因为我做了一个简单的等待工具,如果点击或使用webelement导致页面重新加载,它会一直等到页面加载。这个‘工具’简单地使用main的一个线程来尝试webelement,等待它的引用变得陈旧,也等待'onload event‘在javascript中发生。如果这两种情况都发生在某个超时条件之前,那么我知道A: webelement导致页面重新加载,B:我已经适当地等待了页面重新加载。这很有用,因为我可以通过编程来确定给定的webelement是否会导致页面重新加载,只需尝试它并自动等待它。
问题所在
为了做到这一点,我需要在java中运行一个javascript onload事件。我刚接触ScriptEngine,但我研究了java附带的javascript 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),仅允许本地连接。Sep 17,2018 3:59:11 PM org.openqa.selenium.remote.ProtocolHandshake createSession信息:检测到的方言: OSS sendKeys[ChromeDriver: XP上的chrome (1c2e7600f13bc56ff3b60f9a2de6ee93) ->名称: q][Ljava.lang.CharSequence;@6dd2f3a9页面静态提交[ChromeDriver: XP上的chrome (1c2e7600f13bc56ff3b60f9a2de6ee93) ->名称:q]空
javascript failed
javax.script.ScriptException: ReferenceError:"window“未在>第1行处定义
重新加载的页面
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) at jdk.scripting.nashorn/由::1 java.base/java.lang.Thread.run(Thread.java:844)引起的窗口在java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)处的窗口:“ReferenceError”未在java.base/java.lang.Thread.run(Thread.java:844)中定义at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319) 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)在jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:655) at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.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缺乏经验。
发布于 2018-09-18 08:09:28
ScriptEngineManager
只能在JVM中执行javascript,不能在浏览器中执行。
但“window”在浏览器中是全局变量,而不是在JVM中。这就是为什么你会得到window is undefined.
在浏览器中执行javascript需要使用executeScript()
Selenium api。
String script = "window.addEventListener('load', function() {" +
" alert('ok'); " +
"})";
JavascriptExecutor js =(JavascriptExecutor)driver;
js.executeScript(script);
https://stackoverflow.com/questions/52375302
复制相似问题