I executed JavaScript using this advice and I want to return a value from this script.
4 Answers
You can just return the value like this:
Java:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("return document.title");
Python:
driver.execute_script("return document.title")
driver.execute_script("return document.querySelector('.somecssclass')")
3 Comments
window.addEventListener('click', function (e) {return e}, false); I want that event e .JavascriptException in case of error. You can handle asynchronous calls by adding global variables to the window, and then checking on the variable later with another call!I appended the value to be returned using (in .js file):
document.body.innerHTML += '<div style="display:none;" id="some_id">' + value_to_be_returned + '</div>';
and accessed the value in java using (in .java file):
String return_value = (String) js.executeScript("return document.getElementById('some_id').innerHTML");
1 Comment
If the Javascript you want to execute is synchronous then the javascript return value will be assigned to the result of driver.execute_script() method — this is probably what you would expect, and follows the least surprise principle:
from selenium import webdriver
driver = webdriver.Chrome()
# make sure you have a `return` in the js code
js_url = driver.execute_script("return window.location.href")
print(js_url)
For asynchronous calls use driver.execute_async_script:
from selenium import webdriver
driver = webdriver.Chrome()
print(driver.execute_async_script('''
fetch('http://httpbin.org/get')
.then(resp=>resp.json())
.then(data=>{alert(JSON.stringify(data)
)});
'''))
For the specific case of jQuery.ajax() you can also force the call to be synchronous by passing async: false (by default it is asynchronous), for example the following code will return the http response text synchronously:
from selenium import webdriver
driver = webdriver.Chrome()
http_response = driver.execute_script("""
return $.ajax({
url: 'http://httpbin.org/get',
async: false
}).responseText""")
print(http_response)
Comments
For asynchronous I used the following:
result = driver.executeAsyncScript(
"var callback = arguments[arguments.length-1];" +
"$.ajax('someurl').success(function(data){ callback(data); });"
);
1 Comment
alert(...), but this answer actually returns the result of the asynchronous Javascript operation so it's available in your Java/Selenium code! I made a change to use the last argument as the callback (vs the first argument), and to store the value into a Java variable (which demonstrates the power of this approach, as shown here)