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 http://www.crossword.in

Let us define the testing goal which will help in giving a practical twist to our problem statement

  • Open site http://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.

====================================================

CrossWordExerciseMethodA.java

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 http://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(“http://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);

}

 

}

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.

====================================================

CrossWordExerciseMethodB.java

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 http://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(“http://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);

}

 

}

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.

http://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 Reply