Blogs

CPSAT Blog Series : findElements, HREF and InnerText properties, String conversion and sorting Checks

Problem Statement: findElements hrefs & InnerText properties + string Conversion and sorting checks

Many a times we have to fetch more than one element and then in a loop work on verifying the content.

  1. How to use different element properties for solving the test scenarios
  2. Using language specific string to integer conversions, string handling and also sorting mechanisms, augmenting selenium power to solve our testing goals

Problem case study

The case study is taken from https://www.crossword.in
Let us define the testing goal which will help in giving a practical twist to our problem statement

  • Open site https://www.crossword.in/
  • Choose “Books” from tabs visible (we would like to confirm the number of books found)
  • Click on Price: Sort by Price: high to low from the dropdown
  • We want to ensure that the books are indeed sorted on price high to low (Test)

This is how actually most CPSAT practical exam questions are constructed, where participants have to solve real life problem statements applying Selenium and language specific learnings.
Following screen shots (Image1.jpg) help define the case study

 

Solution

Let us try to solve the case study step by step

Step 1 – Locator strategy

We need to get the locator for the book menu
Using google chrome – when the book menu is inspected, the xpath provided by chrome is as below
//*[@id=”nav-menu-915599″]/ul/li[2]/a
The element is
<a href=”/books” class=” “>Books</a>
Let us try constructing custom xpath – both the following custom xpath also works
//a[contains(text(),”Books”) and @class=” “]
//li[2]/a[contains(text(),”Books”)]

Once we click on the books, We would also need locator for the select dropdown
Both of the following xpath locators will work
//div/select
//*[@id=”sort_type”]   ->> is given by chrome inspect
Once we are able to click on high to low drop down the books are displayed.
Incidentally there is no cost or price of the book that is displayed on the page.
Please see the screenshot below

The goal is to check or ensure that the books are really shown in the high to low price order.
This is where we have two approaches to proceed

  1. Approach A, This is what a manual tester would take. It would start with clicking on the book, going to the book page, keeping a note of the book price and then doing it again for next few books and verifying if the book order is as per the high to low price. When we do it in automated manner we would do the same, it would start with fetching all the book elements one by one, getting their hrefs (the book pages), going to the book page and then extracting the individual book price and keeping a track in some list and then checking if the price is correctly sorted in high to low order.
  2. Approach B, we would look for some other means of finding if the page contains the book price in some hidden elements and then using the same checking if the order of the book displayed is proper or not (High to Low)

Step2 – Approach A – going the manual testing way

We would need to do the following

  • Find all the books on the page
  • Get their hrefs
  • Visit the book page
  • Get their price
  • Store the same in a list or a data structure of choice
  • Check if the high to low sorting order is maintained

The locator should be such that it gives all the book elements having href of the books
A quick inspect on the first three books shows the following xpaths
//*[@id=”search-result-items”]/li[1]/div/div[1]/a
//*[@id=”search-result-items”]/li[2]/div/div[1]/a
//*[@id=”search-result-items”]/li[3]/div/div[1]/a
We can easily replace li[1] , li[2], li[3] with li[*] – it will give all the books.
Please see the following image

 
And then on visiting the page, the following xpath is able to give the price, checked with the first two books
//*[@id=”pricing_summary”]/div/div[2]/span/span

Step 2 – Approach B – Looking at alternative ways to fetch the price of the books

A closer look at the elements while inspecting the book element, reveals that there is another sibling node“Price”
Please see the image below

The element code is as below
<span class=“price”> <span class=“variant-final-price”> <span
class=“m-w”><span class=“m-c c-inr”>Rs.</span>38,750</span>
</span>
</span>
The child node has a class name variant-final-price, and it has an inner span and a text which shows the correct price.
We can use the following xpath to browse through all the elements such that we can get the price.
//*[@class=”variant-final-price”] , better is to use //*[@class=”variant-final-price”]//*[@class=”m-w”]

The only challenge is that the element is a hidden element and the normal getText() method does not work.
The attribute innerText has to be used.
Please check the properties section of the chrome devtool tab – image below
The entire code is shared in the section below

We will have to use getAttribute(“innerText”) to get the price.

Step 3 – Final Code for approach A

The code takes care of string to integer conversions, including using substring and also replacing characters. Sorting using collections.sort() and collections.reverse() methods are being used. ArrayList is the preferred collection object which is being used in the code below. Please see the entire code below, it has enough comments for you to understand. At the same time the code can be downloaded from the dropbox link provided below.
====================================================
[gdlr_code title=”CrossWordExerciseMethodA.java” active=”no”]
package cpsatblogs;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeTest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
/*
* CPSAT Program
* Exercise on Crossword
*
* Open site https://www.crossword.in/
* Choose “Books” from tabs visible
* Display number of books found
* Click on Price: Sort by Price: high to low icon
* Ensure that the books are indeed sorted on price high to low
* Solution – A
* is implementing automation the way the manual testing team will check
* hence this is a preferred method
* We can also take screen shots of the individual book price if we want
* Coverage
* How to fetch multiple elements
* How to act on these elements in a loop
* how to extract integer from strings
* how to use collections.sort and reverse in order for doing sorting check
* use testNg assertTrue
*
*/
 
public class CrossWordExerciseMethodA {
 
WebDriver driver;
WebDriverWait wait;
@Test
public void crossWordtest() throws IOException, InterruptedException {
 
wait.until(ExpectedConditions.titleIs(driver.getTitle()));
//Selecting book from home page
WebElement booklink = driver.findElement(By.xpath(“//li[2]/a[contains(text(),’Books’)]”));
booklink.click();
 
//Navigating to books page
String expTitle = “Books”;
wait.until(ExpectedConditions.titleContains(expTitle));
 
// get the total number of titles
// //*[@id=”search-results”]/div[2]/div[1]/span[1]/text()
 
String strTotalBooks = driver.findElement(By.xpath(“//*[@id=\”search-results\”]/div[2]/div[1]/span[1]”)).getText();
 
System.out.println(“strTotal books = ” + strTotalBooks);
// Do a substring from the first space
strTotalBooks = strTotalBooks.substring(strTotalBooks.indexOf(” “)+1);
 
//remove any space
strTotalBooks = strTotalBooks.trim();
 
System.out.println(“strTotal books = ” + strTotalBooks);
 
// Do a substring now from start to the second space
strTotalBooks = strTotalBooks.substring(0,strTotalBooks.indexOf(” “));
 
System.out.println(“strTotal books = ” + strTotalBooks);
 
 
//                                                            Selecting high to low in sort
String visibletext = “High to Low”;
WebElement element = driver.findElement(By.xpath(“//div/select”));
 
selectByVisibleText(element, visibletext);
 
wait.until(ExpectedConditions.urlContains(“sort_type=price_in_desc”));
 
System.out.println(“Navigated to books page and sorted books by Price – High to low”);
 
//captureScreenShot(driver);
Thread.sleep(2000);
 
// There are two ways to solve this. One is to look at the innerText and get the price
// Or to get the URL for each of the book, and then fetch the price from that page in a loo
// We are taking the second approach as that is what manual testing team would also do
 
//                                                            Get the entire hrefs of all the books
List<WebElement> listOfBooks =
driver.findElements(By.xpath(“//*[@id=\”search-result-items\”]/li[*]/div/div[2]/span[1]/a”));
 
int size = listOfBooks.size();
System.out.println(“Total number of items in the list = ” + size);
// Step 1 – store all the Href’s in a list – going through the loop
List<String> listOfURLs = new ArrayList<String>();
for (int i=0;i<size;i++) {
WebElement bookElementURL = listOfBooks.get(i);
String url = bookElementURL.getAttribute(“href”);
listOfURLs.add(url);
System.out.println(“URL of the book =” + url);
}
 
//Step2 – go through the Hrefs and store the price in two lists
// we will also be doing a conversion from String to Int
// we get a string Rs.38,750
// we will have to do a substring from . on wards
// and then replace , with nothing
 
List<Integer> actualPriceOfBooks = new ArrayList<Integer>();
List<Integer> forSortingOfPrice = new ArrayList<Integer>();
 
for (int i=0;i<listOfURLs.size();i++) {
String url = listOfURLs.get(i);
driver.get(url);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(“//*[@id=\”pricing_summary\”]/div/div[2]/span/span”)));
driver.findElement(By.tagName(“body”)).sendKeys(“Keys.ESCAPE”); // this is to not wait for the entire website to load
WebElement bookPriceElement = driver.findElement(By.xpath(“//*[@id=\”pricing_summary\”]/div/div[2]/span/span”));
String strPrice = bookPriceElement.getText();
System.out.println(“Original str = ” + strPrice);
// get the subString
strPrice = strPrice.substring(strPrice.indexOf(“.”)+1);
System.out.println(“SubString from . onwards = ” + strPrice);
strPrice = strPrice.replaceAll(“,”, “”);
System.out.println(“Cleaned up string = ” + strPrice);
// we can try converting this to integer
int iPrice = Integer.parseInt(strPrice);
System.out.println(“integer price = ” + iPrice);
//store it in arrayList
actualPriceOfBooks.add(iPrice);
forSortingOfPrice.add(iPrice);
}
 
//do the sorting through Java
Collections.sort(forSortingOfPrice); //this will sort
Collections.reverse(forSortingOfPrice); //this will make it high to low
// we can now do the comparision of two list
boolean sortingProper = forSortingOfPrice.equals(actualPriceOfBooks);
 
System.out.println(“Sorting Proper = ” + sortingProper);
 
Assert.assertTrue(sortingProper,”Elements are not sorted in descending order”);
}
 
@BeforeTest
public void beforeTest() {
 
System.setProperty(“webdriver.chrome.driver”, “src/test/resources/drivers/chromedriver.exe”);
 
driver = new ChromeDriver();
 
driver.get(“https://www.crossword.in”);
 
driver.manage().window().maximize();
 
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
 
wait = new WebDriverWait(driver,25);
 
}
 
@AfterTest
public void afterTest() {
driver.quit();
}
 
public void selectByVisibleText(WebElement element, String visibletext)
{
Select select = new Select(element);
select.selectByVisibleText(visibletext);
}
 
}
[/gdlr_code]
The code file CrossWordExerciseMethodA.java can be downloaded from the below URL
https://www.dropbox.com/s/411kr3exg3sfiek/CrossWordExerciseMethodA.java?dl=0

Step 3 – Final Code for approach B

The code takes care of string to integer conversions, including using substring and also replacing characters. Sorting using collections.sort() and collections.reverse() methods are being used. ArrayList is the preferred collection object which is being used in the code below. Please see the entire code below, it has enough comments for you to understand. At the same time the code can be downloaded from the dropbox link provided below.
====================================================
[gdlr_code title=”CrossWordExerciseMethodB.java” active=”no”]
package cpsatblogs;
 
import org.testng.annotations.Test;
import org.testng.annotations.BeforeTest;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
 
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
 
/*
* CPSAT Program
* Exercise on Crossword
*
* Open site https://www.crossword.in/
* Choose “Books” from tabs visible
* Display number of books found
* Click on Price: Sort by Price: high to low icon
* Ensure that the books are indeed sorted on price high to low
* Solution – B
*
* Use of innerText
* The price of books are available in the html page
* but not visible
*
* Coverage
*
* Handling innerText attribute
* https://stackoverflow.com/questions/43933778/how-to-get-inner-text-of-an-element-in-selenium
* if the element is hiddent getText() does not work
* we have use innerText attribute
*
* How to fetch multiple elements
* How to act on these elements in a loop
* how to extract integer from strings
* how to use collections.sort and reverse in order for doing sorting check
* use testNg assertTrue
*
*/
 
public class CrossWordExerciseMethodB {
 
WebDriver driver;
WebDriverWait wait;
 
@Test
public void crossWordtest() throws IOException, InterruptedException {
 
// wait for the page to load
 
wait.until(ExpectedConditions.titleIs(driver.getTitle()));
 
//Selecting book from home page
// //a[contains(text(),”Books”) and @class=” “]
// //li[2]/a[contains(text(),’Books’)]
WebElement booklink = driver.findElement(By.xpath(“//a[contains(text(),\”Books\”) and @class=\” \”]”));
//WebElement booklink = driver.findElement(By.xpath(“//li[2]/a[contains(text(),’Books’)]”));
 
booklink.click();
 
//Navigating to books page
String expTitle = “Books”;
wait.until(ExpectedConditions.titleContains(expTitle));
 
//Selecting high to low in sort
String visibletext = “High to Low”;
WebElement element = driver.findElement(By.xpath(“//div/select”));
 
// please see a simple method which creates a Select object and selects by visible text
// this is how the wrapper methods are created too
selectByVisibleText(element, visibletext);
 
// the URL changes once the sorting is done, wait for the same
wait.until(ExpectedConditions.urlContains(“sort_type=price_in_desc”));
System.out.println(“Navigated to books page and sorted books by Price – High to low”);
 
Thread.sleep(2000); //only for debugging purpose
 
//                  Step 1
// use tags which are hidden and have the price
// the following xpath has the final price stored
// //span[@class=”variant-final-price”]//span[@class=”m-w”]/text() returns the final variant price for all the books
// we can use //span[@class=”variant-final-price”]//span[@class=”m-w”] as our xpath
// we can also use //*[@class=”variant-final-price”]//*[@class=”m-w”]
// also simply //*[@class=”variant-final-price”]
 
List<WebElement> list = driver.findElements(By.xpath(“//*[@class=\”variant-final-price\”]//*[@class=\”m-w\”]”));
 
System.out.println(“Total Elements found: “+list.size());
 
// Step2 – go through the element and get innert text of price
// we will also be doing a conversion from String to Int
// we get a string Rs.38,750
// we will have to do a substring from . on wards
// and then replace , with nothing
// add the same in the two list
// one list would be used for sorting purpose
// and it will then be used to compare with the original list
 
 
List<Integer> actualPriceOfBooks = new ArrayList<Integer>();
List<Integer> forSortingOfPrice = new ArrayList<Integer>();
 
for(int i=0; i<list.size(); i++) {
 
String textexperiment = list.get(i).getText();
System.out.println(“Text Value  will be blank = ” + textexperiment);
 
// since text does not work, we will have to use innerText
String strPrice = list.get(i).getAttribute(“innerText”);
 
System.out.println(“Original str = ” + strPrice);
 
// Rs.38,750 needs to be cleaned
// get the subString after the first .
strPrice = strPrice.substring(strPrice.indexOf(“.”)+1);
System.out.println(“SubString from . onwards = ” + strPrice);
 
//remove all the , by nothing
strPrice = strPrice.replaceAll(“,”, “”);
strPrice = strPrice.trim();
System.out.println(“Cleaned up string = ” + strPrice);
// we can try converting this to integer
int iPrice = Integer.parseInt(strPrice);
//add the cost into both the lists
actualPriceOfBooks.add(iPrice);
forSortingOfPrice.add(iPrice);
}
 
System.out.println(“Total elements inserted: “+actualPriceOfBooks.size());
Collections.sort(forSortingOfPrice);
Collections.reverse(forSortingOfPrice);
 
// we can now do the comparison of two list
boolean sortingProper = forSortingOfPrice.equals(actualPriceOfBooks);
System.out.println(“Sorting Proper = ” + sortingProper);
Assert.assertTrue(sortingProper,”Elements are not sorted in descending order”);
}
 
@BeforeTest
public void beforeTest() {
 
System.setProperty(“webdriver.chrome.driver”, “src/test/resources/drivers/chromedriver.exe”);
 
driver = new ChromeDriver();
 
driver.get(“https://www.crossword.in”);
 
driver.manage().window().maximize();
 
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
 
wait = new WebDriverWait(driver,25);
 
}
 
@AfterTest
public void afterTest() {
driver.quit();
}
 
public void selectByVisibleText(WebElement element, String visibletext)
{
Select select = new Select(element);
select.selectByVisibleText(visibletext);
}
 
}
[/gdlr_code]
Full code for CrossWordExerciseMethodB.java can be downloaded from the below URL
https://www.dropbox.com/s/40g7wrjcmmd07p4/CrossWordExerciseMethodB.java?dl=0
 

About CPSAT

CP-SAT is the number 1 globally recognized selenium certificate. If you know selenium and you are not CP-SAT you are definitely missing something.
https://cpsat.agiletestingalliance.org/
CP-SAT and Agile Testing Alliance is always looking for Selenium evangelists who can help in curating such blogs, help in curating conferences and our community initiatives like CPSATday and Meetups.
ATA is helping teams transform. If you have testing teams who do not know selenium automation, ATA will help you transform.

Leave a Comment