Welcome to today’s comprehensive guide on Handling Web Tables in Selenium with Java. Web tables are a fundamental component of many web applications, presenting data in a structured, tabular format. Mastering the interaction with various types of web tables is crucial for building robust automation scripts using Selenium WebDriver. This tutorial will walk you through different scenarios, provide practical examples, and offer assignments to enhance your Selenium automation skills.



1. Introduction

Web tables are ubiquitous in web applications, presenting data such as user information, product listings, booking details, and more. Automating interactions with these tables is essential for tasks like data validation, information extraction, and performing operations based on table data. Depending on their implementation, web tables can vary in complexity, requiring different strategies to handle them effectively.


2. Types of Web Tables

Understanding the type of web table you are dealing with is the first step in determining the appropriate handling method. Web tables generally fall into three categories:

  1. Static Web Tables: Tables with a fixed number of rows and columns, and static data that does not change dynamically.
  2. Dynamic Web Tables: Tables where data, as well as the number of rows, can change dynamically based on user interactions or backend processes.
  3. Pagination Web Tables: Tables that display a subset of data per page, with navigation controls to move between pages containing more data.

2.1. Static Web Tables

Static Web Tables have a fixed structure with a constant number of rows and columns. The data within these tables remains unchanged unless manually modified. These tables are straightforward to handle in Selenium, making them ideal for beginners to practice basic table interactions.

Characteristics:

  • Fixed number of rows and columns.
  • Static data that does not change dynamically.
  • Easy to locate and interact with using Selenium locators.

Example Scenario:

A table listing books with columns for Book Name, Author, Subject, and Price.

2.2. Dynamic Web Tables

Dynamic Web Tables exhibit variability in data and the number of rows. Rows can be added or removed based on user actions or data fetched from the server. Handling dynamic tables requires more sophisticated strategies to ensure reliable automation.

Characteristics:

  • Variable number of rows.
  • Data within the table can change dynamically.
  • May require dynamic locators or synchronization techniques to handle data loading.

Example Scenario:

A user management table where new users can be added or existing users can be deleted, altering the number of rows dynamically.

2.3. Pagination Web Tables

Pagination Web Tables divide large datasets into manageable pages, displaying a subset of rows per page. Users can navigate between pages to view more data. Automating interactions with pagination tables involves handling multiple pages and aggregating data across them.

Characteristics:

  • Large datasets split into multiple pages.
  • Navigation controls (e.g., Next, Previous, Page Numbers) to move between pages.
  • May require looping through pages to perform actions on all data.

Example Scenario:

A customer list displaying 10 records per page with navigation controls to move through 194 pages of customer data.


3. Handling Static Web Tables

Static tables serve as an excellent starting point for mastering table interactions in Selenium. This section covers the essential operations you can perform on static web tables.

3.1. Understanding Table Structure

Before interacting with a web table, it’s crucial to understand its HTML structure. Typically, a web table is defined using the <table> tag, containing <thead>, <tbody>, <tr>, <th>, and <td> tags.

HTML Structure Example:

<table name="BookTable">
    <tbody>
        <tr>
            <th>Book Name</th>
            <th>Author</th>
            <th>Subject</th>
            <th>Price</th>
        </tr>
        <tr>
            <td>Master in Selenium</td>
            <td>Mukesh</td>
            <td>Automation</td>
            <td>$300</td>
        </tr>
        <tr>
            <td>JavaScript Essentials</td>
            <td>Amit</td>
            <td>Programming</td>
            <td>$500</td>
        </tr>
        <!-- More rows -->
    </tbody>
</table>

Key Elements:

  • <table>: Defines the table.
  • <tbody>: Contains the table body.
  • <tr>: Represents a table row.
  • <th>: Denotes a table header cell.
  • <td>: Represents a table data cell.

3.2. Counting Rows and Columns

Objective: Determine the number of rows and columns in a static web table.

Approach:

  1. Counting Rows:
    • Each <tr> tag within <tbody> represents a row.
    • Use Selenium to locate all <tr> elements within the table.
    • Count the number of <tr> elements.
  2. Counting Columns:
    • The first <tr> typically contains <th> elements representing columns.
    • Locate all <th> elements within the first <tr>.
    • Count the number of <th> elements.

Sample Code:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;

public class StaticWebTableExample {
    public static void main(String[] args) throws InterruptedException {
        // Set the path for ChromeDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");

        // Initialize WebDriver
        WebDriver driver = new ChromeDriver();

        // Maximize Browser Window
        driver.manage().window().maximize();

        // Navigate to the page containing the static table
        driver.get("https://example.com/staticTable.html");

        // Locate the table by name attribute
        WebElement table = driver.findElement(By.xpath("//table[@name='BookTable']"));

        // 1. Count the number of rows
        List allRows = table.findElements(By.tagName("tr"));
        int numberOfRows = allRows.size();
        System.out.println("Total number of rows: " + numberOfRows);

        // 2. Count the number of columns
        // Assuming the first row contains the headers
        List allColumns = allRows.get(0).findElements(By.tagName("th"));
        int numberOfColumns = allColumns.size();
        System.out.println("Total number of columns: " + numberOfColumns);

        // Close the browser
        driver.quit();
    }
}

Explanation:

  • Counting Rows: The findElements method locates all <tr> elements within the specified table. The size of the resulting list indicates the total number of rows.
  • Counting Columns: The first row (allRows.get(0)) typically contains <th> elements representing column headers. Counting these elements provides the total number of columns.

Important Considerations:

  • Single vs. Multiple Tables: Ensure that the locator uniquely identifies the desired table, especially if multiple tables exist on the page.
  • Header Rows: The first <tr> is usually the header. Adjust your row counting logic accordingly if you need to exclude headers.

3.3. Reading Specific Cell Data

Objective: Extract data from a specific row and column in a static web table.

Approach:

  1. Identify the Table: Locate the table using appropriate locators (name, id, XPath, etc.).
  2. Specify Row and Column Indices: Determine the row and column numbers from which you want to extract data.
  3. Construct XPath Dynamically: Use the row and column indices to build an XPath that points to the desired cell.
  4. Extract Text: Use the getText() method to retrieve the cell’s content.

Sample Code:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class ReadSpecificCellData {
    public static void main(String[] args) {
        // Set the path for ChromeDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");

        // Initialize WebDriver
        WebDriver driver = new ChromeDriver();

        // Maximize Browser Window
        driver.manage().window().maximize();

        // Navigate to the page containing the static table
        driver.get("https://example.com/staticTable.html");

        // Define row and column numbers (1-based indexing)
        int rowNumber = 5; // Example: 5th row
        int columnNumber = 1; // Example: 1st column

        // Construct XPath dynamically
        String cellXPath = "//table[@name='BookTable']/tbody/tr[" + rowNumber + "]/td[" + columnNumber + "]";
        WebElement cell = driver.findElement(By.xpath(cellXPath));

        // Extract text from the cell
        String cellData = cell.getText();
        System.out.println("Data at row " + rowNumber + ", column " + columnNumber + ": " + cellData);

        // Close the browser
        driver.quit();
    }
}

Explanation:

  • Dynamic XPath Construction: The cellXPath string dynamically incorporates the rowNumber and columnNumber variables to point to the desired cell.
  • Data Extraction: The getText() method retrieves the text content of the specified cell.

Key Points:

  • 1-Based Indexing: XPath indices start at 1, not 0.
  • Header Handling: Ensure that your row indices account for header rows if present.

3.4. Iterating Over Rows and Columns

Objective: Read and process data from all rows and columns in a static web table.

Approach:

  1. Locate the Table: Use appropriate locators to identify the table.
  2. Determine the Number of Rows and Columns: Count rows and columns as previously described.
  3. Nested Looping:
    • Outer Loop: Iterates over each row.
    • Inner Loop: Iterates over each column within the current row.
  4. Extract and Process Data: Retrieve cell data and perform necessary operations (e.g., printing, validation).

Sample Code:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;

public class IterateOverTable {
    public static void main(String[] args) {
        // Set the path for ChromeDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");

        // Initialize WebDriver
        WebDriver driver = new ChromeDriver();

        // Maximize Browser Window
        driver.manage().window().maximize();

        // Navigate to the page containing the static table
        driver.get("https://example.com/staticTable.html");

        // Locate the table by name attribute
        WebElement table = driver.findElement(By.xpath("//table[@name='BookTable']"));

        // 1. Count the number of rows
        List allRows = table.findElements(By.tagName("tr"));
        int numberOfRows = allRows.size();

        // 2. Count the number of columns (assuming first row contains headers)
        List allColumns = allRows.get(0).findElements(By.tagName("th"));
        int numberOfColumns = allColumns.size();

        // 3. Iterate over each row (starting from 2 if first row is header)
        for (int r = 2; r <= numberOfRows; r++) {
            // 4. Iterate over each column
            for (int c = 1; c <= numberOfColumns; c++) {
                // Construct XPath for each cell
                String cellXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[" + c + "]";
                WebElement cell = driver.findElement(By.xpath(cellXPath));
                String cellText = cell.getText();
                System.out.print(cellText + "\t"); // Print with tab separation
            }
            System.out.println(); // Newline after each row
        }

        // Close the browser
        driver.quit();
    }
}

Explanation:

  • Nested Loops: The outer loop iterates through each row (excluding the header), while the inner loop iterates through each column within the current row.
  • Data Presentation: System.out.print(cellText + "\t") prints each cell’s data separated by tabs for better readability. System.out.println() moves to the next line after each row.

Output Example:

Total number of rows: 7
Total number of columns: 4

Table Headers:
Book Name	Author	Subject	Price	

Master in Selenium	Mukesh	Automation	$300	
JavaScript Essentials	Amit	Programming	$500	
Advanced Automation Techniques	Mukesh	Testing	$700	
Learning Python	John	Data Science	$600	
Java in Depth	Mukesh	Development	$800	
Database Fundamentals	Alice	DB	$400	
Web Development Basics	Bob	Web	$200	

Books authored by Mukesh:
Master in Selenium	Mukesh
Advanced Automation Techniques	Mukesh
Java in Depth	Mukesh

Total Price of All Books: $2900

3.5. Conditional Data Retrieval

Objective: Retrieve data from a table based on specific conditions (e.g., print book names where the author is “Mukesh”).

Approach:

  1. Iterate Over Rows: Loop through each row in the table.
  2. Check Condition: For each row, verify if a specific cell meets the condition (e.g., Author equals “Mukesh”).
  3. Retrieve and Process Data: If the condition is met, extract the desired cell data (e.g., Book Name).

Sample Code:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;

public class ConditionalDataRetrieval {
    public static void main(String[] args) {
        // Set the path for ChromeDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");

        // Initialize WebDriver
        WebDriver driver = new ChromeDriver();

        // Maximize Browser Window
        driver.manage().window().maximize();

        // Navigate to the page containing the static table
        driver.get("https://example.com/staticTable.html");

        // Locate the table by name attribute
        WebElement table = driver.findElement(By.xpath("//table[@name='BookTable']"));

        // 1. Count the number of rows
        List allRows = table.findElements(By.tagName("tr"));
        int numberOfRows = allRows.size();

        // 2. Count the number of columns (assuming first row contains headers)
        List allColumns = allRows.get(0).findElements(By.tagName("th"));
        int numberOfColumns = allColumns.size();

        // 3. Iterate over each row (starting from 2 if first row is header)
        for (int r = 2; r <= numberOfRows; r++) {
            // Construct XPath for Author column (assuming Author is the 2nd column)
            String authorXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[2]";
            WebElement authorCell = driver.findElement(By.xpath(authorXPath));
            String authorName = authorCell.getText();

            // Check if Author is "Mukesh"
            if (authorName.equals("Mukesh")) {
                // Construct XPath for Book Name column (1st column)
                String bookNameXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[1]";
                WebElement bookNameCell = driver.findElement(By.xpath(bookNameXPath));
                String bookName = bookNameCell.getText();

                // Print Book Name and Author Name
                System.out.println(bookName + "\t" + authorName);
            }
        }

        // Close the browser
        driver.quit();
    }
}

Explanation:

  • Condition Check: The script checks if the author name in the second column equals “Mukesh”.
  • Data Extraction: If the condition is true, it extracts the book name from the first column of the same row.

Output Example:

Books authored by Mukesh:
Master in Selenium	Mukesh
Advanced Automation Techniques	Mukesh
Java in Depth	Mukesh

Handling Duplicate Conditions: If multiple rows meet the condition, the script will retrieve and process each one accordingly. There’s no limitation on the number of matches unless explicitly coded.

3.6. Sample Code for Static Tables

Combining all the concepts discussed, here’s a complete sample script that:

  • Counts rows and columns.
  • Iterates through the table.
  • Retrieves specific cell data.
  • Performs conditional data retrieval.
  • Calculates the total price of all books.
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;

public class StaticWebTableComprehensive {
    public static void main(String[] args) throws InterruptedException {
        // 1. Setup WebDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();

        // 2. Navigate to the page containing the static table
        driver.get("https://example.com/staticTable.html");

        // 3. Locate the table by name attribute
        WebElement table = driver.findElement(By.xpath("//table[@name='BookTable']"));

        // 4. Count the number of rows
        List allRows = table.findElements(By.tagName("tr"));
        int numberOfRows = allRows.size();
        System.out.println("Total number of rows: " + numberOfRows);

        // 5. Count the number of columns (assuming first row contains headers)
        List allColumns = allRows.get(0).findElements(By.tagName("th"));
        int numberOfColumns = allColumns.size();
        System.out.println("Total number of columns: " + numberOfColumns);

        // 6. Print table headers
        System.out.println("\nTable Headers:");
        for (WebElement column : allColumns) {
            System.out.print(column.getText() + "\t");
        }
        System.out.println("\n");

        // 7. Iterate over each row (starting from 2 if first row is header)
        for (int r = 2; r <= numberOfRows; r++) {
            for (int c = 1; c <= numberOfColumns; c++) {
                // Construct XPath for each cell
                String cellXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[" + c + "]";
                WebElement cell = driver.findElement(By.xpath(cellXPath));
                String cellText = cell.getText();
                System.out.print(cellText + "\t");
            }
            System.out.println(); // Newline after each row
        }

        // 8. Conditional Data Retrieval: Print book names where Author is "Mukesh"
        System.out.println("\nBooks authored by Mukesh:");
        for (int r = 2; r <= numberOfRows; r++) { // Starting from 2 to skip header
            String authorXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[2]";
            WebElement authorCell = driver.findElement(By.xpath(authorXPath));
            String authorName = authorCell.getText();

            if (authorName.equals("Mukesh")) {
                String bookNameXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[1]";
                WebElement bookNameCell = driver.findElement(By.xpath(bookNameXPath));
                String bookName = bookNameCell.getText();
                System.out.println(bookName + "\t" + authorName);
            }
        }

        // 9. Calculate Total Price of All Books
        int totalPrice = 0;
        for (int r = 2; r <= numberOfRows; r++) { // Starting from 2 to skip header
            String priceXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[4]";
            WebElement priceCell = driver.findElement(By.xpath(priceXPath));
            String priceText = priceCell.getText(); // e.g., "$300"

            // Remove the dollar sign and convert to integer
            int price = Integer.parseInt(priceText.replace("$", ""));
            totalPrice += price;
        }
        System.out.println("\nTotal Price of All Books: $" + totalPrice);

        // Close the browser
        driver.quit();
    }
}

Explanation:

  • Counting and Printing: The script counts rows and columns, prints table headers, and iterates through all rows and columns to print cell data.
  • Conditional Retrieval: It prints book names authored by “Mukesh”.
  • Price Calculation: It calculates the total price by extracting price data, converting it from string to integer, and summing it up.

Output Example:

Total number of rows: 7
Total number of columns: 4

Table Headers:
Book Name	Author	Subject	Price	

Master in Selenium	Mukesh	Automation	$300	
JavaScript Essentials	Amit	Programming	$500	
Advanced Automation Techniques	Mukesh	Testing	$700	
Learning Python	John	Data Science	$600	
Java in Depth	Mukesh	Development	$800	
Database Fundamentals	Alice	DB	$400	
Web Development Basics	Bob	Web	$200	

Books authored by Mukesh:
Master in Selenium	Mukesh
Advanced Automation Techniques	Mukesh
Java in Depth	Mukesh

Total Price of All Books: $2900

Important Considerations:

  • Data Types: When performing arithmetic operations on cell data (like calculating total price), ensure that the data is converted from string to numeric types appropriately.
  • Exception Handling: Incorporate try-catch blocks to handle potential exceptions, such as NoSuchElementException if elements are not found.
  • Dynamic Data: While this guide focuses on static tables, similar principles apply to dynamic tables with additional considerations for synchronization and dynamic locators.


4. Best Practices

  1. Use Explicit Waits Over Thread.sleep():
      • Why?: Enhances synchronization and reduces test execution time.
      • How?:
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    wait.until(ExpectedConditions.elementToBeClickable(By.id("elementID")));
    
  2. Prefer Reliable Locators:
    • Why?: Ensures consistency and reduces maintenance.
    • How?:
      • Use By.id or By.name when available.
      • Use descriptive XPath or CSS selectors.
      • Avoid brittle locators that depend on dynamic attributes.
  3. Handle Exceptions Gracefully:
      • Why?: Prevents abrupt test failures and allows for better debugging.
      • How?:
    try {
        // Interaction code
    } catch (NoSuchElementException e) {
        System.out.println("Element not found: " + e.getMessage());
    }
    
  4. Avoid Hardcoding Values:
    • Why?: Enhances flexibility and reusability.
    • How?:
      • Use variables or external data sources for input values.
      • Parameterize test scripts.
  5. Maintain Clean and Readable Code:
    • Why?: Facilitates easier maintenance and collaboration.
    • How?:
      • Use descriptive variable and method names.
      • Comment complex logic or XPath expressions.
      • Organize code into reusable methods or Page Object Model (POM) structures.
  6. Use Page Object Model (POM):
    • Why?: Promotes reusability and separation of concerns.
    • How?:
      • Create separate classes for each page.
      • Encapsulate element locators and interaction methods within page classes.
  7. Regularly Update WebDriver and Browsers:
    • Why?: Ensures compatibility and leverages the latest features and fixes.
  8. Securely Handle Credentials:
    • Why?: Prevents exposure of sensitive information.
    • How?: Use environment variables or encrypted storage solutions.
  9. Validate Actions:
      • Why?: Ensures that the intended actions (like selecting a checkbox) have been performed successfully.
      • How?:
    assert checkbox.isSelected() : "Checkbox was not selected.";
    
  10. Avoid Overcomplicating Locators:
    • Why?: Simplifies maintenance and reduces errors.
    • How?: Use the simplest locator that uniquely identifies an element.


5. Assignments

• Assignment 1: Handling Static Web Tables

Objective: Automate interactions with a static web table by performing various operations such as counting rows and columns, reading specific cells, iterating through the table, performing conditional data retrieval, and calculating the total price of all books.

  1. Navigate to the Static Table Page:
  2. Count the Total Number of Rows and Columns:
    • Locate the table using the name attribute.
    • Count the number of <tr> elements to determine rows.
    • Count the number of <th> elements in the first row to determine columns.
  3. Read Specific Cell Data:
    • Extract data from the 5th row and 1st column (e.g., “Master in Selenium”).
    • Extract data from the 7th row and 3rd column (e.g., “JavaScript Essentials”).
  4. Iterate Through the Table and Print Data:
    • Loop through each row and column to print all table data in a tabular format.
  5. Conditional Data Retrieval:
    • Print book names where the author is “Mukesh”.
  6. Calculate Total Price of All Books:
    • Extract all price values.
    • Convert them from string to integer.
    • Sum them up to find the total price.

Submission: Provide the complete Selenium script with comments explaining each step.

Sample Skeleton:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;

public class Assignment1_StaticWebTable {
    public static void main(String[] args) throws InterruptedException {
        // 1. Setup WebDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();

        // 2. Navigate to the static table page
        driver.get("https://example.com/staticTable.html");

        // 3. Locate the table by name attribute
        WebElement table = driver.findElement(By.xpath("//table[@name='BookTable']"));

        // 4. Count rows
        List allRows = table.findElements(By.tagName("tr"));
        int numberOfRows = allRows.size();
        System.out.println("Total number of rows: " + numberOfRows);

        // 5. Count columns
        List allColumns = allRows.get(0).findElements(By.tagName("th"));
        int numberOfColumns = allColumns.size();
        System.out.println("Total number of columns: " + numberOfColumns);

        // 6. Read specific cell data
        int specificRow = 5;
        int specificColumn = 1;
        String cellXPath = "//table[@name='BookTable']/tbody/tr[" + specificRow + "]/td[" + specificColumn + "]";
        WebElement specificCell = driver.findElement(By.xpath(cellXPath));
        String specificData = specificCell.getText();
        System.out.println("Data at row " + specificRow + ", column " + specificColumn + ": " + specificData);

        // 7. Iterate through the table and print data
        System.out.println("\nComplete Table Data:");
        for (int r = 1; r <= numberOfRows; r++) {
            for (int c = 1; c <= numberOfColumns; c++) {
                String dynamicXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[" + c + "]";
                List cells = table.findElements(By.xpath(dynamicXPath));
                if (!cells.isEmpty()) {
                    System.out.print(cells.get(0).getText() + "\t");
                }
            }
            System.out.println();
        }

        // 8. Conditional Data Retrieval: Print book names where Author is "Mukesh"
        System.out.println("\nBooks authored by Mukesh:");
        for (int r = 2; r <= numberOfRows; r++) { // Starting from 2 to skip header
            String authorXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[2]";
            WebElement authorCell = driver.findElement(By.xpath(authorXPath));
            String authorName = authorCell.getText();

            if (authorName.equals("Mukesh")) {
                String bookNameXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[1]";
                WebElement bookNameCell = driver.findElement(By.xpath(bookNameXPath));
                String bookName = bookNameCell.getText();
                System.out.println(bookName + "\t" + authorName);
            }
        }

        // 9. Calculate Total Price of All Books
        int totalPrice = 0;
        for (int r = 2; r <= numberOfRows; r++) { // Starting from 2 to skip header
            String priceXPath = "//table[@name='BookTable']/tbody/tr[" + r + "]/td[4]";
            WebElement priceCell = driver.findElement(By.xpath(priceXPath));
            String priceText = priceCell.getText(); // e.g., "$300"

            // Remove the dollar sign and convert to integer
            int price = Integer.parseInt(priceText.replace("$", ""));
            totalPrice += price;
        }
        System.out.println("\nTotal Price of All Books: $" + totalPrice);

        // 10. Close the browser
        driver.quit();
    }
}

Notes:

  • Dynamic XPath: The script dynamically constructs XPath expressions using loop variables to target specific cells.
  • Data Conversion: Prices are converted from strings (e.g., “$300”) to integers for arithmetic operations.
  • Header Handling: The script skips the header row when performing data retrieval and calculations.

• Assignment 2: Handling Dynamic and Pagination Web Tables

Objective: Automate a scenario involving dynamic web tables with pagination by finding the lowest price and completing a booking process.

Scenario Overview:

  1. Navigate to BlazeDemo:
  2. Select Departure and Destination Cities:
    • Choose any departure city from the drop-down.
    • Choose any destination city from the drop-down.
    • Click on “Find Flights”.
  3. Handle the Flights Table:
    • A table displaying available flights will appear with columns like Airline, From, To, Price.
    • The table may have multiple pages (pagination).
  4. Find the Lowest Price:
    • Capture all price values from the table.
    • Determine the lowest price among them.
    • Identify the flight corresponding to the lowest price.
  5. Choose the Flight:
    • Click on “Choose This Flight” for the flight with the lowest price.
  6. Fill in the Purchase Form:
    • Enter details like First Name, Address, City, State, etc.
    • Select options from drop-downs and checkboxes as required.
    • Click on “Purchase Flight”.
  7. Validate Purchase Confirmation:
    • Verify that the confirmation message “Thank you for your purchase today!” is displayed.

Key Challenges:

  • Dynamic Table with Pagination: Handling tables where data spans multiple pages requires iterating through all pages to ensure accurate data retrieval.
  • Finding the Lowest Price: Requires capturing all price values, sorting them, and identifying the minimum value.

Approach:

  1. Iterate Through All Pages:
    • Navigate through each page of the table to capture all price values.
  2. Capture and Sort Prices:
    • Store all captured prices in an array or list.
    • Sort the array to identify the lowest price.
  3. Select the Flight with the Lowest Price:
    • Locate the row containing the lowest price.
    • Click on the corresponding “Choose This Flight” button.
  4. Complete the Purchase:
    • Fill in the purchase form with dummy data.
    • Submit the form and verify the confirmation message.

Sample Code Skeleton:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

public class Assignment2_DynamicPaginationWebTable {
    public static void main(String[] args) throws InterruptedException {
        // 1. Setup WebDriver
        System.setProperty("webdriver.chrome.driver", "path_to_chromedriver");
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();

        // 2. Navigate to BlazeDemo
        driver.get("https://blazdemo.com/");

        // 3. Select Departure and Destination Cities
        // Example: Departure - Boston, Destination - London
        WebElement departureCity = driver.findElement(By.id("input_departure"));
        departureCity.click();
        departureCity.findElement(By.xpath("//option[text()='Boston']")).click();

        WebElement destinationCity = driver.findElement(By.id("input_destination"));
        destinationCity.click();
        destinationCity.findElement(By.xpath("//option[text()='London']")).click();

        // 4. Click on Find Flights
        WebElement findFlightsButton = driver.findElement(By.xpath("//input[@value='Find Flights']"));
        findFlightsButton.click();
        Thread.sleep(3000); // Wait for flights table to load

        // 5. Handle the Flights Table with Pagination
        List priceList = new ArrayList<>();
        String nextPageXPath = "//a[text()='Next']";
        boolean hasNextPage = true;

        while (hasNextPage) {
            // 5.1. Capture all price values on the current page
            List prices = driver.findElements(By.xpath("//table[@class='table']/tbody/tr/td[4]"));
            for (WebElement priceElement : prices) {
                String priceText = priceElement.getText(); // e.g., "700"
                int price = Integer.parseInt(priceText);
                priceList.add(price);
            }

            // 5.2. Check if 'Next' button is enabled
            List nextButtons = driver.findElements(By.xpath(nextPageXPath));
            if (!nextButtons.isEmpty() && nextButtons.get(0).isDisplayed()) {
                nextButtons.get(0).click();
                Thread.sleep(2000); // Wait for next page to load
            } else {
                hasNextPage = false; // No more pages
            }
        }

        // 6. Find the Lowest Price
        int lowestPrice = Collections.min(priceList);
        System.out.println("Lowest Price: $" + lowestPrice);

        // 7. Locate the Flight with the Lowest Price and Choose It
        // Assuming all flights are now captured; navigate back to the first page
        driver.navigate().back();
        Thread.sleep(3000); // Wait for flights table to load

        hasNextPage = true;
        boolean flightChosen = false;

        while (hasNextPage && !flightChosen) {
            List rows = driver.findElements(By.xpath("//table[@class='table']/tbody/tr"));
            for (WebElement row : rows) {
                WebElement priceElement = row.findElement(By.xpath("td[4]"));
                int price = Integer.parseInt(priceElement.getText());

                if (price == lowestPrice) {
                    // Click on 'Choose This Flight'
                    row.findElement(By.xpath("td[5]/input")).click();
                    flightChosen = true;
                    break;
                }
            }

            if (!flightChosen) {
                List nextButtons = driver.findElements(By.xpath(nextPageXPath));
                if (!nextButtons.isEmpty() && nextButtons.get(0).isDisplayed()) {
                    nextButtons.get(0).click();
                    Thread.sleep(2000); // Wait for next page to load
                } else {
                    hasNextPage = false; // No more pages
                }
            }
        }

        // 8. Fill in the Purchase Form
        driver.findElement(By.id("inputName")).sendKeys("John Doe");
        driver.findElement(By.id("address")).sendKeys("123 Elm Street");
        driver.findElement(By.id("city")).sendKeys("New York");
        driver.findElement(By.id("state")).sendKeys("NY");
        driver.findElement(By.id("zipCode")).sendKeys("10001");

        // Select card type
        WebElement cardType = driver.findElement(By.xpath("//input[@value='visa']"));
        cardType.click();

        // Enter credit card details
        driver.findElement(By.id("creditCardNumber")).sendKeys("4111111111111111");
        driver.findElement(By.id("creditCardMonth")).sendKeys("12");
        driver.findElement(By.id("creditCardYear")).sendKeys("2025");
        driver.findElement(By.id("nameOnCard")).sendKeys("John Doe");

        // Click on Purchase Flight
        WebElement purchaseButton = driver.findElement(By.xpath("//input[@value='Purchase Flight']"));
        purchaseButton.click();
        Thread.sleep(3000); // Wait for confirmation

        // 9. Validate Purchase Confirmation
        WebElement confirmationMessage = driver.findElement(By.xpath("//h1[text()='Thank you for your purchase today!']"));
        if (confirmationMessage.isDisplayed()) {
            System.out.println("Purchase confirmed successfully.");
        } else {
            System.out.println("Purchase confirmation failed.");
        }

        // 10. Close the browser
        driver.quit();
    }
}

Explanation:

  • Handling Pagination:
    • The script iterates through all pages by clicking the “Next” button until no more pages are available.
    • It collects all price values across all pages to determine the lowest price.
  • Selecting the Flight:
    • After identifying the lowest price, the script navigates back to the flights table.
    • It searches for the flight with the lowest price and clicks the corresponding “Choose This Flight” button.
  • Filling the Purchase Form:
    • The script enters dummy data into the purchase form fields.
    • It selects the card type, enters credit card details, and submits the form.
  • Validation:
    • It verifies that the confirmation message is displayed, indicating a successful purchase.

Important Considerations:

  • Synchronization: Utilize explicit waits (WebDriverWait) instead of Thread.sleep() for better reliability and efficiency.
  • Dynamic Locators: Ensure that locators are robust and can handle dynamic changes in the DOM, especially when dealing with multiple pages.
  • Error Handling: Implement try-catch blocks to handle potential exceptions during execution.

Handling Dynamic Price Sorting: Alternatively, instead of manually capturing and sorting prices, you can implement logic to find the minimum price while iterating through the table. However, using built-in Java collections like List and Collections.min() simplifies the process.

Tips for Handling Dynamic Web Tables with Pagination:

  1. Loop Through Pages:
    • Use a loop to navigate through each page of the table.
    • Check for the presence and visibility of the “Next” button to determine if more pages exist.
  2. Aggregate Data:
    • Collect necessary data (e.g., prices) across all pages.
    • Store data in a List or array for processing.
  3. Identify Target Rows:
    • After determining the target data (e.g., lowest price), iterate again through the pages to locate and interact with the corresponding row.
  4. Optimize Locators:
    • Use relative XPath expressions that are not brittle to changes in the table structure.
    • Avoid hardcoding indices unless necessary.
  5. Handle Dynamic Content:
    • Implement waits to ensure that dynamic content loads before attempting to interact with it.
    • Use ExpectedConditions to wait for elements to become clickable or visible.


6. Conclusion

Handling web tables is a fundamental aspect of Selenium WebDriver automation. Mastery of these interactions ensures that your automation scripts can effectively manage data validation, information extraction, and perform operations based on table data, leading to more reliable and efficient test executions.

Key Takeaways:

  • Understanding Table Types: Recognize the differences between static, dynamic, and pagination web tables to choose the appropriate handling method.
  • Static Tables: Utilize straightforward locators and looping mechanisms to interact with static tables efficiently.
  • Dynamic Tables with Pagination: Implement robust strategies to handle tables with changing data and multiple pages, ensuring comprehensive data coverage.
  • Conditional Data Retrieval: Apply conditional logic to extract and process data based on specific criteria within the table.
  • Best Practices: Incorporate synchronization techniques, maintain clean and readable code, and use reliable locators to enhance script reliability and maintainability.

Next Steps:

  • Practice Assignments: Implement the provided assignments to reinforce your understanding of table handling in Selenium.
  • Explore Advanced Topics: Delve into handling more complex tables, integrating Selenium with testing frameworks like TestNG or JUnit, and leveraging the Page Object Model (POM) for better code organization.
  • Continuous Learning: Stay updated with Selenium WebDriver’s latest features and best practices to build efficient and robust automation scripts.

Happy Automating!