Selenium WebDriver WebTable getData: How to get a value of "td" if it is depends on another "td" - selenium

I am facing one issue where the value of a one particular cell(td) in a webtable depends on another cell (td)..
Example:
Use http://www.espncricinfo.com/new-zealand-v-australia-2015-16/engine/match/914239.html and click on Full score...
Now I want to get a batsmen name who is unbeaten (Need "Not out" batsman from New Zealand 1st Innings. In this case "TA Boult")
But "TA Boult" and "Not out" are 2 different td's of a same "tr".
Can someone please guide me how to achieve this?

The following XPath would solve this issue for you:
//table[contains(#class,"batting-table")][1]//td/a[.="TA Boult"]/../../td[#class="dismissal-info" and contains(text(), "not out")]
You may want to make the selector for the top table a bit more specific, but essentially this XPath is doing the following:
Find the first table that contains the classname "batting-table"
Get all the td elements within this table
Get all the a elements within the td elements
Specify that the a element's text must be the player you are searching form, in this case, TA Boult.
Use /../.. to select the parent of the parent of the a element that has the text "TA Boult". So if the parent of the a tag is td, the parent of the td tag is tr.
Now that we are in the row containing any matching a tags, we can search within this row for the td tag with the "dismissal-info" class that contains the text "not out".
From there you could then use /../.. again to return the entire row as the result of the XPath.
So essentially, you are searching for a row, then searching for a child, then searching for a parent, then searching for a different child and then returning a correct row.
Hope that helps!

Ok so...
//all tr elements.
IList<IWebElement> tableTRCollection = driver.FindElement(By.Xpath("//table[#class='batting-table innings']")).FindElements(By.TagName("tr"))
//in every tr all td elements will be:
IList<IWebElement> tableTDCollection;
foreach(IWebElement tr in tableTRCollection )
{
tableTDCollection = tr.FindElements(By.TagName("td"));
}
//in td collection take all td
foreach(IWebElement td in tableTDCollection )
{
string tdText = td.Text;
}
and so on...
after you get all the collections you can get everything.

Thank you all for answers.. I was able to find an answer after a lot of struggle, but found solution is almost same that Ben has suggested.
I did not try another suggested solution though..
Below is the code...
WebElement name = driver.findElement(By.xpath(".//*[#id='full-scorecard']/div[2]/div/table[1]//td[#class='dismissal-info'][contains(text(),'not out')]/ancestor::tr/td[#class='batsman-name']"));

Related

How can I check that a dropdown field is disabled using selenium?

I am trying to write a function in selenium to check if a Reasons dropdown is showing as disabled, but can't quite get the xpath right. The code for the dropdown is in the pic, the function I'm working on is the second one (InputDisabled), having based it on the working first one (SearchDisabled):
` public By SearchDisabled(string searchId) => By.XPath($"//div[#id='{searchId}']//div[contains(#class, 'v-input--is-disabled')]");
public By InputDisabled(string inputId) => By.XPath($"//div[#id='{inputId}']//div[contains(#class, 'v-input--is-disabled')]");`
The inputId going into it is 'ai-confirm-allergy-modal-reason'. I've tried it as 'input[contains...' and 'contains(#disabled, 'disabled'...' among other things, but my xpath knowledge isn't great yet!
dropdown code
Use below code
String value = driver.findElement(By.XPath("//input[contains(#id, 'ai-confirm-allergy')]").getAttribute("disabled");
Assert.AssertEquals(value, "disabled");
I do not quite get your question.
well if you are trying to use xpath to locate an element, you can just use the id; assuming that it is unique.so:
driver.findElement(By.xpath("//input[contains(#id, 'ai-confirm-allergy')]")
should locate the webelement.
However, your xpath for the SearchDisabled is locating a div containing class 'v-input--is-disabled' with in another div with id of '{searchId}';
the same logic goes for the next one. your xpath is trying to locate a div containing class 'v-input--is-disabled' which is located with in another div located using input id. I don't think this combination can locate the element highlighted in the picture.

Selenium find element next to another one

I need to find an element that is located next to another one depending to an if condition.
For example, I'm trying to retrieve the bottom with the word “Log In & Pay” only if I found the words ‘DANA’ before.
I can find the first element with text DANA in this way, but how can I find then the next botton element with the text “Log In & Pay” ?
driver.findElement(By.xpath ("//*[contains(text(), 'DANA')]"));
Below the Html page:
Get the span with the desired text, find the closest ancestor div which contains both els, find the el you want from there. i.e.
//span[contains(text(), 'DANA')]
//ancestor::div[#class='web-pay-wallet-inside-wrap']
//div[#class='action']
/div[contains(text()='Log In & Pay')]
try using nested predicates
//div[span[contains(text(), 'DANA')]]/following-sibling::div[#class='action']/div
Explanation
//div[span[contains(text(), 'DANA')]] finds the div which contains span with text DANA
following-sibling::div finds the following div at the same level
Selenium 4 introduces relative locators which allow to look up elements in relative position to others. Like:
above
below
right of
left of
and even "near"
You can find examples here.

Selenium finding elements returns incorrect elements

I'm using Selenium to try and get some elements on a web page but I'm having trouble getting the ones I want. I'm getting some, but they're not the ones I want.
So what I have on my page are five divs that look like this:
<div class="membershipDetails">
Inside each one is something like this:
<div class="membershipDetail">
<h3>
VIP Membership
</h3>
</div>
They DO all have this same link, but they don't have the same text ('VIP Membership' would be replaced by something else)
So the first thing was to get all the divs above in a list. This is the line I use:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
This gives me five elements, just as I would expect. I checked the 'class' attribute name and they are what I would expect. At this point I should say that they aren't all EXACTLY the same name 'membershipDetail'. Some have variations. But I can see that I have all five.
The next thing is to go through these elements and try and get that element which contains the href ('VIP Membership').
So I did that like this:
for elem in listElementsMembership:
elemDetailsLink = elem.find_element_by_xpath('//a[contains(#href,"EditMembership")]')
Now this does return something, but it always got me the element from the FIRST of the five elements. It's as if the 'elem.find_element_by_xpath' line is going up a level first before finding these hrefs. I kind of confirmed this by switching this to a 'find_elements_by_xpath' (plural) and getting, you guessed it, five elements.
So is this line:
elemDetailsLink = elem.find_element_by_xpath('//a[contains(#href,"EditMembership")]')
going up a level before getting its results? If it is, now can I make it not do that and just restrict itself to the children?
If you are trying to find element with in an element use a . in the xpath like below:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
for elem in listElementsMembership:
elemDetailsLink = elem.find_element_by_xpath('.//a') # Finds the "a" tag with respect to "elem"
Suppose if you are looking for VIP Membership:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
for elem in listElementsMembership:
value = elem.find_element_by_xpath('.//a').get_attribute("innerText")
if "VIP Membership" in value:
print(elem.find_element_by_xpath('.//a').get_attribute("innerText"))
And if you dont want iterate over all the five elements try to use xpath like below: (As per the HTML you have shared)
//div[#class='membershipDetail']//a[text()='VIP Membership']
Or
//div[#class='membershipDetail']//a[contains(text(),'VIP Membership')]
You've few mistake in that css selector.
Quotes are missing.
^ is for starts-with, not sure if you really need that. In case it's partial matching please use * instead of ^
Also, I do not see any logic for the below statement in your code attempt.
The next thing is to go through these elements and try and get that
element which contains the href ('VIP Membership').
Code :
listElementsMembership = driver.find_elements_by_css_selector("div[class*='membershipDetail']")
for ele in listElementsMembership:
e = ele.find_element(By.XPATH, ".//descendant::a")
if "VIP Membership" in e.get_attribute('href'):
print(e.text, e.get_attribute('href'))
You can give an index using a square bracket like this.
elemDetailsLink = elem.find_element_by_xpath('(//a[contains(#href,"EditMembership")])[1]')
If you are trying to get an element using XPath, the index should start with 1, not 0.

Get last element from several results with cssselector

So I have this CSS-selector query that returns several results:
div[class=b-folders] span[class=b-folders__folder]
And I want to get only the last one, I tried;
div[class=b-folders] span[class=b-folders__folder]:last-of-type
But nothing was found.
:last-of-type, :last-child and other relevant pseudo-classes/selectors check the element's position inside it's parent:
The :last-of-type CSS pseudo-class represents the last sibling with the given element name in the list of children of its parent element.
Instead, solve it using your selenium language bindings - get all elements matching the selector and get the last found element. For instance, in Python:
driver.find_elements_by_css_selector("div[class=b-folders] span[class=b-folders__folder]")[-1]
You can have an array list of elements and then select the last element by:
List<WebElement> elements= driver.findElements(By.css("css"));
element = elements.get(list.size() - 1);

Webdriver click second element in list

The page I'm testing has 2 elements with the same name and I need to click the second Element.
I can get the elements by using:
driver.findElements(By.linkText("Services"));
But I don't know how to click on the second element.
There are two ways to do this:
1) Using xpath, try in following manner.
driver.findElement(By.xpath("('xpath of the link')[2]"));//If you had given html, I could have added exact xpath.
2) Using findElements() you can try following:
List<WebElement> li = driver.findElements(By.linkText("Services"));;
li.get(1).click();//If there are only two such element, here 1 is index of 2nd element in list returned.
Hope you get the idea. :)
Or for short you can do
driver.FindElements(By.ClassName("drop"))[1].Click();
If you`re using python, you can try this way:
li = driver.findElements(By.linkText("Services"))[index].click()