Feature-rich jQuery-like Java interface for Selenium WebDriver
seleniumQuery is a feature-rich cross-driver Java library that brings a jQuery-like interface for Selenium WebDriver.
It is designed to be a thin layer over Selenium. You can use seleniumQuery to manage the WebDriver for you, or you can use seleniumQuery on top of your favorite selenium framework just
to make some cases simpler when needed.
Example snippet:
// Regular SeleniumWebElementel = driver.findElement(By.cssSelector(".street"));
StringoldStreet = element.getAttribute("value"); // what if ".street" is a <select>? this won't workelement.setAttribute("value", "4th St!")
// seleniumQuery// getting the valueStringoldStreet = $(".street").val(); // works even if it is a <select>, <textarea>, etc.// setting the value$("input.street").val("4th St!"); // also would work for a <select>
And much more. The example above is of something that has an equivalent in Selenium. Not everything does (many things would require tons of boilerplate in vanilla Selenium).
No special configuration needed - use seleniumQuery's goodies in your project right now:
// an existing WebDriver...WebDriverdriver = newFirefoxDriver();
// set it up$.driver().use(driver);
// and use all the goodsfor (WebElemente: $(".myClass:contains('My Text!'):not(:button)")) {
System.out.println("That element: " + e);
}
and even some own seleniumQuery selectors: $("#myOldDiv").is(":not(:present)").
Built using Selenium WebDriver's capabilities, no jQuery.js is embedded at the page, no side-effects are generated.
Quickstart: A running example
Try it out now with the running example below:
importstaticio.github.seleniumquery.SeleniumQuery.$; // this will allow the short syntaxpublicclassSeleniumQueryExample {
publicstaticvoidmain(String[] args) {
// The WebDriver will be instantiated only when first used$.driver()
.useChrome() // sets Chrome as the driver (this is optional, if omitted, will default to HtmlUnit)
.headless() // configures chrome to be headless
.autoDriverDownload() // automatically downloads and configures chromedriver.exe
.autoQuitDriver(); // automatically quits the driver when the JVM shuts down// or, instead, use any previously existing driver// $.driver().use(myExistingInstanceOfWebDriver);// starts the driver (if not started already) and opens the URL$.url("http://www.google.com/?hl=en");
// interact with the page$(":text[name='q']").val("seleniumQuery"); // the keys are actually typed!// Besides the short syntax and the jQuery behavior you already know,// other very useful function in seleniumQuery is .waitUntil(),// handy for dealing with user-waiting actions (specially in Ajax enabled pages):// the command below waits until the button is visible and then performs a real user click (not just the JS event)$(":button[value='Google Search']").waitUntil().isVisible().then().click();
// this waits for the #resultStats to be visible using a selector and, when it is visible, returns its text contentStringresultsText = $("#resultStats").waitUntil().is(":visible").then().text();
// .assertThat() functions: fluently asserts that the text contains the string "seconds", ignoring case$("#resultStats").assertThat().text().containsIgnoreCase("seconds");
System.out.println(resultsText);
// should print something like: About 4,100 results (0.42 seconds)// $.quit(); // would quit the driver, but it is not needed as .autoQuitDriver() was used
}
}
To get the latest version of seleniumQuery, add to your pom.xml:
Download and execute the seleniumQuery showcase project.
It contains many demonstrations of what seleniumQuery is capable of.
Features
seleniumQuery implements all jQuery functions that are useful to browser manipulation.
On top of it, we add many other useful functions (see $("selector").waitUntil() and $("selector").assertThat() below).
Our main goal is to make emulating user actions and reading the state of pages easier than ever, with a consistent behavior across drivers.
Readable jQuery syntax you already know
Make your code/tests more readable and easier to maintain. Leverage your knowledge of jQuery.
// Instead of regular Selenium code:WebElementelement = driver.findElement(By.id("mySelect"));
newSelect(element).selectByValue("ford");
// You can have the same effect writing just:$("#mySelect").val("ford");
Get to know what jQuery functions seleniumQuery supports and what else it brings to the table on our seleniumQuery API wiki page.
Waiting (ajax testing) and asserting
WebDriver's FluentWait is great, but it requires too much boilerplate code. Enters the .waitUntil() function:
// Below is an example of a <div> that should be hidden as effect of an Ajax call.// The code will hold until the modal is gone. If it is never gone, seleniumQuery will throw a timeout exception$("#modalDiv :button:contains('OK')").click();
$("#modalDiv :button:contains('OK')").waitUntil().is(":not(:visible)");
// Or the two commands above, fluently:$("#modalDivOkButton").click().waitUntil().is(":not(:visible)");
You can also assert directly into the seleniumQuery object using .assertThat():
Any function that can be used with $().waitUntil() can also be used with $().assertThat() and vice-versa.
See below, expand (click on the arrow) each item for more details.
$(). function
Property/Evaluation Function
Evaluation Function
.waitUntil()
In order to handle interactions with Ajax-enabled pages, you can use the .waitUntil() function:
The .waitUntil() functions will requery the DOM for the elements until the given condition is met, returning a new seleniumQuery object when that happens.
// .waitUntil() will requery the DOM every time until the matched set fulfills the requirements// .is() functions$(".aDivDiv").waitUntil().is(":present");
$(".myInput").waitUntil().is(":enabled");
$(".aDivDiv").waitUntil().is(":visible");
$(".myInput").waitUntil().is(":visible:enabled");
// functions such as .val(), .text() and others are also available$(".myInput").waitUntil().val().isEqualTo("expectedValue");
$(".aDivDiv").waitUntil().text().contains("expectedText");
// and more...$(".myInput").waitUntil().val().matches(".*\d{10}\*");
$(".myInput").waitUntil().size().isGreaterThan(7);
$(".aDivDiv").waitUntil().html().contains("<div>expected</div>");
.assertThat()
Asserts, fluently, that the function has a specified value or matches a specified condition.
Evaluates if this seleniumQuery object has only visible elements.
Note: this is different from .is(":visible") because .is() requires only one
element to match the selector (to be visible), whereas this .isVisible() method
requires all matched elements to be visible.
Evaluates if this seleniumQuery object has only visible elements.
Note: this is different from .is(":visible") because .is() requires only one
element to match the selector (to be visible), whereas this .isVisible() method
requires all matched elements to be visible.
$("span").assertThat().size().isGreaterThan(5).and().text().isEqualTo("a b c d e");
Or use functions after waiting/asserting using .then():
$("#div").waitUntil().isVisible().then().click();
Flexible WebDriver builder system
How to setup the WebDriver? Simply use our builder. You can download their executables before or you can
let seleniumQuery automatically download and configure them. Setup in seleniumQuery is all too easy:
// Using Chrome, general example:$.driver()
.useChrome() // configures Chrome as the driver
.headless() // configures Chrome to run in headless mode
.autoDriverDownload() // automatically downloads and configures chromedriver.exe
.autoQuitDriver(); // automatically quits the driver when the JVM shuts down// Using Firefox$.driver()
.useFirefox() // configures Firefox as the driver
.headless() // configures Firefox to run in headless mode
.autoDriverDownload() // automatically downloads and configures geckodriver.exe
.autoQuitDriver(); // automatically quits the driver when the JVM shuts down
For more examples, options and all supported drivers, see table below.
Using seleniumQuery in an existingWebDriver instance
The driver builder functions are a bonus, you don't have to use them. For seleniumQuery, it makes no difference.
If you want to create the WebDriver yourself or add seleniumQuery to an existing WebDriver instance just:
WebDrivermyExistingDriverInstance = ...; // created elsewhere by whoever$.driver().use(myExistingDriverInstance); // from now on, $ will work on myExistingDriverInstance// now you can use all of seleniumQuery's power!$("#phone").assertThat().val().isEqualTo("99887766");
Chrome
Here's how seleniumQuery can simplify a ChromeDriver instantiation.
Configures Chrome as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().useChrome() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.headless()
Runs Chrome in headless mode.
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
.autoDriverDownload()
seleniumQuery automatically downloads and configures the driver. The download is managed by webdrivermanager.
Additional options are available, pass a lambda to .autoDriverDownload(<labda>) to be able to configure:
$.driver().useChrome().autoDriverDownload((BrowserManagerconfigurer) -> {
// se more options at https://github.com/bonigarcia/webdrivermanager#webdrivermanager-apiconfigurer.proxy("http://corpproxy:8182");
configurer.proxyUser("myUser");
configurer.proxyPass("myPass")
});
.withOptions(ChromeOptions)
Enables additional configuration through a ChromeOptions instance.
.withPathToChromeDriver(String)
If you don't want seleniumQuery to automatically download the executable for you (using .autoDriverDownload()) you can
specify the location of chromedriver.exe/chromedriver yourself:
If you use neither .autoDriverDownload() nor .withPathToChromeDriver(), seleniumQuery will attempt to find the executable
on your PATH or classpath. If it doesn't find it anywhere, an exception will be thrown.
.withCapabilities(DesiredCapabilities)
Configures the given DesiredCapabilities in the driver to be instantiated. Prefer ChromeOptions when possible.
// Using Chrome$.driver().useChrome(); // will look for chromedriver/exe to you, including in the classpath!// if you don't have chromedriver.exe and want seleniumQuery to auto download and configure it$.driver().useChrome().headless().autoDriverDownload();
// If you want to set the path to chromedriver.exe yourself$.driver().useChrome().withPathToChromeDriver("path/to/chromedriver.exe")
// General example:$.driver()
.useChrome() // configures Chrome as the driver
.headless() // configures Chrome to run in headless mode
.autoDriverDownload() // automatically downloads and configures chromedriver.exe
.autoQuitDriver(); // automatically quits the driver when the JVM shuts down// using options$.driver()
.useChrome()
.withOptions(<someChromeOptionsinstance>)
Firefox
Easy FirefoxDriver instantiation and configuration with seleniumQuery.
Configures Firefox as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().useFirefox() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.headless()
Runs Firefox in headless mode.
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
.autoDriverDownload()
seleniumQuery automatically downloads and configures the driver. The download is managed by webdrivermanager.
Additional options are available, pass a lambda to .autoDriverDownload(<labda>) to be able to configure:
$.driver().useFirefox().autoDriverDownload((BrowserManagerconfigurer) -> {
// se more options at https://github.com/bonigarcia/webdrivermanager#webdrivermanager-apiconfigurer.proxy("http://corpproxy:8182");
configurer.proxyUser("myUser");
configurer.proxyPass("myPass")
});
.withOptions(FirefoxOptions)
Enables additional configuration through a FirefoxOptions instance.
.withBinary(FirefoxBinary)
Enables additional configuration through a FirefoxBinary instance.
.withProfile(FirefoxProfile)
Enables additional configuration through a FirefoxProfile instance.
.withCapabilities(DesiredCapabilities)
Configures the given DesiredCapabilities in the driver to be instantiated. Prefer FirefoxOptions when possible.
// Using Firefox$.driver()
.useFirefox() // configures Firefox as the driver
.headless() // configures Firefox to run in headless mode
.autoDriverDownload() // automatically downloads and configures geckodriver.exe
.autoQuitDriver(); // automatically quits the driver when the JVM shuts down// simplified setting of profile, options and binary$.driver()
.useFirefox()
.withProfile(<aninstanceofFirefoxProfile>)
.withOptions(<aninstanceofFirefoxOptions>)
.withBinary(<aninstanceofFirefoxBinary>);
Opera
Automatic driver download available.
.useOpera()
Configures Opera as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().useOpera() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
.autoDriverDownload()
seleniumQuery automatically downloads and configures the driver. The download is managed by webdrivermanager.
Additional options are available, pass a lambda to .autoDriverDownload(<labda>) to be able to configure:
$.driver().useOpera().autoDriverDownload((BrowserManagerconfigurer) -> {
// se more options at https://github.com/bonigarcia/webdrivermanager#webdrivermanager-apiconfigurer.proxy("http://corpproxy:8182");
configurer.proxyUser("myUser");
configurer.proxyPass("myPass")
});
.withOptions(OperaOptions)
Enables additional configuration through a OperaOptions instance.
.withBinary(string | File)
Configures the Opera browser binary location. Example:
Configures the given DesiredCapabilities in the driver to be instantiated. Prefer OperaOptions when possible.
// Opera// we'll download the driver for you$.driver().useOpera().autoDriverDownload();
// simplified setting of options and binary$.driver()
.useOpera()
.withOptions(<aninstanceofOperaOptions>)
.withBinary("C:/Program Files/Opera/49.0.2725.47/opera.exe") // example path
.autoDriverDownload();
Configures PhantomJS as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().usePhantomJS() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
.autoDriverDownload()
seleniumQuery automatically downloads and configures the driver. The download is managed by webdrivermanager.
Additional options are available, pass a lambda to .autoDriverDownload(<labda>) to be able to configure:
$.driver().usePhantomJS().autoDriverDownload((BrowserManagerconfigurer) -> {
// se more options at https://github.com/bonigarcia/webdrivermanager#webdrivermanager-apiconfigurer.proxy("http://corpproxy:8182");
configurer.proxyUser("myUser");
configurer.proxyPass("myPass")
});
.withPathToPhantomJS(String)
If you don't want seleniumQuery to automatically download the executable for you (using .autoDriverDownload()) you can
specify the location of phantomjs.exe/phantomjs yourself:
If you use neither .autoDriverDownload() nor .withPathToPhantomJS(), seleniumQuery will attempt to find the executable
on your PATH or classpath. If it doesn't find it anywhere, an exception will be thrown.
.withCapabilities(DesiredCapabilities)
Configures the given DesiredCapabilities in the driver to be instantiated.
// PhantomJS (GhostDriver)// we'll download phantomjs.exe for you$.driver().usePhantomJS().autoDriverDownload();
// or, we may find phantomjs[.exe] for you, throwing an error if not present$.driver().usePhantomJS();
// Or you may set the path yourself$.driver().usePhantomJS().withPathToPhantomJS("path/to/phantomjs.exe");
HmtlUnit
Always headless, java-based. No need to download anything.
.useHtmlUnit()
Configures HmtlUnit as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().useHtmlUnit() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
Note: Since HtmlUnit is a java-based driver, it will quit upon JVM shutdown anyway.
.withoutJavaScript()
Runs HtmlUnit with disabled JavaScript.
.emulatingChrome()
Configures HtmlUnit to emulate Chrome.
.emulatingFirefox()
Configures HtmlUnit to emulate Firefox.
.emulatingInternetExplorer()
Configures HtmlUnit to emulate Internet Explorer.
.withCapabilities(DesiredCapabilities)
Configures the given DesiredCapabilities in the driver to be instantiated.
// There are many possibilities to set up HtmlUnitDriver// HtmlUnit default (Chrome/JavaScript ON)$.driver().useHtmlUnit();
// Want disabled JavaScript, just call .withoutJavaScript()$.driver().useHtmlUnit().withoutJavaScript();
// HtmlUnit emulating Chrome$.driver().useHtmlUnit().emulatingChrome();
$.driver().useHtmlUnit().emulatingChrome().withoutJavaScript();
// HtmlUnit emulating Firefox$.driver().useHtmlUnit().emulatingFirefox(); // could disable JS here as well// And IE$.driver().useHtmlUnit().emulatingInternetExplorer11(); // JS is disableable as well$.driver().useHtmlUnit().emulatingInternetExplorer(); // will pick latest IE
Safari
seleniumQuery tests Safari as a remote driver.
$.driver().useDriver(newSafariDriver());
Edge
Automatic driver download available.
.useEdge()
Configures Edge as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().useEdge() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
.autoDriverDownload()
seleniumQuery automatically downloads and configures the driver. The download is managed by webdrivermanager.
Additional options are available, pass a lambda to .autoDriverDownload(<labda>) to be able to configure:
$.driver().useEdge().autoDriverDownload((BrowserManagerconfigurer) -> {
// se more options at https://github.com/bonigarcia/webdrivermanager#webdrivermanager-apiconfigurer.proxy("http://corpproxy:8182");
configurer.proxyUser("myUser");
configurer.proxyPass("myPass")
});
.withOptions(EdgeOptions)
Enables additional configuration through a EdgeOptions instance.
.withCapabilities(DesiredCapabilities)
Configures the given DesiredCapabilities in the driver to be instantiated. Prefer EdgeOptions when possible.
// Edge// we'll download the driver for you$.driver().useEdge().autoDriverDownload();
// simplified setting of options$.driver()
.useEdge()
.withOptions(<aninstanceofEdgeOptions>);
Configures Internet Explorer as the driver to be used. Provides additional configuration options that can be chained.
Calling $.driver().useInternetExplorer() does not instantiate the driver right away, it merely configures it.
The driver will be instantiated when first used only (e.g. when $.url("http://somepage") is called).
.autoQuitDriver()
Automatically quits the driver upon JVM shutdown.
If you don't use .autoQuitDriver(), you can quit the driver calling $.quit().
Having .autoQuitDriver() on and still calling $.quit() makes no harm, so quit at will.
.autoDriverDownload()
seleniumQuery automatically downloads and configures the driver. The download is managed by webdrivermanager.
Additional options are available, pass a lambda to .autoDriverDownload(<labda>) to be able to configure:
$.driver().useInternetExplorer().autoDriverDownload((BrowserManagerconfigurer) -> {
// se more options at https://github.com/bonigarcia/webdrivermanager#webdrivermanager-apiconfigurer.proxy("http://corpproxy:8182");
configurer.proxyUser("myUser");
configurer.proxyPass("myPass")
});
.withPathToIEDriverServerExe(String)
If you don't want seleniumQuery to automatically download the executable for you (using .autoDriverDownload()) you can
specify the location of IEDriverServer.exe yourself:
If you use neither .autoDriverDownload() nor .withPathToIEDriverServerExe(), seleniumQuery will attempt to find IEDriverServer.exe
on your PATH or classpath. If it doesn't find it anywhere, an exception will be thrown.
.withCapabilities(DesiredCapabilities)
Configures the given DesiredCapabilities in the driver to be instantiated.
// InternetExplorerDriver// we'll download the driver for you$.driver().useInternetExplorer().autoDriverDownload();
// or we search IEDriverServer.exe on your computer (path and classpash) for you$.driver().useInternetExplorer();
// Or you set the path yourself$.driver().useInternetExplorer().withPathToIEDriverServerExe("C:\\IEDriverServer.exe");
seleniumQuery still is Selenium - with "just" a jQuery interface
So there is a important aspect of it: Although our functions yield the same result as if you were using jQuery, remember we always execute them from the user perspective.
In other words, when you call:
We don't change the value attribute directly like jQuery does. We actually do as a user would: We clear the input
and type, key by key, the string provided as argument!
And we go the extra mile whenever possible:
Our $().val() even works on contenteditable elements AND documentMode=on <iframe>s: They don't have value, but we type the text in them, again, key by key, as an user would;
If it is an <input type="file"> we select the file;
When the element is a <select>, we choose the <option> by the value given (same as $("selector").as().select().selectByValue("123")).
Always from the user perspective
On the same tone, when selecting/checking <option>s or checkboxes or radios, try not to use $().prop("selected", true) directly to them (which to work, of course, would need JS to be enabled on the driver).
Do as an user would: call .click()! Or, better yet, use seleniumQuery's .as().select() functions: $().as().select().selectByVisibleText("My Option") or $().as().select().selectByValue("123").
Using multiple browsers/drivers simultaneously
Typically, the $ is a static variable, thus every command you issue only affects the one same instance of WebDriver.
But... what if you want/need to use two WebDrivers at the same time?
publicstaticvoidmain(String[] args) {
StringdemoPage = "https://cdn.rawgit.com/seleniumQuery/seleniumQuery-showcase/master/Agent.html";
// using two drivers (chrome and firefox) at the same timeSeleniumQueryBrowserchrome = newSeleniumQueryBrowser();
chrome.$.driver().useHtmlUnit().emulatingChrome().autoQuitDriver();
chrome.$.url(demoPage);
SeleniumQueryBrowserfirefox = newSeleniumQueryBrowser();
firefox.$.driver().useHtmlUnit().emulatingFirefox().autoQuitDriver();
firefox.$.url(demoPage);
chrome.$("#agent").assertThat().text().contains("Chrome");
firefox.$("#agent").assertThat().text().contains("Firefox");
}
Plugin System
seleniumQuery supports plugins through the .as(PLUGIN) function, such as:
There are some default plugins. To check them out, call .as() without arguments. Example:
// the .select() plugin$("#citiesSelect").as().select().selectByVisibleText("New York");
// picks an <option> in the <select> based in the <option>'s visible text
If the dollar symbol, $, gives you the yikes -- we know, it is used for internal class names --, it is important to notice that the $ symbol in seleniumQuery is not a class name, but a static method (and field). Still, if you don't feel like using it, you can resort to sQ() or good ol' jQuery() and benefit from all the same goodies:
The tool quite simple, so there's a lot of room for improvement. If you think something would be useful for you, it
would probably be useful to us all, tell us what you're thinking!