How to write xpath for a field and validate the fields - selenium

I have a requirement to verify field name and values. My code looks like
<div class="line info">
<div class="unit labelInfo TextMdB">
Reference #:
</div>
<div class="unit lastUnit">
701
</div>
</div>
</div>
<div class="line info">
<div class="unit labelInfo TextMdB">
Registered Date:
</div>
<div class="unit lastUnit">
05/05/2020
</div>
</div>
I gave my xpath as
"//div[#class='unit lastUnit']//preceding-sibling::div[#class='unit labelInfo TextMdB' and contains(text(),'Reference #:')]".
With this xpath I am able to reach "reference#" field . But how to verify reference # field is displaying the value (in this case 701) .
Appreciate your response.
Thanks

You can first reach the Reference # text by using its text in the xpath and then you can use following-sibling to fetch the div tag and then use getText()(java) / text (python) method to get 701.
(Edited answer after OP's comment)
If you want to check if the element is displayed on the page or not then you can fetch its list and check if the size of that list is greater than 0 or not.
You can do it like:
In Java:
List<WebElement> elementList = driver.findElements(By.xpath("//div[#class='line info']//div[contains(text(),'Reference #')]//following-sibling::div"));
if(elementList.size()>0){
// Element is present on the UI
// Finding its text
String text = elementList.get(0).getText();
}
In python:
elementList = driver.find_elements_by_xpath("//div[#class='line info']//div[contains(text(),'Reference #')]//following-sibling::div")
if (elementList.len>0):
# Element is present
# Printing its text
print(elementList[0].text)

Related

Python Selenium: If there are multiple "div" tags, how do print a specific one WITHOUT Xpath?

I am trying to learn how to print by tag. Cannot use find element by xpath or class. If there are 4 "div" tags, how do I print the contents of a specific one?
Desired Output:
vjs-poster
Attempt 1:
divs = driver.find_elements(By.TAG_NAME, "div")
print(divs[0])
Attempt 2:
divs = driver.find_elements(By.TAG_NAME, "div")
print(divs[0].get_attribute('class'))
HTML: (The third line says "vjs-poster" this is what I want to print.)
<video id="video_html5_api" class="vjs-tech" onclick="streaming();" src="/video/stream?cntId=21671&quality=sd"></video>
<div></div>
<div class="vjs-poster" tabindex="-1" style="background-image: url("https://[REDACTED].com/images/V15064/720X480/720x480/nt/4.jpg");"></div>
<div class="vjs-text-track-display vjs-hidden" aria-live="assertive" aria-atomic="true"></div>
<div class="vjs-loading-spinner" dir="ltr"></div>
To print the value of the class attribute vjs-poster of the second <div> you can use:
print(driver.find_elements(By.TAG_NAME, "div")[1].get_attribute('class'))
You can also use a css_selector as:
print(driver.find_element(By.CSS_SELECTOR, "video.vjs-tech#video_html5_api +div +div").get_attribute('class'))
You can try locating that element based on it class name and style or any one of them if the locator will still be unique.
You try this:
class_val = driver.find_elements(By.XPATH, "//div[contains(#style,'https://[REDACTED].com/images')").get_attribute('class')
print(class_val)

How to find xpath of an element which depends upon sibling class

I have below html code
<a class = sidetoolsdivider>
<div class = sideone > Test 1 </div>
<div class = sidetwo> </div>
</a>
<a class = sidetoolsdivider>
<div class = sideone > Test 2 </div>
<div class = sidetwo> </div>
</a>
...............
Here I need to find xpath locator of class sidetwo which has text Test1. There are many such similar classes hence you can differentiate between different only based on element text
The xpath would be something like below:
Since the element depends on the text, can make use of text attribute for the same.
//div[text()='Text1']/following-sibling::div
Or
//div[contains(text(),'Text1')]/following-sibling::div
Or
//div[contains(text(),'Text1')]/following-sibling::div[#class='sidetwo']
Link to refer - Link
This gets you the correct 'a'. Find an 'a' which contains the right div of sideone (note the .//, find a Child which is)
"//a[.//div[ #class='sideone" and text()='Test 1']"
Then just get the side two, complete xPath
"//a[.//div[ #class='sideone" and text()='Test 1']//div[#class='sidetwo']"
Works even if there is more text inside the entire 'a' and stuff gets complex with more elements inside.

No such element Exception. class name with double__

I am trying to get the text under the tag. That is Arduus, Gstaad, Switzerland. I tried with the classname and also with xpath.
driver.findElement(By.className("chalet-details__title"));
String chaletTitle = driver.findElement(By.xpath("//div/h1[#class='chalet-details_title']")).getText();
But its giving NoSuchElementException. The classname has double underscore(__) .Is it because of that not working? Can anyone help me with this?
<div class="col-md-12 col-sm-12 col-xs-12">
<h1 class="chalet-details__title">
<span class="chalet-details__title-property">Arduus</span>,
<a class="chalet-details__title-resort" href="/ski- resorts/switzerland/gstaad">Gstaad</a>,
<a class="chalet-details__title-country" href="/ski- resorts/switzerland">Switzerland</a>
</h1>
<div class="chalet-details__rating">
<div class="chalet-details__wrapper">
<span class="chalet-details__star" style="width: 108px;"></span>
<span class="chalet-details__mask"></span>
</div>
</div>
</div>
You can try something like:
driver.findElement(by.cssSelector("h1.chalet-details__title"))
I just tried this and it worked fine with the provided html, if this still fails for you, can you verify that there aren't any iframes on the page.
Both your locators are OK, but you might need to wait for your element to be present in DOM:
WebDriverWait wait= new WebDriverWait(driver,20 );
String chaletTitle = wait.until(ExpectedConditions.presenceOfElementLocated(By.className("chalet-details__title"))).getText();
Another reason for NoSuchElementException: your element could be located inside an iframe, so you need to switch to that frame before handling target element:
driver.switchTo().frame("iframeNameOrId");
If it has no attributes as id or name:
WebElement someFrame = driver.findElement(By.xpath("//iframe[#someAttr='someValue']"));
driver.switchTo().frame(someFrame);
To get all the text under h1 tag find all elements using locator as follows:
List<WebElement> items = driver.findElements(By.cssSelector("h1.chalet-details__title > *")); //it will find all elements immediately under the h1 tag
Now, iterate over the elements.
Complete code:
List<WebElement> items = driver.findElements(By.cssSelector("h1.chalet-details__title > *"));
for(WebElement item : items){
System.out.println(item.getText());
}

Any suggesstions to locate the below elements in Selenium

Example HTML below. I want to locate the elements which contains the text Person Attributes and Age.
<div id="ext-gen210" class="x-tool x-tool-toggle"></div>
<span id="ext-gen214" class="x-panel-header-text">Person Attributes</span>
</div>
<div id="ext-comp-1071" class=" DDView ListView" style="height: auto;">
<p class="dragItem "><i class="icon-Gen"></i>Age</p>
</div>
Note: I am looking for a solution without using xpath or id or className as they might change with every new release of my website.
I tried to locate them using
'name' --> By.name("Person Attributes") and By.name("Age") but both failed.
By.name would check for the name attribute. What you need is to check the text of an element using By.xpath:
By.xpath('//div[span/text() = "Person Attributes"]')
Or, you can also check that an id element starts with ext-gen:
By.xpath('//div[starts-with(#id, "ext-gen")]')

Not finding the Correct xpath

I'm trying write a Python script to get some information from Google's products listed on the top right of the screen. (Usual 6 pictures with price and seller)
I am using Python, PhantomJS and Selenium
Doing a google search for "red shoe" I want my script to return the prices. I get stuck in the step where I try to even find the element containing the products. Am I missing something with my xpath?
def getTopSongs(object):
print "Working YETI"
browser = webdriver.PhantomJS('c:/projects/phantomjs/phantomjs.exe')
browser.get('http://google.com/search?q=red+shoe')
time.sleep(5)
title = browser.find_element_by_xpath('//div[contains#class, "pla-unit")]/text()[contains(., "red")]/following::b').text
From Google's webpage I element under a few nested
<div id="rhs">
...
<div class="_Pwb">
<div class="_Ohb">
<div style="width:109px" class="pla-unit">
<div class="_PD">
<div class="pla-unit-img-container">
<div class="_Z5">
<div class="_vT"><a href="http://www.somewebsite.com">
<span class="rhsl4">Nina 'Forbes' Peep Toe Pump <b>Red</b> R...</span>
<span class="rhsg3 rhsl5">Nina 'Forbes' Peep Toe Pum...</span>
<span class="rhsg4">Nina 'Forbes' Peep Toe Pu...</span></a>
</div>
<div class="_QD"><b>$78.95</b></div>
<div class="_mC">
<span class="rhsl4 a">Nordstrom</span>
<span class="rhsg3 rhsl5 a">Nordstrom</span>
<span class="rhsg4 a">Nordstrom</span>
</div>
</div>
*Update:
I added more HTML. In this example I am looking to get the text from ($78.95) annd (Norstrom)
*Update
To clarify,
<div id="rhs">
is an unique element
There are however multiple (6) elements of:
<div style="width:109px" class="pla-unit">
The elements under each category have the same name and follow the same structure and substructures
ie, there are 6
<div class="_PD">
<div class="pla-unit-img-container">
<div class="_Z5">
<div class="_vD">
<div class="_QD">
<div class="_mC">
and so on.
The main objective is to get all of the elements but for purposes of debugging I was asking help to get the first one.
The xpath for a price unit using XPathChecker on Firefox is:
id('rhs_block')/x:div[1]/x:div/x:div/x:div/x:div[1]/x:div[1]/x:div[2]/x:div[2]/x:b
You can use ancestor:: to go back up then following-sibling:: to get elements at the same level that follow it.
I haven't tried this but give it a shot:
title = browser.find_element_by_xpath('//div[contains#class, "pla-unit")]/text()[contains(., "red")]/ancestor::div/following-sibling::div[1]').text
Then to get to your div class ='mC' you just change:
following-sibling::div[1]
to
following-sibling::div[2]
and get the text from the spans under that.