You shoudn't. JQuery selectors offer most of what CSS 2 and CSS 3 selectors do, plus something more, but you can probably live without it. If you know JQuery selectors, you already know CSS selectors.
Use CSS selectors where you can and use XPath expressions where it's not enough (they're stronger). I doubt you'll find many real usages where these two aren't enough (and then, the usual approach is to get what you can and iterate over the collection, filtering the results manually).
That said, you could possibly force WebDriver to accept JQuery selectors, too:
If you only want to support one or two browsers, the easiest way might be to write a simple addon to that browser which would inject JQuery to every page if it's not already present. You'd then force this addon to be used by the browser you're using.
If you want to support all of the browsers, that solution quickly becomes a burden and the best you could do is to write a decorator for WebDriver that would try to inject JQuery into the page before any findElements()
and/or executeScript()
call, if it's not already present.
See this question to get an idea about injecting JQuery.
After you've injected it, you can use it, again, only via JavaScript:
// earlier
if (driver instanceof JavascriptExecutor) {
js = (JavascriptExecutor)driver;
} else {
throw new IllegalStateException("This driver cannot run JavaScript.");
}
WebElement element = (WebElement)js.executeScript("$('div.account').get(0)");
// or
List<WebElement> elements = (List<WebElement>)js.executeScript("$('div.account').get()");
You can easily wrap those lines into a new By
object, or a new findElement(String jQuerySelector)
method for your decorated WebDriver, if you want, but that's up to your convenience and laziness, we got it working...
The best approach, I think, would be to create a new By
implementation called ByJQuery
. See this answer on how to make a ByJavaScript
- it's a small step from there to reuse it, inject JQuery into the page and run the actual query.
class ByJQuery extends By implements Serializable {
private final String query;
public ByJQuery(String query) {
checkNotNull(query, "Cannot find elements with a null JQuery expression.");
this.query = query;
}
@Override
public List<WebElement> findElements(SearchContext context) {
WebDriver driver = getWebDriverFromSearchContext(context);
if (!isJQueryInThisPage(driver)) {
injectJQuery(driver);
}
return new ByJavaScript("return $(" + query + ")").findElements(context);
}
private static WebDriver getWebDriverFromSearchContext(SearchContext context) {
if (context instanceof WebDriver) {
return (WebDriver)context;
}
if (context instanceof WrapsDriver) {
return ((WrapsDriver)context).getWrappedDriver();
}
throw new IllegalStateException("Can't access a WebDriver instance from the current search context.");
}
private static boolean isJQueryInThisPage(WebDriver driver) {
// TODO Some JavaScript test for a JQuery object.
}
private static void injectJQuery(WebDriver driver) {
// TODO Load JQuery from a file, inject it into the page via JS.
}
@Override
public String toString() {
return "By.jQuery: \"$(" + query + ")\"";
}
}