1

I am a beginner test automator and I've been using direct XPATH references so far.
Now, I have the task of counting list items in a list that has no name.
I can copy the xpath using Chrome inspect but that path is very brittle. Any addition of element above it will make the path invalid. Looking for a more intelligent way to find the list.
I am using Selenium-JUnit-GeckoDriver.
Here is an example of my raw data:

...
<div class="entry-content" itemprop="text"><h3></h3>
<p>&nbsp;</p>
<p>texttexttexttexttexttexttexttext</p>
<p>&nbsp;</p>
<h4 class="p1"><span class="s1">List ONE</span></h4>
<hr>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<h4 class="p1"><strong><span class="s1">List TWO</span></strong></h4>
<hr>
<ul>
<li>d</li>
<li>e</li>
</ul>
...

In my existing (and inadequate code), I do something like:

// Find the text input element by xPath (from chrome inspect)
WebElement element = driver.findElement(By.xpath("//*[@id=\"main\"]/div/div/main/article/div[3]/div[1]/ul[1]"));
List<WebElement> listItems = element.findElements(By.tagName("li"));

... and then I do my test on the list items.

How can I automate something like a method, where I give it a search string ("List ONE") and it returns all list items of the preceding list? (but not the list items of "List Two")?

DraxDomax
  • 1,008
  • 1
  • 9
  • 28
  • You may find [this post helpful](https://stackoverflow.com/questions/33939198/selenium-webdriver-finding-elements-using-cssselector-and-nth-child). It uses css selectors instead of xpath. And makes it fairly simple to get children of nodes – Ron Norris Oct 19 '17 at 11:10
  • Honestly, it is impossible because `List One` and the items don't have a common parent. – Buaban Oct 19 '17 at 11:12
  • @Buaban, I think they might have a common parent... They are inside div, which is inside article and so on... – DraxDomax Oct 19 '17 at 15:12

1 Answers1

1

Just because I'm more familiar with it, I would use a CSS Selector here. Assuming that the order of the lists doesn't change, and the lists of interest are inside that div, the CSS selector for the first list would be:

div.entry-content > ul:nth-of-type(1)

If you really want to stick with XPath, I was able to select the second list using the following:

/div[contains(@class, "entry-content")]//span[contains(text(), 'List TWO')]//parent::*/parent::h4/following-sibling::ul[1]

here we find the div that contains the lists, the heading that contains our target list, then the very first ul list element that follows the selected h4.

Breaks Software
  • 1,721
  • 1
  • 10
  • 15
  • This was so promising for List One but I couldn't hack it to work for List Two – DraxDomax Oct 19 '17 at 15:11
  • 1
    that List Two has that extra "strong" element. I've updated the XPath above to something that works. I don't know how efficient it may be. – Breaks Software Oct 19 '17 at 17:02
  • Took me an hour to figure out why is your solution returning 0. It looks logical, all my testing tools find the right parent but my test fails. This was because I had the test set at counting the number of
  • !!! Therefore, all I needed to do is add: /following-sibling::ul[1] to get from the NOW CORRECT parent back down to the list items. Yes, this is quite a lot of back and forth but the test is going to be run alone, rarely. Please update and I will pick your answer.
  • – DraxDomax Oct 19 '17 at 22:11
  • BTW, I owe you a big one, do you want to be friends? – DraxDomax Oct 19 '17 at 22:12
  • Sorry about that @DraxDomax! I just forgot to add that part back after fiddling around to be sure that I got the correct h4 element. Glad that it helped! – Breaks Software Oct 20 '17 at 11:34