• Home
  • Testing
  • SAP
  • Web
  • Must Learn!
  • Big Data
  • Live Projects
  • Blog

In this tutorial, we will learn the available methods to find and access the Links & Tables using Webdriver. Also, we will discuss some of the common problems faced while accessing Links and will further discuss on how to resolve them.

Here is what you will learn-

Part 1) Accessing Links

Part 2) Reading a Table

Part 1) Accessing Links

Links Matching a Criterion

Links can be accessed using an exact or partial match of their link text. The examples below provide scenarios where multiple matches would exist and would explain how WebDriver would deal with them.

Exact Match

Accessing links using their exact link text is done through the By.linkText() method. However, if there are two links that have the very same link text, this method will only access the first one. Consider the HTML code below

When you try to run the WebDriver code below, you will be accessing the first "click here" link

Code:

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

public class MyClass {				
    		
    public static void main(String[] args) {									
        String baseUrl = "http://demo.guru99.com/selenium/link.html";					
        System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");					
        WebDriver driver = new ChromeDriver();					
        		
        driver.get(baseUrl);					
        driver.findElement(By.linkText("click here")).click();					
        System.out.println("title of page is: " + driver.getTitle());							
        driver.quit();			
    }		

}			

Here is how it works-

As a result, you will automatically be taken to Google.

Partial Match

Accessing links using a portion of their link text is done using the By.partialLinkText() method. If you specify a partial link text that has multiple matches, only the first match will be accessed. Consider the HTML code below.

When you execute the WebDriver code below, you will still be taken to Google.

Code:

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

public class P1 {				
    		
    public static void main(String[] args) {									
        String baseUrl = "http://demo.guru99.com/selenium/link.html";					
        System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");					
        WebDriver driver = new ChromeDriver();					
        		
        driver.get(baseUrl);					
        driver.findElement(By.partialLinkText("here")).click();					
        System.out.println("Title of page is: " + driver.getTitle());							
        driver.quit();			
    }		
}

How to get the non-First Link

So, how to get around the above problem? In cases where there are multiple links with the same link text, and we want to access the links other than the first one, how do we go about it?

In such cases, generally, different locators viz... By.xpath(), By.cssSelector() or By.tagName() are used.

Most commonly used is By.xpath(). It is the most reliable one but it looks complex and non-readable too.

Case-sensitivity

The parameters for By.linkText() and By.partialLinkText() are both case-sensitive, meaning that capitalization matters. For example, in Mercury Tours' homepage, there are two links that contain the text "egis" - one is the "REGISTER" link found at the top menu, and the other is the "Register here" link found at the lower right portion of the page.

Though both links contain the character sequence "egis," one is the "By.partialLinkText()" method will access these two links separately depending on the capitalization of the characters. See the sample code below.

Code

public static void main(String[] args) {								
        String baseUrl = "http://demo.guru99.com/selenium/newtours/";					
        System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");					
        WebDriver driver = new ChromeDriver();					
        		
        driver.get(baseUrl);					
        String theLinkText = driver.findElement(By					
                .partialLinkText("egis"))			
                .getText();		
        System.out.println(theLinkText);					
        theLinkText = driver.findElement(By					
                .partialLinkText("EGIS"))			
                .getText();		
        System.out.println(theLinkText);					

        driver.quit();			

    }

All Links

One of the common procedures in web Testing is to test if all the links present within the page are working. This can be conveniently done using a combination of the Java for-each loop, findElements() & By.tagName("a") method.

The findElements() method, returns a list of Web Elements with tag a. Using a for-each loop, each element is accessed.

The WebDriver code below checks each link from the Mercury Tours homepage to determine those that are working and those that are still under construction.

import org.openqa.selenium.By;		
import org.openqa.selenium.WebDriver;		
import org.openqa.selenium.chrome.ChromeDriver;		
import java.util.List;		
import java.util.concurrent.TimeUnit;		
import org.openqa.selenium.*;		

public class P1 {				
    		
    public static void main(String[] args) {									
        String baseUrl = "http://demo.guru99.com/selenium/newtours/";					
        System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");					
        WebDriver driver = new ChromeDriver();					
        		
        String underConsTitle = "Under Construction: Mercury Tours";					
			driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);					

			driver.get(baseUrl);					
        List<WebElement> linkElements = driver.findElements(By.tagName("a"));							
        String[] linkTexts = new String[linkElements.size()];							
			int					i = 0;					

			//extract the link texts of each link element		
			for (WebElement e : linkElements) {							
			linkTexts[i] = e.getText();							
			i++;			
        }		

			//test each link		
			for (String t : linkTexts) {							
			driver.findElement(By.linkText(t)).click();					
			if (driver.getTitle().equals(underConsTitle)) {							
                System.out.println("\"" + t + "\""								
                        + " is under construction.");			
            } else {			
                System.out.println("\"" + t + "\""								
                        + " is working.");			
            }		
			driver.navigate().back();			
        }		
			driver.quit();			
    }		
}

The output should be similar to the one indicated below.

Links Outside and Inside a Block

The latest HTML5 standard allows the <a> tags to be placed inside and outside of block-level tags like <div>, <p>, or <h3>. The "By.linkText()" and "By.partialLinkText()" methods can access a link located outside and inside these block-level elements. Consider the HTML code below.

The WebDriver code below accesses both of these links using By.partialLinkText() method.

Code:

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

public class MyClass {				
    		
    public static void main(String[] args) {									
        String baseUrl = "http://demo.guru99.com/selenium/block.html";					
        System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");					
        WebDriver driver = new ChromeDriver();					
        		
        driver.get(baseUrl);					
        driver.findElement(By.partialLinkText("Inside")).click();					
        System.out.println(driver.getTitle());					
        driver.navigate().back();			
        driver.findElement(By.partialLinkText("Outside")).click();					
        System.out.println(driver.getTitle());					
        driver.quit();			
    }		
}		

The output above confirms that both links were accessed successfully because their respective page titles were retrieved correctly.

Accessing Image Links

Image links are the links in web pages represented by an image which when clicked navigates to a different window or page.

Since they are images, we cannot use the By.linkText() and By.partialLinkText() methods because image links basically have no link texts at all.

In this case, we should resort to using either By.cssSelector or By.xpath. The first method is more preferred because of its simplicity.

In the example below, we will access the "Facebook" logo on the upper left portion of Facebook's Password Recovery page.

We will use By.cssSelector and the element's "title" attribute to access the image link. And then we will verify if we are taken to Facebook's homepage.

package newproject;
import org.openqa.selenium.By;		
import org.openqa.selenium.WebDriver;		
import org.openqa.selenium.chrome.ChromeDriver;		

public class MyClass {				
    		
    public static void main(String[] args) {									
        String baseUrl = "https://www.facebook.com/login/identify?ctx=recover";					
        System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe");					
        WebDriver driver = new ChromeDriver();					
        		
        driver.get(baseUrl);					
        //click on the "Facebook" logo on the upper left portion		
			driver.findElement(By.cssSelector("a[title=\"Go to Facebook home\"]")).click();					

			//verify that we are now back on Facebook's homepage		
			if (driver.getTitle().equals("Facebook - log in or sign up")) {							
            System.out.println("We are back at Facebook's homepage");					
        } else {			
            System.out.println("We are NOT in Facebook's homepage");					
        }		
				driver.close();		

    }		
}

Result

Part 2) Reading a Table

There are times when we need to access elements (usually texts) that are within HTML tables. However, it is very seldom for a web designer to provide an id or name attribute to a certain cell in the table. Therefore, we cannot use the usual methods such as "By.id()", "By.name()", or "By.cssSelector()". In this case, the most reliable option is to access them using the "By.xpath()" method.

XPath Syntax

Consider the HTML code below.

We will use XPath to get the inner text of the cell containing the text "fourth cell."

Step 1 - Set the Parent Element (table)

XPath locators in WebDriver always start with a double forward slash "//" and then followed by the parent element. Since we are dealing with tables, the parent element should always be the <table> tag. The first portion of our XPath locator should, therefore, start with "//table".

Step 2 - Add the child elements

The element immediately under <table> is <tbody> so we can say that <tbody> is the "child" of <table>. And also, <table> is the "parent" of <tbody>. All child elements in XPath are placed to the right of their parent element, separated with one forward slash "/" like the code shown below.

Step 3 - Add Predicates

The <tbody> element contains two <tr> tags. We can now say that these two <tr> tags are "children" of <tbody>. Consequently, we can say that <tbody> is the parent of both the <tr> elements.

Another thing we can conclude is that the two <tr> elements are siblings. Siblings refer to child elements having the same parent.

To get to the <td> we wish to access (the one with the text "fourth cell"), we must first access the second <tr> and not the first. If we simply write "//table/tbody/tr", then we will be accessing the first <tr> tag.

So, how do we access the second <tr> then? The answer to this is to use Predicates.

Predicates are numbers or HTML attributes enclosed in a pair of square brackets "[ ]" that distinguish a child element from its siblings. Since the <tr> we need to access is the second one, we shall use "[2]" as the predicate.

If we won't use any predicate, XPath will access the first sibling. Therefore, we can access the first <tr> using either of these XPath codes.

Step 4 - Add the Succeeding Child Elements Using the Appropriate Predicates

The next element we need to access is the second <td>. Applying the principles we have learned from steps 2 and 3, we will finalize our XPath code to be like the one shown below.

Now that we have the correct XPath locator, we can already access the cell that we wanted to and obtain its inner text using the code below. It assumes that you have saved the HTML code above as "newhtml.html" within your C Drive.

Accessing Nested Tables

The same principles discussed above applies to nested tables. Nested tables are tables located within another table. An example is shown below.

To access the cell with the text "4-5-6" using the "//parent/child" and predicate concepts from the previous section, we should be able to come up with the XPath code below.

The WebDriver code below should be able to retrieve the inner text of the cell which we are accessing.

The output below confirms that the inner table was successfully accessed.

Using Attributes as Predicates

If the element is written deep within the HTML code such that the number to use for the predicate is very difficult to determine, we can use that element's unique attribute instead.

In the example below, the "New York to Chicago" cell is located deep into Mercury Tours homepage's HTML code.

In this case, we can use the table's unique attribute (width="270") as the predicate. Attributes are used as predicates by prefixing them with the @ symbol. In the example above, the "New York to Chicago" cell is located in the first <td> of the fourth <tr>, and so our XPath should be as shown below.

Remember that when we put the XPath code in Java, we should use the escape character backward slash "\" for the double quotation marks on both sides of "270" so that the string argument of By.xpath() will not be terminated prematurely.

We are now ready to access that cell using the code below.

Shortcut: Use Firebug/Chrome Inspect Element for Accessing Tables in Selenium

If the number or attribute of an element is extremely difficult or impossible to obtain, the quickest way to generate the XPath code is thru Firebug.

Consider the example below from Mercury Tours homepage.

Step 1

Use Firebug to obtain the XPath code.

Step 2

Look for the first "table" parent element and delete everything to the left of it.

Step 3

Prefix the remaining portion of the code with double forward slash "//" and copy it over to your WebDriver code.

The WebDriver code below will be able to successfully retrieve the inner text of the element we are accessing.

Summary

  • Links are accessed using the click() method.
  • Apart from the locators available for any WebElement, Links also have link text based locators:
    • By.linkText() – locates the links based on the exact match of the link's text provided as a parameter.
    • By.partialLinkText() – locates links based on the partial text match of the link's text.
  • Both the above locators are case Sensitive.
  • If there are multiple matches, By.linkText() and By.partialLinkText() will only select the first match. In such cases where multiple links with the same link text are present, other locators based on xpath, CSS are used.
  • findElements() & By.tagName("a") method finds all the elements in the page matching the locator criteria
  • Links can be accessed by the By.linkText() and By.partialLinkText() whether they are inside or outside block-level elements.
  • Accessing image links are done using By.cssSelector() and By.xpath() methods.
  • By.xpath() is commonly used to access table elements.

 

YOU MIGHT LIKE: