Selenium Tips: Finding elements by their inner text using :contains, a CSS pseudo-class

March 19th, 2010 by Santiago Suarez Ordoñez

As we already mentioned in our previous posts CSS Selectors in Selenium Demystified and Start improving your locators, CSS as a location strategy generally far outperforms XPATH.

That’s why for this Tip of the Week, we are presenting our users one more CSS pseudo-class to keep moving their test suites to this faster and cleaner location strategy.

Let’s imagine you have an element like the following:

<div>Click here</div>

The easiest way to locate it is using it’s “Click here” inner text and in XPATH you would do it using XPATH’s text() function:

//div[text() = "Click here"]

or even better (because the previous version can sometimes fail depending on the browser):

//div[contains(text(), "Click here")]

Now, if you want to move your locators to CSS in situations like this one, all you have to do is use the :contains() pseudo-class, with which your tests would end up using the following locator:

css=div:contains("Click here")

Did you find this useful? Are you still fighting with another XPATH functionality to completely move your tests to CSS? Let us know about it in the comments.

Share

Related posts:
Selenium Tips: Start improving your locators
Selenium Tips: CSS Selectors in Selenium Demystified
Selenium Tips: Improving your waiting skills
Selenium Tips: Parametrizing Selenese tests

Comments (You may use the <code> or <pre> tags in your comment)

  1. Alex says:

    I would like to add one useful tip regarding “:contains()”.
    It’s possible to find the _exact_ match using this pseudo-class.
    For example, we have the following elements:
    abc ab
    Locator css=div:contains(“ab”) will find the 1st element.
    While the css=div:contains(“^ab$”) will find the 2nd one.
    It’s similar to regex syntax.

    P.S. Thanks for the great blog, guys.

  2. Alex says:

    P.P.S. The parser has eaten my “div” tags, but I hope the point is clear.

  3. Jayakumar says:

    Hi Santi,

    If i wanted to do a exact text(not like ‘contains’) match with CSS, what could be the locator?

  4. TiTi says:

    Hi guys, thanks for the very good tips.
    I’ve got an intersting XPath which takes an horrible time to run on IE. Is is possible to use a CSS locator instead ?
    Here it is:

    //input[@id=(//label[text()='Fax']/@for)]

    I have no other way to get the good input. I can only use the to differenciate them.
    Use the following simplified HTML to get an idea.
    ctl01,ctl02,ctl03 are dynamic ids, they change each time the page is refresh so I can’t base my test on that.
    ——

    Courrier

    Fax

    Courrier en nombre


    Thx anyways ;)

  5. TiTi says:

    Dammit HTML is protected:
    I’ve pasted the code here: http://pastebin.com/FQ5HYZS4
    and here: http://jsbin.com/ogeto3/edit

  6. Sean Grove says:

    Hey Jayakumar, great question.

    As Alex kindly pointed out, it’s possible to use regular expression (or regex) syntax to specify your matches. For example:

    css=div:contains(“example”)

    css=div:contains(“^example”)

    css=div:contains(“^example$”)

    1. Finds any div that has the text “example” anywhere
    2. In regex syntax, ^ signifies the beginning of the line. Thus, this will find any div with text that begins with “example”, though anything can follow it.
    3. Finally, $ identifies the end of a line. So this version will find any divs with text that contains exactly “example”.

    For more information on Regex, check out http://www.regular-expressions.info/.

  7. Alex says:

    Hi TiTi.
    I don’t know how to convert your xpath to css, but I can suggest you the workaround:

    String id = selenium.getAttribute(“css=label:contains(‘^Fax$’)@for”);
    selenium.check(“css=input#” + id);

    This should work faster than a complex xpath in IE.

  8. Hi TiTi,

    Indeed, as Alex pointed out, you can use css=label:contains(^Fax$’)@for.

    Thanks again Alex for that great tip to match exact content!

  9. TiTi says:

    Hi,

    Thank you for the tip Alex. I tried it, working on FF but not on IE :-(
    >tr<
    >td<storeAttribute>/td<
    >td<css=label:contains(‘^Fax$’)@for>/td<
    >td<plopz>/td<
    >/tr<
    >tr<
    >td<click>/td<
    >td<css=input#${plopz}>/td<
    >td<>/td<
    >/tr<

    I also managed to optimise my XPath with the following expression, which is significantly faster:

    //td[label/text()='Fax en nombre']/input”

    1 second for this one. The other one was taking 12 seconds on my computer ^^

  10. TiTi says:

    In the good order:

    <tr>
        <td>storeAttribute</td>
        <td>css=label:contains(‘^Fax$’)@for</td>
        <td>plopz</td>
    </tr>
    <tr>
        <td>click</td>
        <td>css=input#${plopz}</td>
        <td></td>
    </tr>

  11. strawberry says:

    HI,

    Anyone can tell me how to use the css method to write the deep xpath?

    Such as,
    @selenium.get_text(“//div[@id='App']/div/div[1]/h4[@class='Online']“)

    How to use the css selector to write the above deep xpath?

    Thanks!

  12. Alex says:

    Hi strawberry, it’s me again :)

    Try this one:
    “css=div#App > div > div:first-child > h4.Online”
    It should work exactly like your xpath.

  13. Andrew says:

    Thanks for this article!

    However, I’m running into an issue and I was wondering if you could help. I have two tables with similar data, but I would like to assert that they are different. I have a table that contains a particular header text:

    css=table:contains(User Entered Information)

    That assertion passes. Now I would like to assert that the table has a table row that contains the right text:

    css=table:contains(User Entered Information) tr:contains(Name):contains(Andrew)

    So I would like to use multiple :contains() within an assertion, but it doesn’t seem to be working. What am I doing wrong?

  14. Andrew says:

    Just wanted to leave an update. I think the problem is with Selenium and trying to select descendants. I was able to get it to work when I specified an ID on the table.

    css=#user-entered-information tr:contains(Name):contains(Andrew)

  15. Marcus says:

    Hi, how can i check, if a link is underlined while the mouse is over it?
    My CSS looks like:

    a:hover, a:active{
    text-decoration: underline;
    }

    Thanks for your help!

  16. sonicblaster says:

    ДВЕ электронные сигареты по цене ОДНОЙ! До 21 апреля!
    http://ELCIGAR-SHOP.ru

  17. jjokerstars says:

    ДВЕ электронные сигареты по цене ОДНОЙ! До конца апреля!
    http://ELCIGAR-SHOP.ru
    Успевайте!

  18. awuke says:

    ДВЕ электронные сигареты по цене ОДНОЙ! До конца апреля!
    http://ELCIGAR-SHOP.ru
    Успевайте!

  19. BrooloWreno says:

    Извините, что я вмешиваюсь, но я предлагаю пойти другим путём.

  20. qw says:

    I have a problem with :contains. I cannot locate element using Firefinder by td:contains(“group1″). Does Firefinder support css contains selector?

  21. Hi qw,

    I forgot to mention that :contains is actually only supported by Selenium one and its CSS engine (Sizzle). You should be able to use Selenium IDE to test your locator, but other CSS finders, like Firefinder may not work. :(

  22. andrew_laser says:

    What should be the solution for a bit modified element like the following?

    Click variable_string here

    where “variable_string” is changeable or not known

  23. Aleh says:

    css=div:contains(‘^ab$’) doesn’t work with FF7 and IDE 1.3.0

  24. Nicolas says:

    Thanks for the tip! :)

  25. Roy says:

    Thank you! I’m totally new to Selenium and I could not work out how to check that text stored in a table was present but changing div to table worked for me.

  26. Kamote says:

    Hi Guys,

    I’m having trouble with selenium locating the element in the page. Below is the css that I’m using. It can be detected in Selenium IDE but in Selenium RC, the object can’t be detected. Any suggestions guys? Thanks!

    CSS Locator:
    css=td.lbl:contains(“(if ‘Yes’ provide full details in adjacent box)”)

    Actual HTML:
    (if ‘Yes’ provide full details in adjacent box)

Leave a Comment