How to write dynamic xpath for a webElement? - xpath

I have gone through from a lot of question on stackoverflow but didn't find the solution for my problem
-There is an element on webpage which has text= "Success"
Now I want to locate that element, id of the elements keeps changing. There are some other elements with a similar name say - successful, unsuccessful, successfully etc.. on the same page but I want to search the particular element "Success". How should I do it? In this case,
I don't think- startsWith() and contains() methods of XPath will work.

You can use the following xpath to find it. i) //[text()='Success'] or ii) //[.='Success'].

You can always use other attributes. You are not limited to id.
A few examples below:
Basic xpath syntax:
//tag[#tag-attribute='arrtibute-value']
//*[contains(#tag-attribute,'attribute-value')]
//tag[text()='inner-text']
//*[contains(text(),'inner-text')]
Where:
tag = the html tag
* = tag wildcard - matches any tag
tag-attribute = any attributes within the tag (name,id,class...)
attribute-value = the value of the specified tag-attribute
Consider this sample:
<div id="countryDiv1">
<button type="button" class="btn btn-default" data-toggle="dropdown" data-id="ConsignorAddressCountryId" tabindex="1" id="randomGenerated">Text1</button>
</div>
<div id="countryDiv2">
<button type="button" class="btn btn-default" data-toggle="dropdown" data-id="ConsignorAddressCountryId" tabindex="2" id="randomGenerated">Text2</button>
</div>
Here we have 2 buttons having the same random generated IDs but a few differences like tabindex, inner text, id of parent div.
Sample xpath(s) for button 1:
//button[#tabindex='1']
//button[#data-id='ConsignorAddressCountryId'][#tabindex='1']
//button[#data-id='ConsignorAddressCountryId'][text()='Text1']
//div[#id='countryDiv1']//button
Personally, I prefer using other attributes instead of text mainly because texts can have reserved characters that might mess up your xpath.
You can also check your xpath validity using the following:
Chrome Dev Tools (F12) > Elements Tab > Hit CTRL+F while under elements tab > paste your xpath > valid elements will be highlighted
Chrome Dev Tools (F12) > Console Tab > Enter: $x("yourxpath") > hit enter key > matching elements will be displayed on the console.

You can try following:-
//*[#text()='Success']

Related

XPath valid in Firefox but not in Chrome

I am trying to find a menu element via XPath in the JupyterLab UI; The following is an extract of the list of elements in the menu I am interested in, and should be a good minimal example of my problem:
<li tabindex="0" aria-disabled="true" role="menuitem" class="lm-Menu-item p-Menu-item lm-mod-disabled p-mod-disabled lm-mod-hidden p-mod-hidden" data-type="command" data-command="filemenu:logout">
<div class="f1vya9e0 lm-Menu-itemIcon p-Menu-itemIcon jp-Icon"></div>
<div class="lm-Menu-itemLabel p-Menu-itemLabel">Log Out</div>
<div class="lm-Menu-itemShortcut p-Menu-itemShortcut"></div>
<div class="lm-Menu-itemSubmenuIcon p-Menu-itemSubmenuIcon"></div>
</li>
<li tabindex="0" role="menuitem" class="lm-Menu-item p-Menu-item" data-type="command" data-command="hub:logout"><div class="f1vya9e0 lm-Menu-itemIcon p-Menu-itemIcon jp-Icon">
<div class="f1vya9e0 lm-Menu-itemIcon p-Menu-itemIcon jp-Icon"></div>
<div class="lm-Menu-itemLabel p-Menu-itemLabel">Log Out</div>
<div class="lm-Menu-itemShortcut p-Menu-itemShortcut"></div>
<div class="lm-Menu-itemSubmenuIcon p-Menu-itemSubmenuIcon"></div>
</li>
As you can see, both <li> items contain a <div> with the text Log Out, which is my main problem, as I am trying to write a general Xpath expression that can work for any Menu item. What I am currently trying to use is:
//div[contains(#class, 'p-Menu-itemLabel')][text() = '${item}']
Where ${item} can be any menu item, as all <li> items will have a similar div with text in them. The problem arises with the Log Out item, which is the only one that is repeated twice. In order to handle this special case, I have though of using
//div[contains(#class, 'p-Menu-itemLabel')][text() = 'Log Out']/..[not(contains(#class,'p-mod-hidden'))]
Since either one of the two <li> items will not contain that specific class (i.e., the currently active Log Out element).
This XPath works fine in Firefox and finds the element I am looking for everytime, however Chrome complains that it is not a valid XPath expression. Somehow this reduced version:
//div[contains(#class, 'p-Menu-itemLabel')][text() = 'Log Out']/..
works in Chrome, but any time I try to use an attribute selector on the parent element (i.e. /..[something]) it fails to recognize it as a valid XPath.
Does anyone have any idea of why? And what can I do to make Chrome recognize it as a valid XPath?
It seems that Chrome doesn't like applying a predicate directly from the .. parent axis.
But you can modify to use the long form: parent::*
//div[contains(#class, 'p-Menu-itemLabel')][text() = 'Log Out']/parent::*[not(contains(#class,'p-mod-hidden'))]
Or apply the self::* axis and then apply the predicate:
//div[contains(#class, 'p-Menu-itemLabel')][text() = 'Log Out']/../self::*[not(contains(#class,'p-mod-hidden'))]

Not able to select element using XPath

<div data-v-1dac319c="" class="ca-modal-header">
<span data-v-1dac319c="" class="ca-modal-header-title">New Claim Attachment</span>
<button data-v-1dac319c="" class="ca-modal-close material-icons">close </button>
</div>
I am unable to select the Close button using XPath.
Following is not working - //span[text()='New Claim Attachment']/following-sibling::button[text()='close']
Your XPath expression doesn't work because you have a small space at the end of your close . contains should work:
//span[text()='New Claim Attachment']/following-sibling::button[contains(., 'close')]
You can use this XPath:
//span[text()='New Claim Attachment']/..//button[contains(text(),'close')]
Or this:
//div[.//span[text()='New Claim Attachment']]//button[contains,text()'close')]

check condition to extract value from html response in jmeter

I'm new in JMeter, I'm working on one project on JMeter. where i have to extract value from HTML response depend on condition.
Actual data:
<li class="size size-item 159103">
<button id="productSizesAndGrid-btn-size-1" class="btn selection-button lowStock" data-skucode="159103" data-size="XS 8/10 " data-in-wishlist="false" data-stock-status-name="Low stock"> XS 8/10 </button>
</li>
I want to extract data-code but if data-stock="In stock".
data-stock can be out of stock as well so if data In Stock then and then only i want to extract that value.
I understand simple value extraction using regular expression extractor but couldn't understand how to do this.
when i working with this i realised there are disable data with same attribute and class
<li class="size size-item 159108">
<button id="productSizesAndGrid-btn-size-1" class="btn selection-button outOfStock disabled" data-skucode="159108" data-size="XS 8/10 " data-in-wishlist="false" data-stock-status-name="Out of stock"> XS 8/10 </button>
</li>
Edit:
I tried using below answer : it's not working in my case
Regular Expression : <button id="btnid" class="btn inStock" data-code="(.*?)"(.*?)data-stock="In stock">
Select the first template $1$
Using css selector:
#btnid
this works in my case now problem is i got two elements because both ids are same how to get specific element; i want second one as first one is disabled.
<button id="product-1" class="btn outOfStock disabled" data-code="123456" wishlist="false" data-stock="Out of stock" style="" css="1"></button>
<button id="product-1" class="btn inStock" data-code="123123" data-size="XS 8/10 " wishlist="false" data-stock="Low stock" style="" css="2"></button>
It works if you add 2 in Match No: 2
but i don't know it's correct way or not!
by above solution i still didn't get actual elements which are in stock if i get that then my problem solved but i have only temporary solution; i will appreciate if anyone can show me right way to do it.
Answer: below accepted answer work for me:
Match count: 13
Match[1]=
Match[2]=159109
Match[3]=159110
Match[4]=159111
Match[5]=159112
Match[6]=159103
Match[7]=159104
Match[8]=159105
Match[9]=159106
Match[10]=159107
Match[11]=
Match[12]=
Match[13]=
Don't use regular expressions for parsing HTML, they're hard to develop and maintain, moreover they're fragile and sensitive to markup changes.
I would recommend going for CSS Selector Extractor, the relevant CSS selector to match <button> tags where data-stock attribute is not Out of stock would be something like:
button:not([data-stock=Out of stock])
You need the data-code attribute
Demo:
To achieve this follow below steps:
Add Regular Expression Extractor as a child of the Sampler returning the Response
Regular Expression extractor setting as below:
Regular Expression : <button id="btnid" class="btn inStock" data-code="(.*?)"(.*?)data-stock="In stock">
Select the first template $1$
Proof of it working
Afterwards you can use ${dataCode} anywhere in the script.

How to get descendants with a specific tag name and text in protractor?

I have the following structure (it's just for sample). In protractor, I am getting the top element by id. However, the other elements do not have id's. I need to get the "label" element that contains the text '20'. Is there an easy way in protractor to select the element with a specific tag that contains a specific text from all the descendants of a parent element?
<pc-selector _... id="Number1">
<div ...></div>
<div ...>
<div ...>
<check-box _...>
<div _ngcontent-c25="" ...>
<label _ngcontent-c25="">
<input _ngcontent-c25="" type="checkbox">
<span _ngcontent-c25="" class="m-checkbox__marker"></span>
20 More text to follow</label>
</div>
</check-box>
</div>
</div>
</pc-selector>
I could't find anythitng, so I have tried with xpath, but protractor complains that my xpath is invalid:
parentElement = element(by.id('Number1'));
return parentElement.element(by.xpath(".//label[contains(text(),'20'))]"));
Any ideas?
You have an additional bracket in your [contains(text(),'20'))] which is likely causing you issue but there are multiple other ways this can be achieved using a single XPath or chaining other locators.
The process is that you must find the div with the correct id first and then locate the label that is a child of it.
//Xpath
element(by.xpath("//pc-selector[#id='Number1']//label[contains(text(),'20')]"));
//Chained CSS
element(by.id('Number1')).element(by.cssContainingText('label','20'));
You also may be interested to learn about xpath axes which can allow us to do very dynamic selection.
You can use the direct xpath to access the label.
element(by.xpath("//*[#id='Number1']//label"));

How to write xpath to select item that doesnot have aria-hidden="true"?

I need to click "Cancel" button. So I tried writing an x-path that looks something like this :
//button[text()='Cancel']
But two elements are identified since two elements match the conditions as below, though one of the element is hidden :
<button type="button" class="gwt-Button button_action_id_9135994370013188418_9135995360013188733_compositepopup_3 TableCtrl-button cancel-button">Cancel</button>
<button type="button" class="gwt-Button button_action_id_9149469526113774095_9149539697213772969 TableCtrl-button cancel-button" aria-hidden="true" style="display: none;">Cancel</button>
Is there a way I could identify the element that does not have a tag like 'aria-hidden' ?
Try to use below XPath to match required (not hidden button):
//button[text()='Cancel' and not(#aria-hidden='true')]

Resources