How do I select only visible elements using XPath?

GwtXpathSelenium

Gwt Problem Overview


I have a GWT application for which I'm trying to write some tests using Selenium.

I'm using XPath to identify the elements on the page for the tests. Using id won't work as the id values are auto-generated by GWT and can change. Things started going well when I realised I could find buttons by their labels as follows:

//button[.='OK']

However, when I started running multiple tests I started having problems. I realised that the issue was all the different "pages" of the GWT app once generated by the Javascript remain in the HTML in hidden <div> elements. This meant my Selenium tests were sometimes clicking hidden buttons instead of the button visible in the current view.

Examining the HTML with Firebug, it seems that GWT hides the <div> elements by adding display: none to their style attribute. This means I can find all the hidden OK buttons as follows:

//div[contains(@style,'display: none')]//button[.='OK']

This will find all the hidden OK buttons, i.e the buttons which have an ancestor <div> which is hidden by having display: none in the style.

My question is: how do I use XPath to find only the visible OK buttons? How do I find the buttons which have no ancestor <div> elements with display: none in the style?

Gwt Solutions


Solution 1 - Gwt

This should work:

.//button[.='OK' and not(ancestor::div[contains(@style,'display:none')])
and not(ancestor::div[contains(@style,'display: none')])]

EDIT:

The simpler and more efficient expression below:

//div[not(contains(@style,'display:none'))]//button[.='OK']

does not work properly because every button has at least one div that's visible in its ancestors.

Solution 2 - Gwt

Selenium 2 Webdriver gives us the option of the isDisplayed() method which deals with this problem. Nice work by the selenium contributors.

Solution 3 - Gwt

This works for me:

//div[not(@hidden)]

Solution 4 - Gwt

//div[(contains(@style,'display: block'))]//button[@id='buttonid']

This worked for me. Like 'display: none' representing hidden blocks, 'display: block' represents currently displayed block and we can specify any inner tags to be identified as above

Solution 5 - Gwt

For me this worked to eliminate hidden elements:

//div[@open]//*

Solution 6 - Gwt

I added this code to the namemapping editor and it did not find the Keep button once it came up. The system sees it in the editor but it doesn't want to click on the button whenever create a new test which will include this item.

Now one other thing this is a dynamic button click so what happens is I will select a button that opens up a to drop downs where I place these items inside those dropdowns. Now it works for the first item but fails to recognize the same mapped item for the next time it is used in another screen. The buttonKeep is the same in both areas.

Solution 7 - Gwt

//div[contains(@style,'display: block')]

This code will find visible element xpath

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDave WebbView Question on Stackoverflow
Solution 1 - GwtJulian AubourgView Answer on Stackoverflow
Solution 2 - GwtHari ReddyView Answer on Stackoverflow
Solution 3 - GwtIvyView Answer on Stackoverflow
Solution 4 - GwtVinitha VView Answer on Stackoverflow
Solution 5 - GwtWillemView Answer on Stackoverflow
Solution 6 - GwtLargent803View Answer on Stackoverflow
Solution 7 - GwtMohamedView Answer on Stackoverflow