JavaScript & Selenium WebDriver With Example

What is JavaScript?

JavaScript is a powerful client-side scripting language. Nowadays, most web applications use JavaScript because of its lightweight nature to enhance user interaction with the web page and to make dynamic web pages.

How to Run JavaScript?

As JavaScript is a scripting language, it can not run independently. To run the script, you need a web browser. When a user requests an HTML page with JavaScript, the script is sent to the browser, and when a user interacts with the script, the particular will get executed.

How can we execute Java script manually using a browser?

Nowadays, all browser supports JavaScript. So we can run the JavaScript in any browser by following the below steps:

  • Open any browser
  • I reached the console tab by pressing the F12 key or right-clicking and selecting inspect.
  • Type the Java Script in the console tab and hit enter to run the Java Script.

Add Java Screenshot

How does JavaScript help in Automation Testing?

When performing automation testing using Selenium Webdriver for some scenarios, elements are not performing as expected. In such cases, we can take the help of Java Script to deal with such situations:

  • Sometimes, nested elements are not accessible in Selenium webdriver. For example, if an element is present in a tag like a label or div on which Selenium webdriver cannot click in that case, you can use JavaScript.
  • You can also interact with calendars, Scrolling, Handling Hidden elements, and Drag & drop operations.

How to Execute Java Script Using Selenium?

Execute the Java Script’s selenium Webdriver given an interface, “JavascriptExecutor,” with two methods. That is:

Object executeScript(String arg0, Object arg1);
Object executeAsyncScript(String arg0, Object arg1);

By using two methods in our automation script, we can execute the Java Scripts. While explaining the Selenium WebDriver hierarchy, we have mentioned RemoteWebDriver, which implements the JavascriptExecutor. And all the web browser classes extend the RemoteWebDriver. So, using any browser driver, we can execute the Java Script command.

Let us See a Simple Program:

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class JavaScriptInSelenium 
{
   public static void main(String[] args) 
   {
      System.setProperty("webdriver.chrome.driver","./exefiles/chromedriver.exe");
      WebDriver driver= new ChromeDriver();

      driver.manage().window().maximize();

      JavascriptExecutor js= (JavascriptExecutor)driver;
      js.executeScript("console.log('Hello.');");

      driver.get("https://www.softwaretestingo.com/");
   }
}

Note: In most of the interviews, you may face a question regarding the below statement

JavascriptExecutor js= (JavascriptExecutor)driver;

Explanation: Here, we downcast the driver interface to JavascriptExecutor to execute the Java Script because the WebDriver interface has no visibility of JavascriptExecutor interface methods. So, to execute the Java scripts command, we have downcast the driver.

We can also use the Java scripts without downcast the driver instance if we are:

  • Create a Browser class driver: For example, if we are creating an instance of chromedriver class, then, in this case, we don’t need to downcast because chromedriver has extended RemoteWebDriver, which implements JavascriptExecutor methods. So ChromeDriver has indirect access to those methods.
import org.openqa.selenium.chrome.ChromeDriver;
public class JavaScriptInSelenium
{
   public static void main(String[] args)
   {
      System.setProperty("webdriver.chrome.driver","./exefiles/chromedriver.exe");
      ChromeDriver driver= new ChromeDriver();
      driver.manage().window().maximize();
      driver.executeScript("console.log('Hello.');");
      driver.get("http://www.softwaretestingo.com/");
   }
}
  • Create a Browser class object and Upcast to RemoteWebDriver
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public class JavaScriptInSelenium
{
   public static void main(String[] args)
   {
      System.setProperty("webdriver.chrome.driver","./exefiles/chromedriver.exe");
      RemoteWebDriver driver= new ChromeDriver();
      driver.manage().window().maximize();
      driver.executeScript("console.log('Hello.');");
      driver.get("http://www.softwaretestingo.com/");
   }
}

executeScript() In details

Syntax: java.lang.Object executeScript(java.lang.String script,java.lang.Object… args)

  • Script command which you want to run in the form of String. It is mandatory.
  • An array of arguments. It is optional. It is the same as we have in the main() method of the Java program. These arguments will be used in the Java Script command.
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public class JavaScriptInSelenium
{
   public static void main(String[] args)
   {
      System.setProperty("webdriver.chrome.driver","./exefiles/chromedriver.exe");
      ChromeDriver driver= new ChromeDriver();
      driver.manage().window().maximize();
      driver.executeScript("console.log('Hello '+arguments[0] +' Welcome to '+arguments[1]);","User","SoftwareTestingo");
   }
}

If we saw the method described on the official website, we found that:

Executes JavaScript in the context of the currently selected frame or window. The script fragment provided will be executed as the body of an anonymous function.

That means when we write the below statement:

driver.executeScript(“console.log(‘Hello.’);”);

Then selenium will execute the above Java script like:

function()
{
   console.log("Hello");
}

Return Type of executeScript() method

If the script has a return value (i.e., if the script contains a return statement), then the following steps will be taken:

  • For an HTML element, this method returns a WebElement
  • For a decimal, a Double is returned
  • For a non-decimal number, a Long is returned
  • For a boolean, a Boolean is returned
  • For all other cases, a String is returned.
  • For an array, return a List<Object> with each object following the rules above
  • . We support nested lists.
  • For a map, return a Map<String, Object> with values following the rules above.

Unless the value is null or there is no return value in which null is returned, Arguments must be a number, a boolean, a String, WebElement, or a List of any combination of the above. An exception will be thrown if the arguments do not meet these criteria.

Example:

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public class JavaScriptInSelenium
{
   public static void main(String[] args)
   {
      System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
      ChromeDriver driver = new ChromeDriver();
      driver.manage().window().maximize();
      Object response = driver.executeScript("return 1===2");
      System.out.println(response);
   }
}

executeAsyncScript()

Let us understand the difference between Synchronous and asynchronous. In simple words, Synchronous represents Blocking, and Asynchronous represents Non-blocking.

Let us discuss this in detail. If a program is executed line by line, that’s called synchronous programming. Until the first line execution is completed, the second line will not be executed. But in asynchronous programming, all the lines start the execution at a time, and it does not block any other lines from being executed; every asynchronous piece of code signals when execution is done. The signal is called a callback.

Example:

  • Java is the synchronous programming language
  • NodeJS is an Asynchronous programming language

Syntax of executeAsyncScript

java.lang.Object executeAsyncScript(java.lang.String script, java.lang.Object… args)

If you see the official site for the method description:

Execute an asynchronous piece of JavaScript in the currently selected frame or window context. Unlike executing synchronous Java Script, scripts executed with this method must explicitly signal they are finished by invoking the provided callback. This callback is always injected into the executed function as the last argument.

Lets execute the below Java script command

window.setTimeout(arguments[arguments. length – 1], 5000);

Arguments [arguments.length – 1] is a callback function. We must get the length and minus one to get the last arguments. This method calls the function to execute after 5 seconds.

Example:

import java.util.Date;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.chrome.ChromeDriver;
public class ExecuteAsynJavascriptCommandsInSelenium
{
   public static void main(String[] args)
   {
      System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
      ChromeDriver driver = new ChromeDriver();
      driver.manage().window().maximize();
      System.out.println("Start time: " + new Date());
      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js= (JavascriptExecutor)driver;
      js.executeAsyncScript("window.setTimeout(arguments[arguments.length - 1], 5000);");
      System.out.println("End time: " + new Date());
      driver.quit();
   }
}

You can see execution control waiting until the JavaScript function is executed completely and signaled. This happened because we let JVM know we were executing an async code and waiting for function callbacks.

What will happen if we execute async code through the executeScript method?

import java.util.Date;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.chrome.ChromeDriver;
public class ExecuteAsynJavascriptCommandsInSelenium
{
   public static void main(String[] args)
   {
      System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
      ChromeDriver driver = new ChromeDriver();
      driver.manage().window().maximize();
      System.out.println("Start time: " + new Date());
      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js= (JavascriptExecutor)driver;
      js.executeScript("window.setTimeout(arguments[arguments.length - 1], 5000);");
      System.out.println("End time: " + new Date());
      driver.quit();
   }
}

This time, execution control does not wait because JVM does not know about it. This is the reason to execute an asynchronous piece of code, and we need to use executeAsyncScript.

We have discussed various locators presented in Selenium WebDriver, like ID, Name, Classname, TagName, XPath, and CSSSelector. But when we try to locate some elements in an application, those elements are not identifiable because of reasons like an element being hidden, an element being deeply nested, or a web application having lots of AJAX calls. Java Script helps locate the elements.

How to Locate Element Using JavaScript?

In JavaScript, we have a set of commands; by using those commands, we can easily locate the elements of a web page; those are:

  • getElementById
  • getElementsByClassName
  • getElementsByName
  • getElementsByTagName

getElementById Example

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public class JavaScriptInSelenium 
{
   public static void main(String[] args) 
   {

      System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
      WebDriver driver = new ChromeDriver();

      driver.manage().window().maximize();

      driver.get("https://www.makemytrip.com/");

      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js= (JavascriptExecutor)driver;

      // Down casting to WebElement because executeScript return a type of Object
      WebElement element= (WebElement) js.executeScript("return document.getElementById('searchBtn')");

      // Getting text
      String text= element.getText();
      System.out.println("Text: "+text);
   }
}

getElementsByClassName Example

import java.util.List;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public class JavaScriptInSelenium 
{
   public static void main(String[] args) 
   {
      System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
      WebDriver driver = new ChromeDriver();

      driver.manage().window().maximize();
      driver.get("https://www.makemytrip.com/");

      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js= (JavascriptExecutor)driver;

      // Down casting to List<WebElement> because executeScript return a type of Object
      List<WebElement> element= (List<WebElement>) js.executeScript("return document.getElementsByClassName('non-pot')");

      // Getting text
      System.out.println(element.size());
   }
}

Apart from locating the elements of a web page, we can do other operations using JavaScript.

  • Scroll a WebPage
  • Take a Screenshot Of the Entire page.
  • Giving Input to a Text Box
  • Handle Hidden Element
  • Handle Calendar

Taking a Screenshot Of the Entire page

In our other post regarding the Taking Screenshot, we saw that when we try to capture the screenshot with Selenium WebDriver and TakesScreenshot interface, we can take the screenshot of the only visible part of the browser, not the full page. So, to capture the full-page screenshot, we can use the help of Java Script.

import java.io.File;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class CaptureFullWebPage 
{

   public static String CaptureScreenShotWithTestStepName(WebDriver driver, String testStepsName)
   {
      try{
         // down casting WebDriver to use getScreenshotAs method.
         TakesScreenshot ts= (TakesScreenshot)driver;
         // capturing screen shot as output type file
         File screenshotSRC= ts.getScreenshotAs(OutputType.FILE);
         // Defining path and extension of image
         String path=System.getProperty("user.dir")+"/ScreenCapturesPNG/"+testStepsName+System.currentTimeMillis()+".png";
         // copying file from temp folder to desired location
         File screenshotDest= new File(path);
         FileUtils.copyFile(screenshotSRC, screenshotDest);
         return path;
      }
      catch(Exception e)
      {
         System.out.println("Some exception occured." + e.getMessage());
         return "";
      }
   }
   public static void main(String[] args) throws InterruptedException
   {
      System.setProperty("webdriver.chrome.driver", "./exefiles/chromedriver.exe");
      WebDriver driver = new ChromeDriver();

      driver.manage().window().maximize();
      driver.get("http://www.softwaretestingo.com/");

      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js = (JavascriptExecutor) driver;

      // It returns height of view part. You can say it as page height. When you click on page down key
      // Page scroll by one page.
      long pageHeight= (long)js.executeScript("return window.innerHeight");
      System.out.println("Page height: "+pageHeight);

      // It is how much you can scroll. It is height if you scroll, you will reach to bottom of page.
      long scrollableHeight= (long)js.executeScript("return document.body.scrollHeight");
      System.out.println("Total scrollable height: "+scrollableHeight);

      // Finding number of pages. Adding 1 extra to consider decimal part.
      int numberOfPages=(int) (scrollableHeight/pageHeight)+1;
      System.out.println("Total pages: "+numberOfPages);

      // Now scrolling page by page
      for(int i=0;i<numberOfPages;i++)
      {
         CaptureFullWebPage.CaptureScreenShotWithTestStepName(driver, "Page "+(i+1));
         js.executeScript("window.scrollBy(0,"+pageHeight+")");
         Thread.sleep(2000);
      }
   }
}

Giving Input to a Text Box

For Sending any input to a text box, we always use the sendkeys() method, but we can also achieve the same things with Java Script.

When you check the HTML DOm structure of any HTML Element, you will find an attribute called “Value,” which holds the current value of that element.

For example, there is a text box for FirstName, and you enter “SoftwareTestingo,” and then the value attributed is updated from “Value” to “Value=SoftwareTestingo.”

So, when we cannot enter that value in the text box, we can update the value attribute with the required input so that the same value will also be reflected in the text box.

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class TypeUsingJavascript 
{
   public static void main(String[] args) 
   {

      System.setProperty("webdriver.chrome.driver","./exefiles/chromedriver.exe");
      WebDriver driver= new ChromeDriver();

      driver.manage().window().maximize();
      driver.get("https://www.google.com/");

      WebElement searchBox= driver.findElement(By.name("q"));

      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js = (JavascriptExecutor) driver;

      // Setting value for "value" attribute
      js.executeScript("arguments[0].value='selenium'", searchBox);
   }
}

Handle Hidden Element

Sometimes, you can say some elements are hidden on a web page. In that case, you can also use the help of Javascript. Using Javascript, we can change the value of an attribute of a web element to make it visible and do the required operation.

import java.io.IOException;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class TypeIntoHiddenElement 
{
   public static void main(String[] args) throws IOException 
   {
      System.setProperty("webdriver.chrome.driver","./exefiles/chromedriver.exe");
      WebDriver driver= new ChromeDriver();

      driver.manage().window().maximize();
      driver.get("file:///C://Users//amodm//Desktop//NewHidden.html");
      WebElement searchBox= driver.findElement(By.id("files"));

      // Down casting driver to JavascriptExecutor
      JavascriptExecutor js = (JavascriptExecutor) driver;

      // Setting value for "style" attribute to make input tag visible
      js.executeScript("arguments[0].style.display='block';", searchBox);

      searchBox.sendKeys("F:\\Eclipse_WS\\softwaretestingo\\ScreenCapturesPNG\\TypeUsingJS.jpg");
   }
}

Handle Calendar

We have mentioned, for example, how to handle calendar posts. You can check the post.

I love open-source technologies and am very passionate about software development. I like to share my knowledge with others, especially on technology that's why I have given all the examples as simple as possible to understand for beginners. All the code posted on my blog is developed, compiled, and tested in my development environment. If you find any mistakes or bugs, Please drop an email to softwaretestingo.com@gmail.com, or You can join me on Linkedin.

1 thought on “JavaScript & Selenium WebDriver With Example”

Leave a Comment