Selecting cousin element with XPATH - xpath

Given following markup
<div>
<a>Username1</a>
</div>
<div>
<button>Unblock</button>
</div>
<div>
<a>Username2</a>
</div>
<div>
<button>Unblock</button>
</div>
<div>
<a>Username3</a>
</div>
<div>
<button>Unblock</button>
</div>
How do I select button element which is a cousin of a element with text Username2?
I can select the a element with //a[contains(., 'Username2')], so I thought that //a[contains(., 'Username2')]/following-sibling::/div/button would select the correct button, but that does not work. I think that it's not even valid XPATH.

You were close:
//a[contains(., 'Username2')]/../following-sibling::div[1]/button
To navigate to the cousin you first have to go to the parent (..) and then to its sibling.
Note that the following-sibling:: axis selects all following siblings, not only the first one. This means you must use [1] if you just want the first.
This would also work:
//a[. = 'Username2']/../following-sibling::div[1]/button
So would this:
//div[a = 'Username2']/following-sibling::div[1]/button

Related

Click on a element with specific text

Alright, I have a item which has this class class="country" and there are 12 elements with the same class. Now I want to get a element on its value. For example Italy. And now I want to click on a link in this item. The class of the link is class="link". So basically I want to click the link of the item with the name Italy
My code at the moment:
cy.get('.country').should('have.text', 'Italy').click();
HTML
<div class="countries">
<div class="text">
<h3></h3>
<div class="country">Italy</div>
<h4>Yala</h4>
<p>test</p>
<a class="link" href="/mysite">Show details</a>
</div>
</div>
Should() is an assertion and won't select the element you want.
you probably want the contains() function.
cy.get('.country').contains('Italy').click()
Best

How to select the first occurrence in each element by XPath?

In the following html tags:
<div>
<div>
<h3>
<a href='http://Ali.org'></a>
</h3>
<div>
<p>
<a href='http://Mohammad.org'></a>
</p>
</div>
</div>
<div>
<h4>
<a href='http://Ali.org'></a>
</h4>
<p>
<a href='http://Mohammad.org'></a>
</p>
</div>
</div>
I want to select two 'a' tags 'http://Ali.org' & 'http://YaALi.org'. By the following, I can:
//div//a[not(parent::*[not(following-sibling::*)])]
But what about a simpler XPath?
By the following, all of 'a' tags will be selected since they are all the first child of their parents:
//div/div//a[1]
Or by the following, just the first 'a' tag will be selected:
(//div//a)[1]
I want to select 'a' tags that are the first in the 'a' tags of div elements...
// in the middle of a path is an abbreviation for descendant-or-self::node(), so if you do
//div/div//a[1]
this effectively means
//div/div/descendant-or-self::node()/a[1]
This picks the first child a of all descendant nodes. What you want is:
//div/div/descendant::a[1]
which will pick the first descendant a.

Need to select a checkbox, based on text in another div

<div class="bli-category">
<div class="row ng-scope" ng-repeat="placementtrack by $index">
<div class="col-sm-12">
<div class="col-sm-1 bli-category-checkbox">
<input class="bli-check-box ng-valid" type="checkbox" ng-click="addPlacement" ng-checked="checkedPlacementIndex" ng-model="selectedPlacement">
</div>
<div class="col-sm-8 bli-category-content">
<div class="ng-binding" ng-bind="placement.placementName">page_details</div>
</div>
</div>
</div>
I need to select the checkbox in class='bli-check-box ng-valid' for the text in class='ng-binding'
When I try to get the xpath like
//input[#class='bli-check-box ng-valid']
it selects all the 4-5 checkboxes
To select the checkbox in class='bli-check-box ng-valid' with respect to the text in class='ng-binding' i.e. page_details you can use the following xpath :
//div[#class='bli-category']//div[#class='ng-binding' and contains(.,'page_details')]//preceding::input[#class='bli-check-box ng-valid']
Note : As the element is an Angular element you have to induce wait for the element to be clickable before attempting to click.
//div[text='page_detials' and class='ng-binding']/../preceding-sibling::div//input[class='bli-check-box ng-valid']
The above xpath starts with finding the node which has the custom text that you know. It then traverses to its parent and then its previous sibling which in your case houses your required input node. So after traversing to the div you select its child which is your required input node.

Xpath: robust path for a locator of an element with 1 sibling and one...cousin?

This is the code:
<li>
<a>
<h1>Quorn StukĀ­jes</h1>
<p class="price">
</a>
<form>
<button type="submit">+</button>
</form>
</li>
I want to create a locator that finds the first <h1> that has an sibling element <p> with an attribute "price". Easy so far. But now I also want that <h1> to share its grandparent with a <button> class with the attribute type "submit".
What I created was the following:
//a/p[#class="price"]/preceding-sibling::p/preceding-sibling::h1
I'm wondering if this is the most sensible solution (it does work), or if there is something more elegant and robust.
(//*[form/button[#type = 'submit']]/*[p[#class = 'price']]/h1)[1] should do (assuming a submit button only makes sense in a form parent element).

xPath strange behaviour - selecting ALL elements even if [1] set

today I stumbled upon a very interesting case (at least for me). I am messing around with Selenium and xPath and tried to get some elements, but got a strange behaviour:
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some other text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some even unrelated text
</a>
</div>
</div>
</div>
This is my data.
When i run the following xPath query:
//div[#class="title"][1]/a
I get as a result ALL instead of only the first one. But if I query:
//div[#class="resultcontainer"][1]/div[#class="info"]/div[#class="title"]/a
I get only the first , not all.
Is there some divine reason behind that?
Best regards,
bisko
I think you want
(//div[#class="title"])[1]/a
This:
//div[#class="title"][1]/a
selects all (<a> elements that are children of) <div> elements that have a #class of 'title', that are the first children of their parents (in this context). Which means: it selects all of them.
The working XPath selects all <div> elements that have a #class of 'title' - and of those it takes the first one.
The predicates (the expressions in square brackets []) are applied to each element that matched the preceding location step (i.e. "//div") individually. To apply a predicate to a filtered set of nodes, you need to make the grouping clear with parentheses.
Consequently, this:
//div[1][#class="title"]/a
would select all <div> elements, take the first one, and then filter it down futher by checking the #class value. Also not what you want. ;-)

Resources