Post by leiwang on Dec 22, 2016 9:06:23 GMT
SE+ provides APIs:
[li]To execute a Javascript on a certain Component (WebElement) in the context of the currently selected frame or window:[/li]
[/ul]
Before calling Javascript:
There are something we should understand. Such as the parameters of these APIs and how these Java-parameters are passed to Javascript as parameters, it is important! We don't need to understand all of them , the items below are listed by necessity priority:
Examples:
- To execute a Javascript in the context of the currently selected frame or window:
- SeleniumPlus.executeScript()
- SeleniumPlus.executeAsyncScript()
[li]To execute a Javascript on a certain Component (WebElement) in the context of the currently selected frame or window:[/li]
[/ul]
Before calling Javascript:
There are something we should understand. Such as the parameters of these APIs and how these Java-parameters are passed to Javascript as parameters, it is important! We don't need to understand all of them , the items below are listed by necessity priority:
- "Javascript snippet": It is passed in as first parameter for executeScript() and executeAsyncScript(); While it is passed in as second parameter for ExecuteScript().
- "Javascript parameters": They are defined by keyword arguments, so arguments[0], arguments[1] ... can be used in the Javascript snippet. They are passed in as second, third ... parameters of executeScript() and executeAsyncScript(); While for ExecuteScript(), the first parameter Component is arguments[0], and the third parameter is arguments[1], fourth parameter is arguments[2] etc.
- "callback method": It is ONLY for asynchronous invocation executeAsyncScript(), this callback is always injected automatically as the last argument, so it is always arguments[arguments.length - 1]. The Javascript snippet must explicitly signal it is finished by invoking this callback. The first argument passed to the callback function will be used as the script's result. The conversion from Javascript object to Java object definition.
- "script timeout": It is ONLY for asynchronous invocation executeAsyncScript(), the default timeout for a script to be executed is 0ms. In most cases one must set the script timeout beforehand to a value sufficiently large enough by calling setScriptTimeout(long,TimeUnit).
- "debug() method": For synchronous invocation executeScript() and ExecuteScript(), user can call debug(debug-message) in the Javascript snippet to write debug message into SE+ debug log. By default, this functionality is off, user can turn it on by setting JavaScriptFunctions.jsDebugLogEnable=true. Normally the debug message will be written to a file, we can also send debug message to browser's console by setting JavaScriptFunctions.logToBrowserConsole=true.
- "throw_error() method": For synchronous invocation executeScript() and ExecuteScript(), user can call throw_error(error-message) in the Javascript snippet so that a JSException will be thrown out in Java code. Below is how it is normally used in Javascript snippet.
try{
//do some javascript actions
}catch(err){
throw_error(err);
}
- "event listener": Here we are NOT talking about the "event listener" inside Javascript, BUT about the Java listener reacting to the Javascript event. We can call addJavaScriptEventListener(WebElement, eventName, listener) / removeJavaScriptEventListener(WebElement, eventName, listenerID) to add/remove listener. Below is an example how to add a DefaultJSEventListener for "mousedown" event on a WebElement. This DefaultJSEventListener is not public class, it is a protected inner class inside SearchObject, click this link and search "DefaultJSEventListener" to get the source code, you can imitate it to write your own listener.
WebElement webelement = null;//User must assign it with a valid value.
String event = "mousedown";
int timeout = 1000;//milliseconds
DefaultJSEventListener listener = new DefaultJSEventListener(event);
//add listener for event
String listenerID = WDLibrary.addJavaScriptEventListener(webelement, event, listener);
//do some mousedown related work, for example 'click'
webelement.click();
//wait for event happen
if(listener.waitEventFired(timeout)){ //ok, event has been fired.}
//remove the listener
WDLibrary.removeJavaScriptEventListener(webelement, event, listenerID);
Examples:
- SeleniumPlus.executeScript()
//set "your text" to innerHTML of Component Map.Google.SignIn
WebElement we = SeleniumPlus.getObject(Map.Google.SignIn);
String script = "arguments[0].innerHTML=arguments[1];";
List<Object> params = new ArrayList<Object>();
params.add(we);//arguments[0]
params.add("your text");//arguments[1]
SeleniumPlus.executeScript(script, params.toArray(new Object[0]));
//get innerHTML of component Map.Google.SignIn
script = "return arguments[0].innerHTML;";
params.clear();
params.add(we);//arguments[0]
Object result = SeleniumPlus.executeScript(script, params.toArray(new Object[0]));
- SeleniumPlus.executeAsyncScript()
//Example #1: Performing a sleep in the browser under test.
long start = System.currentTimeMillis();
String script = "var callback = arguments[arguments.length - 1];"+
"window.setTimeout(callback, 500);";
SeleniumPlus.executeAsyncScript(script);
System.out.println("Elapsed time: " + System.currentTimeMillis() - start);
//Example #2: Synchronizing a test with an AJAX application:
Click(Map.Mail.ComposeButton);
String script = "var callback = arguments[arguments.length - 1];" +
"mailClient.getComposeWindowWidget().onload(callback);";
Object result = SeleniumPlus.executeAsyncScript(script);
Component.InputCharacters(Map.Mail.To, "bog@example.com");
//Example #3: Injecting a XMLHttpRequest and waiting for the result:
String script = "var callback = arguments[arguments.length - 1];" +
"var xhr = new XMLHttpRequest();" +
"xhr.open('GET', '/resource/data.json', true);" +
"xhr.onreadystatechange = function() {" +
" if (xhr.readyState == 4) {" +
" callback(xhr.responseText);" +
" }" +
"};" +
"xhr.send();";
//Wait result for at the most 5 seconds
WDTimeOut.setScriptTimeout(5, TimeUnit.SECONDS);
Object result = SeleniumPlus.executeAsyncScript(script);
JsonObject json = new JsonParser().parse((String) result);
//Example #4, call REST service to get a result.
try{
WDTimeOut.setScriptTimeout(1, TimeUnit.SECONDS);
JavaScriptFunctions.DEBUG_OUTPUT_JAVASCRIPT_FUNCTIONS = true;
JavaScriptFunctions.setJsDebugLogEnable(true);
String script = "try{ "
+ " var callback = arguments[arguments.length - 1];"
+ " debug('try to get registration service.');"
+ " var service = registry.getRegistrationService();"
+ " if(service==undefined){"
+ " debug('Failed to get service');"
+ " }else{"
+ " debug('we got registration service.'); "
+ " }"
+ " service.get({'user-id': 'administrator'}).done(callback).fail(callback);"
+ "}catch(error){"
+ " debug('we met exception');"
+ " throw_error(error);"
+ "}";
Object results = SeleniumPlus.executeAsyncScript(script);
System.out.println(results);
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
WDTimeOut.resetScriptTimeout(0, TimeUnit.MILLISECONDS);
}
- SeleniumPlus.ExecuteScript()
SeleniumPlus.ExecuteScript(
Map.Google.SignIn, // The WebElement passed as 'arguments[0]' to the script.
"arguments[0].innerHTML=arguments[1];", // Script to set the WebElements innerHTML value.
"my text value"); // The value passed as 'arguments[1]' to set to innerHTML.
SeleniumPlus.ExecuteScript(
Map.Google.SignIn, // The WebElement passed as 'arguments[0]' to the script.
"return arguments[0].innerHTML;"); // A script to return the WebElemenbts innerHTML.
//scriptResult should get the innerHTML value returned.
String scriptResult = SeleniumPlus.prevResults.getStatusInfo();