Inject the Sizzle CSS selector library

5 (100%) 1 vote

Problem

We might experience some locator issues during the transition from Selenium 1 to Selenium WebDriver. We face these issues because Selenium WebDriver stays strict to the CSS standard. It might that :contains(‘text’) does not locate the web page elements anymore. The solution is to inject the Sizzle engine into the browser under test. We can make a SizzleSelector class and use the power of Sizzleselector where necessary. Shannon Code came up with a very nice class, which can be found here: http://www.prototypic.net/weblog/?p=14

Solution

This is the code of the SizzleSelector class. It injects the Sizzle engine into the browser under test by JavaScript.

<code lang="java">
import java.util.List;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
 
@SuppressWarnings("unchecked")
public class SizzleSelector {
    private JavascriptExecutor driver;
 
    public SizzleSelector(WebDriver webDriver) {
        driver = (JavascriptExecutor) webDriver;
    }
 
    public WebElement findElementBySizzleCss(String using) {
        injectSizzleIfNeeded();
        String javascriptExpression = createSizzleSelectorExpression(using);
        List&lt;WebElement> elements = (List&lt;WebElement>) driver
                .executeScript(javascriptExpression);
        if (elements.size() > 0)
            return (WebElement) elements.get(0);
        return null;
    }
 
    public List&lt;WebElement> findElementsBySizzleCss(String using) {
        injectSizzleIfNeeded();
        String javascriptExpression = createSizzleSelectorExpression(using);
        return (List&lt;WebElement>) driver.executeScript(javascriptExpression);
    }
 
    private String createSizzleSelectorExpression(String using) {
        return "return Sizzle(\"" + using + "\")";
    }
 
    private void injectSizzleIfNeeded() {
        if (!sizzleLoaded())
            injectSizzle();
    }
 
    public Boolean sizzleLoaded() {
        Boolean loaded;
        try {
            loaded = (Boolean) driver.executeScript("return Sizzle()!=null");
        } catch (WebDriverException e) {
            loaded = false;
        }
        return loaded;
    }
 
    public void injectSizzle() {
        driver.executeScript(" var headID = document.getElementsByTagName(\"head\")[0];"
                + "var newScript = document.createElement('script');"
                + "newScript.type = 'text/javascript';"
                + "newScript.src = 'https://raw.github.com/jquery/sizzle/master/sizzle.js';"
                + "headID.appendChild(newScript);");
    }
}
</code>

How to use it

The class described above will inject the Sizzle engine into the browser under test. This allows us to use all the Sizzle selector features, such as :contains(‘text’). Other classes can extended this class and we are able to use the findElementBySizzleCss() method to locate the elements.

<code lang="java">
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class SizzleExample {
    private static WebDriver driver;
    SizzleSelector sizzle;
    
    @BeforeClass
    public void setUp() {
        driver = new FirefoxDriver();
        sizzle = new SizzleSelector(driver);
        driver.get("http://techblog.polteq.com/prestashop/");
    }
    
    @AfterClass
    public void tearDown() {
        driver.close();
        driver.quit();
    }
    
    @Test
    public void useSizzleSelector() {
        sizzle.findElementBySizzleCss("input#search_query_top").sendKeys("ipod nano");
        sizzle.findElementBySizzleCss("input[name='submit_search']").click();
        String searchHeader =  sizzle.findElementBySizzleCss("H1").getText().toLowerCase();
        
        Assert.assertTrue(searchHeader.contains("ipod nano"));
    }
}
</code>

11 thoughts on “Inject the Sizzle CSS selector library”

  1. Hi, I would really, really, like to be able to use sizzle in webdriver. I implemented the class but get the following error: Unresolved compilation problem: Type mismatch: cannot convert from Object to WebElement for the findElementBySizzleCss method beginning on line 15. Any thoughts or help would be greatly appreciated!

    1. Thanks for your reply!

      I have enriched the post with a detailed example. Please let me know if you still have some difficulties.

  2. can this sizzle selector library be used with web driver. scenarios is as follows:
    // parent tags
    adams // child-1
    kevin // child-2
    mahi // child-3

    css locator for selenium 1 for child-3: css=div.x>div:contains(‘mahi’)

    can this injection help me in locating ‘mahi’ for web driver in same manner as in selenium1(css locator strategy)?

    please mention a locator for ‘mahi’ .

    1. Sure, you can do something like this:

      element:nth-child(3)

      It would be good if you are able to give me a HTML-snippet.

      Regards,
      Roy de Kleijn

  3. Can we do something like below with this ?

    //td[text()=’SomeText’]/div/a

    My question is Can we locate elements using innerText?

    1. hi Santosh,

      Sure you can. Given the above example: String searchHeader = sizzle.findElementBySizzleCss(“H1:contains(‘ipod nano’)”).getText().toLowerCase();

      Best regards,
      Roy

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.