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
———————————————————————————————————————————————
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 <strong>setUp()</strong>{ System.setProperty("webdriver.chrome.driver", "C:\Selenium\BrowserDrivers\chromedriver.exe"); driver = new ChromeDriver(); } @After public void <strong>tearDown</strong>(){ driver.quit(); } <a class='bp-suggestions-mention' href='https://huddle.eurostarsoftwaretesting.com/members/test/' rel='nofollow'>@Test</a> public void <strong>testWithSelenium</strong>() { 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:
- opens the site
- execute a keyword search
- click on the 1st result from the results page
- checks if the book element is displayed in the details page
- checks if the book value is not empty on the details page
Lets re-write it and use JavaScript instead of WebDriver methods:
public class TestClass { WebDriver driver; JavascriptExecutor jsExecutor; @Before public void <strong>setUp</strong>(){ System.setProperty("webdriver.chrome.driver", "C:\Selenium\BrowserDrivers\chromedriver.exe"); driver = new ChromeDriver(); jsExecutor = (JavascriptExecutor) driver; } @After public void <strong>tearDown</strong>(){ driver.quit(); } <a class='bp-suggestions-mention' href='https://huddle.eurostarsoftwaretesting.com/members/test/' rel='nofollow'>@Test</a> public void <strong>testWithJavaScript</strong>(){ driver.get("http://www.vpl.ca"); <strong>//type a keyword in the search text box</strong> String typeKeywordJS; typeKeywordJS = "document.getElementById('globalQuery').value='java'"; jsExecutor.executeScript(typeKeywordJS); <strong>//click the search button</strong> String clickSearchButtonJS; clickSearchButtonJS = "document.querySelector(\"[class='search_button']\")" + ".click()"; jsExecutor.executeScript(clickSearchButtonJS); delay(5); <strong>//click the 1st result from the results page</strong> String clickFirstResultJS; clickFirstResultJS = "document.querySelector(\"a[testid='bib_link']\")" + ".click()"; jsExecutor.executeScript(clickFirstResultJS); delay(5); <strong>//gets the book title value from the details page</strong> 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); <strong>//gets the book element from the details page</strong> 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); <a href="https://katalon.com/resources-center/discover/eurostarhuddle_banner/survival-tips-for-software-testers?utm_source=eurostar_huddle&utm_medium=bannerads&utm_campaign=recommendedtrackviapf&utm_content=728x90&pf=true_foroverlay" class="related_ebook_ad" ><img data-interchange="[ https://huddle.eurostarsoftwaretesting.com/wp-content/uploads/2024/09/Katalon-Ad-resized-336x280-1.jpg , small], [ https://huddle.eurostarsoftwaretesting.com/wp-content/uploads/2024/09/Katalon-Ad-Resized-728x90-1.jpg, medium]" alt="Info" /></a>
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 <strong>waitUntilPageLoaded</strong>(){ Boolean isLoaded = false; while (!isLoaded) { isLoaded = isPageLoaded(); delay(1); } } private Boolean <strong>isPageLoaded</strong>(){ 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')"; <a class='bp-suggestions-mention' href='https://huddle.eurostarsoftwaretesting.com/members/test/' rel='nofollow'>@Test</a> public void <strong>testWithJavaScript</strong>(){ 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 <strong>highlightElement</strong>(String locator){ String jsQuery = String.format("%s.style.backgroundColor='red'", locator); jsExecutor.executeScript(jsQuery); } private void <strong>typeJS</strong>(String locator, String keyword){ String jsQuery = String.format("%s.value='%s'", locator, keyword); jsExecutor.executeScript(jsQuery); } private void <strong>clickJS</strong>(String locator){ String jsQuery = String.format("%s.click()", locator); jsExecutor.executeScript(jsQuery); } private String <strong>getValueJS</strong>(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 <strong>getElementJS</strong>(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 <strong>delay</strong>(int seconds){ Thread.sleep(seconds * 1000); } private void <strong>waitUntilPageLoaded</strong>(){ Boolean isLoaded = false; while (!isLoaded) { isLoaded = isPageLoaded(); delay(1); } } private Boolean <strong>isPageLoaded</strong>(){ 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.