How To…Selenium Execute JavaScript

Each month on the first Tuesday of the month, we will post a new blog post to take you through a step-by-step guide on how to address a particular aspect of a tool, platform or device that you might need to address in your testing. This part of the series focuses on how to execute JavaScript in Selenium.

You will find different aspects of Selenium that you might need to cover as part of your testing in previous posts below.

Find the previous posts here:

How To…Select Elements In Selenium WebDriver Scripts

How To…Use Explicit Waits In Selenium WebDriver

How To…Manage Exceptions In Selenium WebDriver

How To…take Screenshots in Selenium

How To…Interact with sliders in Selenium

How to…Interact with Modal Windows

How to…Use Expected Conditions

How To..Find Elements

———————————————————————————————————————————————

WebDriver tests need to be executed in multiple browsers.

And sometimes, you get different results.

The test may work correctly in Firefox but not work in Chrome or IE.

What do you do in this case?

Changing the locator may work.

Executing JavaScript may work as well.

Let’s investigate how to execute JavaScript in Selenium in this article.

What can you do with JavaScript?

You can do with JavaScript pretty much everything you can do through the WebDriver library:

  • click an element
  • type a keyword in a textbox
  • select an option from a listbox
  • get the value of an element
  • find an element

But JavaScript allows you also to do other things such as modify web elements by changing their color, or font size.

Or even removing them from the page.

How to Execute JavaScript in Selenium

Lets start with a simple example:

public class TestClass {

WebDriver driver;
By searchTextBoxLocator = By.id("globalQuery");
By searchButtonLocator = By.xpath("//input[@class='search_button']");
By firstResultLocator = By.xpath("(//a[@testid='bib_link'])[1]");
By resultTitleLocator = By.id("item_bib_title");

@Before
public void setUp(){
System.setProperty("webdriver.chrome.driver",
"C:\\Selenium\\BrowserDrivers\\chromedriver.exe");

driver = new ChromeDriver();
}

@After
public void tearDown(){
driver.quit();
}

@Test
public void testWithSelenium()
{
driver.get("http://www.vpl.ca");

WebElement searchField;
searchField = driver.findElement(searchTextBoxLocator);
searchField.click();
searchField.sendKeys("java");

WebElement searchButton;
searchButton = driver.findElement(searchButtonLocator);
searchButton.click();

delay(5);

WebElement searchResultLink;
searchResultLink = driver.findElement(firstResultLocator);
searchResultLink.click();

delay(5);

WebElement bookTitleElement;
bookTitleElement = driver.findElement(resultTitleLocator);
String bookTitleValue;
bookTitleValue = bookTitleElement.getText();
assertTrue(bookTitleElement.isDisplayed() == true);
assertTrue(bookTitleValue.length() > 0);

}

The test script is very simple and it does the following:

  1. opens the site
  2. execute a keyword search
  3. click on the 1st result from the results page
  4. checks if the book element is displayed in the details page
  5. checks if the book value is not empty on the details page
Info

Lets re-write it and use JavaScript instead of WebDriver methods:

public class TestClass {

WebDriver driver;
JavascriptExecutor jsExecutor;

@Before
public void setUp(){
System.setProperty("webdriver.chrome.driver",
"C:\\Selenium\\BrowserDrivers\\chromedriver.exe");

driver = new ChromeDriver();
jsExecutor = (JavascriptExecutor) driver;
}

@After
public void tearDown(){
driver.quit();
}

@Test
public void testWithJavaScript(){

driver.get("http://www.vpl.ca");

//type a keyword in the search text box

String typeKeywordJS;
typeKeywordJS =
"document.getElementById('globalQuery').value='java'";

jsExecutor.executeScript(typeKeywordJS);

//click the search button

String clickSearchButtonJS;
clickSearchButtonJS =
"document.querySelector(\"[class='search_button']\")" +
".click()";

jsExecutor.executeScript(clickSearchButtonJS);

delay(5);

//click the 1st result from the results page

String clickFirstResultJS;
clickFirstResultJS =
"document.querySelector(\"a[testid='bib_link']\")" +
".click()";

jsExecutor.executeScript(clickFirstResultJS);

delay(5);

//gets the book title value from the details page

String getTitleValueJS = "function getTitle() {" +
"var title=document.getElementById('item_bib_title')" +
".innerHTML;"+
"return title; }; "+
"return getTitle()";

String bookTitleValue;
bookTitleValue =
(String)jsExecutor.executeScript(getTitleValueJS);

System.out.println(bookTitleValue.trim());
assertTrue(bookTitleValue.length() > 0);

//gets the book element from the details page

String getTitleElementJS = "function getTitleElement(){"+
"var title = document.getElementById('item_bib_title');"+
"return title; };"+
"return getTitleElement()";

WebElement bookTitleElement = (WebElement)jsExecutor
.executeScript(getTitleElementJS);

assertTrue(bookTitleElement.isDisplayed() == true);
System.out.println(bookTitleElement.getText());
System.out.println(bookTitleElement.getTagName());

}

How easy was this?

Every time I wanted to execute a JavaScript query, I would do 2 things

  • prepare the JavaScript query in a String variable
  • execute it with a JavaScript Executor

The JavaScript queries that interact with a web element are very simple.

But if the JavaScript query returns a value that you need in the test method, the JavaScript query needs to include a return statement.

Like in this example:

String getTitleElementJS="function getTitleElement(){"+
" var title = document.getElementById('item_bib_title');"+
" return title; }; "+
" return getTitleElement()";

When executing the JavaScriptt query, the result of the query should be casted to the type of expected result.

The previous query returns an element so the result of the executeScript() method is casted with (WebElement):

WebElement bookTitleElement =
(WebElement)jsExecutor.executeScript(getTitleElementJS);

Info

 

What else can we do with JavaScript?

We can highlight elements before interacting with them:

String jsQuery =
String.format("%s.style.backgroundColor='red'", locator);

jsExecutor.executeScript(jsQuery);

And we can wait until the whole page is loaded:

private void waitUntilPageLoaded(){
Boolean isLoaded = false;
while (!isLoaded) {
isLoaded = isPageLoaded();
delay(1);
}
}

private Boolean isPageLoaded(){
String jsQuery = "function pageLoaded() "
+ "{var loadingStatus=(document.readyState=='complete');
+ "return loadingStatus;};"
+ "return pageLoaded()";

return (Boolean)jsExecutor.executeScript(jsQuery);
}

See below the complete code:

String searchKeywordJSLocator =
"document.getElementById('globalQuery')";

String searchButtonJSLocator =
"document.querySelector(\"[class='search_button']\")";

String firstResultJSLocator =
"document.querySelector(\"a[testid='bib_link']\")";

String resultTitleJSLocator =
"document.getElementById('item_bib_title')";

@Test
public void testWithJavaScript(){

driver.get("http://www.vpl.ca");

waitUntilPageLoaded();

highlightElement(searchKeywordJSLocator);
typeJS(searchKeywordJSLocator, "java");

highlightElement(searchButtonJSLocator);
clickJS(searchButtonJSLocator);

waitUntilPageLoaded();

highlightElement(firstResultJSLocator);
clickJS(firstResultJSLocator);

waitUntilPageLoaded();

String bookTitleValue = getValueJS(resultTitleJSLocator);
assertTrue(bookTitleValue.length() > 0);

highlightElement(resultTitleJSLocator);

WebElement bookTitleElement =
getElementJS(resultTitleJSLocator);

assertTrue(bookTitleElement.isDisplayed() == true);

}

private void highlightElement(String locator){
String jsQuery =
String.format("%s.style.backgroundColor='red'", locator);

jsExecutor.executeScript(jsQuery);
}

private void typeJS(String locator, String keyword){
String jsQuery =
String.format("%s.value='%s'", locator, keyword);

jsExecutor.executeScript(jsQuery);
}

private void clickJS(String locator){
String jsQuery = String.format("%s.click()", locator);

jsExecutor.executeScript(jsQuery);
}

private String getValueJS(String locator){

String jsQuery =
String.format("function getValue() "
+ "{var value=%s.innerHTML;return value;};"
+ "return getValue()", locator);

String value = (String) jsExecutor
.executeScript(jsQuery);

return value;
}

private WebElement getElementJS(String locator){

String jsQuery =
String.format("function getElement()" +
"{var element = %s; return element; }; "
+ "return getElement()", locator);

WebElement element =
(WebElement) jsExecutor.executeScript(jsQuery);

return element;
}

private void delay(int seconds){
Thread.sleep(seconds * 1000);
}

private void waitUntilPageLoaded(){
Boolean isLoaded = false;
while (!isLoaded) {
isLoaded = isPageLoaded();
delay(1);
}
}

private Boolean isPageLoaded(){
String jsQuery = "function pageLoaded() "
+ "{var loadingStatus = "
+ (document.readyState == 'complete');"
+ "return loadingStatus; }; "
+ "return pageLoaded()";

return (Boolean)jsExecutor
.executeScript(jsQuery);
}
}


I hope this guide on how to execute JavaScript in Selenium helps you with your testing.

 

See more articles in the How To Selenium Series

About the Author

Alex

Software Tester from Vancouver, Canada. Blogs on test automation topics for manual testers on http://test-able.blogspot.ca When not testing or creating test automation scripts for my clients, I teach manual testers programming with Java and test automation with Selenium WebDriver.
Find out more about @alexsiminiuc

Related Content