0

I have an unordered list of list items containing elements for labels and values that are dynamically generated. I am trying to validate that the list contains a specific label with a specific value.

I am attempting to write an xpath that will allow me to find the parent element that contains the defined label and value with protractor's element(by.xpath). Given a list, I need to be able to find any single li by the combination of two descendants of specific attributes. For example, a li element that contains any descendent with class=label and text=Color AND any descendent with text=Blue.

<ul>
   <li>
      <span class='label'> Car </span>
      <p> Ford </p>
   </li>
<li>
      <span class='label'> Color </span>
      <p> <span>My favorite color is</span> : <webl>Blue</webl></p>
   </li>
<li>
      <span class='label'> Name </span>
      <p> Meri </p>
   </li>
<li>
      <span class='label'> Pet </span>
      <p> Cats <span>make the best pets</span> </p>
   </li>

I have tried several variations on the following pattern:

//li[.//*[@class="label" | contains(text(), 'Color')] | .//*[contains(text(), 'Blue')]

This is the closest I think I have come and it's coming back as not a valid xpath. I've been looking at references, cheatsheets, and SO questions for several hours now and I am no closer to understanding what I am doing wrong. Eventually I will need to replace the text with variables, but right now I just need to get my head around this.

a list item that contains, at any depth,
   any tag with a class of 'label' and text of x
   AND
   any tag with text y

Can anyone tell me what I am doing wrong? Am I just making it too complex?

Heather Frank
  • 135
  • 3
  • 8

2 Answers2

1

The reason you are getting invalid xPath is because:

The |, or union, operator returns the union of its two operands, which must be node-sets..

However since you have used inside one node you are getting issue. To meet your requirement below xpath will work just fine:

//*[@class="label" and contains(text(),'Color')]//ancestor::li//*[contains(text(), 'Blue')]
rahul rai
  • 2,260
  • 1
  • 7
  • 17
1

As per the HTML you have shared to locate the <li> element that contains a descendent with class='label' and text=Color AND any descendent with text=Blue you can use the following based Locator Strategy:

//li[./span[@class='label' and contains(., 'Color')]][.//webl[contains(., 'Blue')]]

Proof Of Concept:

XPATH

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352