有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javascript“窗口”没有在java中为Selenium定义ScriptEngine

我在做什么

我试图在javascript中调用一些基本的东西,在页面加载后执行。我这么做是为了硒。为什么?我听到你问,这是因为我正在制作一个简单的等待工具,如果点击或“使用”一个webelement导致页面重新加载,它会一直等待直到页面加载。这个“工具”只是使用main的一个线程来尝试webelement,等待它的引用过时,并等待javascript中出现“onload事件”。如果这两件事都发生在某个超时条件之前,那么我知道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异常。现在运行这段代码将返回以下堆栈跟踪:

Starting ChromeDriver 2.41.578737 (49da6702b16031c40d63e5618de03a32ff6c197e) on port 30355 Only local connections are allowed. Sep 17, 2018 3:59:11 PM org.openqa.selenium.remote.ProtocolHandshake createSession INFO: Detected dialect: OSS sendKeys[[ChromeDriver: chrome on XP (1c2e7600f13bc56ff3b60f9a2de6ee93)] -> name: q][Ljava.lang.CharSequence;@6dd2f3a9 page was static submit[[ChromeDriver: chrome on XP (1c2e7600f13bc56ff3b60f9a2de6ee93)] -> name: q]null

javascript thing failed

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

page reloaded

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/jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:154) at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) at SeleniumTest.isPageReloaded.run(isPageReloaded.java:48) at java.base/java.lang.Thread.run(Thread.java:844) Caused by: :1 ReferenceError: "window" is not defined at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57) 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) at 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 more

Process finished with exit code 0

附加说明

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


共 (1) 个答案

  1. # 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);