jQuery injection for Selenium Automation tests
Introduction
Selenium WebDriver provides methods to manipulate the browser, find elements and interact with them, but sometimes they are not enough and you need other ways to take the actions you need. As you know, Selenium can run javascript code on the browser, so… why not run the jQuery functions that you need to hack your testing?
Problems to solve
The Selenium built in methods to get elements use css or xpath locators, but you can’t distinguish between dynamics statuses of the elements like ‘hover’, ‘focus’, ‘enabled’, ‘visible’, etc. It’s really common on web applications that a modal or dialog exists on the DOM but it is hidden, and is a good case to use the “visible” suffix on the selector to get it only when it is visible.
Enhanced features
The known javascript library, called jQuery, provides a bunch of methods that can be performed over any web element and, of course, since Selenium is able to run javascript code, you can run jQuery methods on them using WebDriver.
This library also allows you to use all CSS enhanced selectors, like “:has”, “:not”, “:contains” to find in a better way the element you need.
How to inject jQuery library
There is no weird trick to inject the jQuery library into the page, it is the same way you can do it by using the browser console manually. By the way, every time the page is refreshed you should inject it if necessary.
The javascript code to inject the library is the following:
// Javascript code
var headID = document.getElementsByTagName(“head”)[0];
var newScript = document.createElement(‘script’);
newScript.type = ‘text/javascript’;
newScript.src = ‘https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js';
headID.appendChild(newScript);
Basically you are creating a new HTML ‘script’ element whose source is the link to the jQuery library (in the example above it is injecting version 3.3.1, but you can use the one you need).
To execute javascript with WebDriver, you should use JavascriptExecutor, so let me show you how to do it, and how to perform the injection.
// Java code
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(
“var headID = document.getElementsByTagName(“head”)[0];” +
“var newScript = document.createElement(‘script’);” +
“newScript.type = ‘text/javascript’;” +
“newScript.src = ‘https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js';” +
“headID.appendChild(newScript);”);
After the injection is executed we need to wait until jQuery is fully loaded, so we need to create an Explicit wait to do it and be sure we succeed:
// Java code
WebDriverWait wait = new WebDriverWait(driver, 30);
Function<WebDriver, Boolean> jQueryAvailable = WebDriver -> (
(Boolean) js.executeScript(“return (typeof jQuery != \”undefined\”)”)
);
wait.until(jQueryAvailable);
What the code above does is to wait for 30 seconds for jQuery to be available. We can know that it is loaded by running javascript code asking if the type of jQuery is not undefined. When the condition is true, the method stops waiting.
Well, after all this you can run jQuery code or use its selector enhancements to find elements, but we can still improve something in order to avoid future issues with some other third party libraries. Injecting jQuery replaces the dollar sign ‘$’ value from javascript global variables, it is the shortener used to access jQuery methods, so we need to restore the value it had before we inject the library, no matter if it was in use or not, but it is a good practice to avoid future issues. Run the following code to avoid conflicts:
// Java code
js.executeScript(“$.noConflict();”);
How to use jQuery selectors and methods
Once jQuery is injected and available for us on the webpage, we can use any of its methods or enhanced selectors. Remember that after running noConflict() method, we are not able to use the shortcut symbol (dollar sign) to access jQuery, so we need to call it with the jQuery keyword.
Again the JavascriptExecutor will be needed, because we are going to run javascript code. For example, for getting Web Elements you should run code as the one below:
// Java code
JavascriptExecutor js = (JavascriptExecutor) driver;
List<WebElement> elements = (List<WebElement>) js.executeScript(“return jQuery.find(‘div.className:visible’)”);
You can find all jQuery selectors here.
There is not much difference for executing jQuery methods, you can do it the following way:
// Java code
JavascriptExecutor js = (JavascriptExecutor) driver;
Long w = (Long) js.executeScript(“return jQuery.find(‘div.className:visible’).width()”);
So now you have no constraints on managing jQuery and JavascriptExecutor. You are able to run any javascript and jQuery code you need. Think big and rock your code using the wide features of the jQuery you love.