How to match xpath for id element that changes each time page loads? - selenium

I have these 2 xpath that are different each time I load a webpage.
The xpaths were recorded by Selenium-IDE and always have mainForm_view within the id string and the text before and after this always changes.
xpath=//input[#id='abc_hyd_wuu2_8333nd_mainForm_view_jjd_uueue2_jjd_11_jkdhd']
xpath=//div[#id='abc_hyd_wuu2_8333nd_mainForm_view_kcjjcs_sjsjs_jjdj_994_kkk']/div/div[2]/div/div/div/a[1]/h2
I've tried to locate the id like below but doesn't work.
xpath=//input[contains(#id,'mainForm_view')]
xpath=//div[contains(#id,'mainForm_view')]
Which would be the correct way to do it?
Thanks in advance.
UPDATE
I've tried with CSS selector like below but it seems is taking another id that is within an input element
document.querySelector("input[id*='mainForm_view']").id
Examining the html code I see that the id I need is related with a unique class. The code is like below:
<div class="Class_p2">
<div class="Class_p3" style="...">
<input name="8333nd$mainForm$view$jjd$uueue2" type="text" class="class a1 n1-Control" value="xyz" id="8333nd_mainForm_view_jjd_uueue2" disabled="disabled" style="..">
</div>
<input name="8333nd$mainForm$view$ttyi" type="text" disabled="disabled">
</div>
I've tried the following Javascript code in Chrome console but it doesn't work
document.getElementsByClassName("class a1 n1-Control").id
How would be to get the id=8333nd_mainForm_view_jjd_uueue2 that is related with Class=class a1 n1-Control?
UPDATE2
I was finally able to do it with
document.getElementsByClassName("class a1 n1-Control")[0].id
Thanks for all the help and time.

You can write css selector as :
input[id*='mainForm_view']
for div it'd be :
div[id*='mainForm_view']
Asterisk is to match the sub string part.
Note that if any id contains mainForm_view that will also be selected, so better to check in developers tool before proceeding.

You can try finding some other element for which xpath/css locator remains same and then try to reach to this element by traversing from there. You can use parent, ancestor, preceding-sibling, following-sibling keywords in order to traverse. Hope it helps :)

Related

How to use scriptAll to grab all values when the intended value is not text type

I have a page with multiple textboxes and dropdowns with values that I am trying to validate. The values in them will be dynamic in each run.
The HTML looks something like:
<input readonly="readonly" class="form-control valid" data-val="true" data="ABC" aria-invalid="false" xpath="1">
What I want to do is grab the value of "data" for each textbox. I have used scriptAll before in such a case when I was grabbing text by using innerText. However, that won't work with a regular value such as in the HTML above.
I did try one solution that worked:
driver.value(//input[#data])
However, that just grabs the first textbox value, is there a way I can combine scriptAll with driver.value? OR would I be better off doing some JS here?
Thank you in advance!
Yes, refer the docs for scriptAll(): https://github.com/karatelabs/karate/tree/master/karate-core#scriptall
Use whatever JS works to get an attribute value. Haven't tried, but this should work, you get the idea:
* def list = scriptAll('input', "_.getAttribute('data')")

Selenium XPath find element where second text child element contains certain text (use contains on array item)

The page contains a multi-select dropdown (similar to the one below)
The html code looks like the below:
<div class="button-and-dropdown-div>
<button class="Multi-Select-Button">multi-select button</button>
<div class="dropdown-containing-options>
<label class="dropdown-item">
<input class="checkbox">
"
Name
"
</label>
<label class="dropdown-item">
<input class="checkbox">
"
Address
"
</label>
</div>
After testing in firefox developer tools, I was finally able to figure out the xPath needed in order to get the text for a certain label ...
The below XPath statement will return the the text "Phone"
$x("(//label[#class='dropdown-item'])[4]/text()[2]")
The label contains multiple text items (although it looks like there is just one text object when looking at the UI) in the label element. There are actually two text elements within each label element. The first is always empty, the second contains the actual text (as shown in the below image when observing the element through the Firefox developer tool's console window):
Question:
How do I modify the XPath shown above in order to use in Selenium's FindElement?
Driver.FindElement(By.XPath("?"));
I know how to use the contains tool, but apparently not with more complex XPath statements. I was pretty sure one of the below would work but they did not (develop tool complain of a syntax error):
$x("(//label[#class='dropdown-item' and text()[2][contains(., 'Name')]]")
$x("(//label[#class='dropdown-item' and contains(text()[2], 'Name')]")
I am using the 'contains' in order to avoid white-space conflicts.
Additional for learning purposes (good for XPath debugging):
just in case anyone comes across this who is new to XPath, I wanted to show what the data structure of these label objects looked like. You can explore the data structure of objects within your webpage by using the Firefox Console window within the developer tools (F12). As you can see, the label element contains three sub-items; text which is empty, then the inpput checkbox, then some more text which has the actual text in it (not ideal). In the picture below, you can see the part of the webpage that corresponds to the label data structure.
If you are looking to find the element that contains "Name" given the HTML above, you can use
//label[#class='dropdown-item'][contains(.,'Name')]
So finally got it to work. The Firefox developer environment was correct when it stated there was a syntax problem with the XPath strings.
The following XPath string finally returned the desired result:
$x("//label[#class='dropdown-item' and contains(text()[2], 'Name')]")

Unable to retrieve the text inside the div tag even when the tag is identified

I am trying to retrieve the text embedded inside the div tag. Partial html code is given below. I consulted the other existing answers, but the tag is located successfully but the text is coming back as empty string.My purpose is to retrieve the string between the 'div' tag as "You entered an invalid username or password, please try again."
I used the xpath
//div[#class='login-card js-login-card']/div[#role='alert']/div[2]
I used the css
.alert__heading.js-alert--error-text
This only getting back the tag name as div, but the text as an empty string.
Any ideas or corrections?
<div class="login-card js-login-card">
<div class="login-page__alert alert alert--error tt js-alert--error" role="alert">
<div class="alert__icon">
<div class="alert__heading js-alert--error-text">You entered an invalid username or password, please try again. </div>
</div>
<div id="cmePageWrapper" class="page-wrapper page-wrapper--card"> </div>
Try following xpath, as the required div tag is child node of div with class 'alert__icon':
//div[#class='login-card js-login-card']/div[#role='alert']/div[1]/div
Let me know, if it works for you.
Maybe you wanna try this
div[class*="error-text"]
If it didn't work try to get text by executing javascript code using this
$$( "div[class*="error-text"]" ).text() OR .val()/.html()
Good luck !
You could use contains with xpath, something like //div[contains(#class, 'error-text' ) ], using findelement will retrieve first element match the criteria. If it still returns empty, it means that the page might have more than one element which match the criteria

Selenium WebDriver : Not able find xpath for Paytm.com , Proceed button

I was trying to automate paytm.com site ,
Here i found Proceed button attribute has name but when i tried to use xpath checker for the name attribute , it was showing 13 matches but my question here is in the webpage from the UI level am not able to see 13 Proceed buttons instead only one Proceed button are present .
Even i tried with other attribute to find the xpath , but it showing more matches found.
Below is the HTML code for Proceed
<div class="msg-container">
<div class="btn-spinner" alt="Proceed to Recharge">
<div class="spinner hidden"></div>
<input class="btn proceed active" type="submit" data-express-text="Recharge Now" data-soft-block-text="Proceed anyway" data-default-text="Proceed" name="Proceed" value="Proceed" alt="Proceed to Recharge">
Can you please let me where am going wrong ?
This xpath returns 1 match for me
//form[#id='prepaidMobile']//input[#name='Proceed']
Also, if want use only //input[#name='Proceed'] you can get it from List of WebElements:
WebElement firstInput = driver.findElements(by.xpath("//input[#name='Proceed']"))[0];
This will work for you, I think:
driver.findElement(By.xpath("(//input[#name='Proceed'])[1]")));

Span id not found in Selenium IDE

I am using Selenium IDE and need to store a span id value:
<span id="ustData"
data-itemId="2130078"></span> <div class="clear"></div>
</div>
I want to store the value "2130078". This value changes for each page but is not visible. I have looked far and wide for a solution.
Currently using xpath location:
StoreAtribute
//data-itemId[#span='ustData']
From documentation I have read this seems correct?
When I run the test I get: [error] Element //data-itemId[#span='ustData'] not found
Any help would very much appreciated.
Your XPath should be:
//span[#id='ustData']
to match your span tag with an id attribute of 'ustData'
Then if you want to get the data-itemId attribute you can do:
//span[#id='ustData']/#data-itemId