【问题标题】:"window" is not defined ScriptEngine in java for Selenium“窗口”未在 Java 中为 Selenium 定义 ScriptEngine
【发布时间】:2019-02-21 19:47:28
【问题描述】:

我在做什么

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

问题

为了做到这一点,我需要在 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 事件。如果这两件事都没有发生,那么我们单击的 web 元素不会导致页面重新加载。如果元素变得陈旧,我们知道元素发生了变化,但页面不会重新加载。如果这两种情况都发生了,那么我们就知道 web 元素会重新加载页面。一切都在适当地等待,并且准备好找到下一个 web 元素。这对 Selenium 很有用,因为我不必担心页面重新加载或删除自身但不重新加载页面的元素或任何其他可能导致 StaleReference 异常在不应出现时抛出的奇怪边缘情况。现在运行这段代码会返回这个堆栈跟踪:

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

javascript 失败

javax.script.ScriptException: ReferenceError: "window" is not defined in >at line number 1

页面重新加载

在 jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:469) 在 jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:453) 在 jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:405) 在 jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:401) 在 jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.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) 原因::1 ReferenceError:“窗口”未定义在 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_/1394969414.:program(:1) 在 jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:655) 在 jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) 在 jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:527) 在 jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:448) ... 6 更多

进程以退出代码 0 结束

附加说明

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

【问题讨论】:

    标签: javascript java selenium onload nashorn


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-01
      • 2019-07-01
      • 2021-02-02
      • 2016-07-24
      • 1970-01-01
      • 2021-10-06
      • 2019-06-03
      • 2021-01-15
      相关资源
      最近更新 更多