Selenium find element next to another one - selenium

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.

Related

selenium python how to find and click element that change everytime

im trying to find an element with dinamic values , for example <span class="ms-Button-label label-175" id="id__177">Save</span> in inspect element, the id and class values tend to change for every refresh, how can i in this case find the element in selenium? i tried troguht xpath but seems doesnt work because can not find the path, i was thinking to find "Save" world torught always find by xpath but actually i dont know if im doing well : driver.find_element_by_xpath(//span(#.... but then? how can insert element if it changes everytime? thanks!
Something like this may work:
driver.find_element_by_xpath('//span[text()="Save"]')
But this will fail, if there is more than one button with text "Save" on the page.
In that case you may try to find some specific outer element (div, form, etc.) which does not change and contains the button. Then find the button inside of it.
With few requests with driver:
specific_div = driver.find_element_by_id("my_specific_div")
button = specific_div.find_element_by_tag_name("span") # e.g. there is only one span in that div
Or with more specific xpath:
button = driver.find_element_by_xpath('//div[#class="some-specific-class"]/span[text()="Save"]')
If needed, search for more nested elements before the button, so you can get more narrow search field.
More examples in the docs.

How to move to sibling in selenium

I have this code in html. and I want to go to a sibling node.
I search by title (since this is a unique value in the UI), but I want to move to the same level but with different class name that will contains ant-select-tree-switcher_close.
This is the xpath to what is marked, and I just want to move in the same level for the first span, but without span1, or any hard coded solution. I want to search by class name that contains the words ant-select-tree-switcher_close as some text in the class name.
the xpath is:
//*[#title='Arts/Ent'] this is marked in yellow
I want to go to the purple section regards
You can use preceding-sibling
//*[#title='Arts/Ent']/preceding-sibling::*[contains(#class, 'ant-select-tree-switcher_close')]
If you want to use the 'Arts/Ent' WebElement to locate the sibling you can use
./preceding-sibling::*[contains(#class, 'a')]

How to locate links from Google results

Scenario:
open "google.co.in".
click in the search input box.
type something.
click Enter.
get the text of all links.
The xpaths of some links are:
.//*[#id='rso']/div[2]/div/div[2]/div/div/h3/a
.//*[#id='rso']/div[2]/div/div[3]/div/div/h3/a
.//*[#id='rso']/div[2]/div/div[4]/div/div/h3/a
.//*[#id='rso']/div[2]/div/div[5]/div/div/h3/a
.//*[#id='rso']/div[2]/div/div[6]/div/div/h3/a
All the xpaths have the same pattern. the third div needs to be incremented by 1 to get the next xpath. I've read somewhere that in the scenarios like this generic xpath can be used. According to his suggestion, the xpath will be ".//*[#id='rso']/div[2]/div/div/div/div/h3/a". just removed the predicate of the third div. This is not working. Is this the way to locate elements?
You can try below XPath to fetch all result links:
//div[#class="g"]//h3/a
If you want to avoid links from "People also ask" block:
//div[#class="g"]//h3/a[not(ancestor::div[#class="_OKe"])]

How to click an element with reference to another web element in Selenium WebDriver(Java)?

There are many span tags as mentioned in the image below and each has its own a-tag with unique id as "chooseitem". I need to choose particular a tag using names in the span tags.
Need to click the a-tag button using the text Mayo Chicken from the above HTML snippet in the image.
I have tried the below Selenium script
WebElement select = driver.findElement(By.xpath("//*[contains(text(),'Mayo Chicken (Single)')]"));
WebElement add = select.findElement(By.id("chooseitem"));
It doesn't work for me.
driver.findElement(By.id("chooseitem"));
The above code chooses the first item in the page by default as its id is also 'chooseitem', but need to define what to be chosen.
Can anybody help me out?
We need to get the common parent(ancestor) element of the chicked and the clickable 'a' tag, then we can navigate to the tag 'a'. Below xpath should ideally work.
"//span[contains(text(),'Mayo chicken')]/ancestor::div[4]//a"
Note: Here i have used div[4] because fourth parent is the common ancestor for 'Mayo chicken' and tag 'a'.
For more details about different xpath axis refer this->https://www.w3schools.com/xml/xpath_axes.asp
Hope this helps you. thanks.
You can do that by using the xpath position, press F12 for developer tools click on "Select element button", click the element that interests you on the page, as in your picture you will see one or more lines highlighted, right click the line -> Copy -> Copy xpath. You will have something like the line below:
//*[#id="comment-76500216"]/td[2]/div/span[1]
The xpath position will be:
//td[2]/div/span[1]
You can use that when you have multiple elements that share the name or id or so on.
And you will have:
WebElement select = driver.findElement(By.xpath("//td[2]/div/span[1]"));
PS: I used google chrome

Using an OR condition in Xpath to identify the same element

I have this logic which gets the current page's title first clicks on next button, fetches the title again and if both the titles are the same, meaning navigation has not moved to the next page, it clicks on Next again.
However, my problem is that the title element's Xpath differs - the same title element has two Xpaths. One is some pages the other in some other pages.
It is either this,
(.//span[#class='g-title'])[2]
OR
.//span[#class='g-title']
So, how can I handle this?
If the element has two xpath, then you can write two xpaths like below
xpath1 | xpath2
Eg: //input[#name="username"] | //input[#id="wm_login-username"]
It will choose any one xpath
You can use or operator like
(.//span[#class='g-title'])[2] or .//span[#class='g-title']
For more details : Two conditions using OR in XPATH
You can use or, like below:
//tr[#class='alternateRow' or #class='itemRow']
I had an interesting insight I had using this method. In my python code I was clicking a cart button and the or "|" ONLY works with separate xpath statements like so ...
WebDriverWait(webdriver,20).until(EC.visibility_of_element_located((By.XPATH,"//*[#class='buttoncount-1'] | //button[contains(text(), 'Add to Cart')]")))
or
btn = webdriver.find_element_by_xpath("//*[#class='buttoncount-1'] | //button[contains(text(), 'Add to Cart')]")
I found that "or" ONLY works when they share the same bracket []
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(text(), 'Add to Cart') or contains(text(),'Buy')]"))).click()
And since you're here. If you're curious about "and" statements this worked for me...
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//button[contains(text(), 'Continue To Order Rev')][#data-attr='continueToOrderReviewBtn']"))).click()
Simply pairing two separate statements was sufficient. No "and" necessary.
Note: This was all in python. I do not know how this will transfer over to java. Hope this was somewhat useful. It took me a few migraines to narrow this down.