I'm trying to call something basic in javascript that executes after a page loads. I'm doing this for Selenium. Why? I hear you asking, it's because I'm making a simple wait tool that waits untill a page is loaded IF clicking or otherwise 'using' a webelement causes said page to reload. This 'tool' simply uses a thread off of main to try the webelement, wait for it's reference to go stale, and also wait for the 'onload event' to occur in javascript. If both those things occur before some timeout condition then I know that A: the webelement causes a page reload and B: I have waited appropriately for the page to reload. This is useful because I can programatically determine wether a given webelement causes a page to reload just by trying it and automatically wait for it.
In order to do this, I need to run a javascript onload event in java. I'm new to javascript but I researched the ScriptEngine API that comes with java. I decided to use that and try to run a simple javascript function when the onload event occurs. The problem is I keep getting a "window" is not defined exception. Since the ScriptEngine Object I'm using to run the javascript only takes in a String of what I'm running I can't really check for errors well.
I've tried researching the documentation on this error and googling around stack overflow but I can't seem to find A java centric answer nor one that explains it well enough for me. All I've gleaned from the research is that I might possibly need to specify a URL as the window object or something but other sources have led me to belive that if I'm using a browser window that the window object should already be defined. I don't know what to beleive. The code in question is:
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
}
Note that this code is inside a thread which runs alongside main. The simple purpose is to wait until the element we click is stale and the page onload event has been fired. If both of those things don't happen, the webelement we clicked doesn't cause the page to reload. If the element becomes stale, we know the element changes but the page doesn't reload. If both things happen then we know the webelement reloads the page. Everything is waited for appropriately and the next webelement is ready to be found. This is useful for Selenium because I don't have to worry about page reloads or elements that delete themselves but don't reload the page or any other weird edge case that might cause StaleReference exceptions to be thrown when they shouldn't be. Right now running this block of code returns this stacktrace:
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
Notice the bold lines in the stacktrace, those are what I added to be printed in some error states. The "page reloaded message" also prints in the normal case as a status message. It reflects the if else state of the code. The javascript failure is to catch the javascript exceptions and see more visibly that it did indeed fail. I just want to know what I should do to get the window defined so that this javascript code (and future js code) will run for me. Take into account that I am experienced with java but inexperienced with javascript.
The ScriptEngineManager
executes javascript in JVM only, not in browser.
But the 'window' is global variable in browser, not in JVM. That's why you get window is undefined.
You should use executeScript()
Selenium api to execute javascript in browser.
String script = "window.addEventListener('load', function() {" +
" alert('ok'); " +
"})";
JavascriptExecutor js =(JavascriptExecutor)driver;
js.executeScript(script);