RicoRicochet
RicoRicochet

Reputation: 2289

Link not opening during web page automation with selenium

I have been trying to automate a browser operation via selenium, the goal is - google.com will be opened, gmail text will be searched and the first link will be clicked and opened. The code used is --

public static void main(String[] args) {
        WebDriver driver= new FirefoxDriver();
        driver.get("https://www.google.co.in");
        driver.manage().window().maximize();
        WebElement searchbox= driver.findElement(By.id("lst-ib"));
        searchbox.sendKeys("gmail");
        driver.findElement(By.name("btnG")).click();
        driver.findElement(By.xpath("//ol[@id='rso']//div[1]//div[1]//div//h3//a")).click();
}

but nothing is happening, I am getting an error -

error-Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//ol[@id='rso']//div[1]//div[1]//div//h3//a"}

where am I doing wrong ?

Upvotes: 0

Views: 1127

Answers (3)

giri-sh
giri-sh

Reputation: 6962

You are getting error because you are trying to click the first link (gmail) even before its loaded. Update your code to implement a wait until the element loads after you search for something and click on the search button. There are many types of wait available in Selenium, use explicit waits to wait between two actions and it's my most preferable method. Here's how -

driver.findElement(By.name("btnG")).click();
(new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//ol[@id='rso']//div[1]//div[1]//div//h3//a"))).click(); //explicitly wait for the element to load and then click

Another better way to handle this is to wait for the element to appear and keep polling the page if the element showed up using Fluent waits. Here's how -

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class); //create a fluent wait object
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//ol[@id='rso']//div[1]//div[1]//div//h3//a"))).click(); //fluent wait until element loads

You can also use an implicit wait time. which waits for a predefined time after each and every action that selenium performs. But it's again a non preferable one as it can throw errors at times when performance of the webpage is slow. Here's how -

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //implicitly wait until element loads for predefined time
driver.get("https://www.google.co.in");

However, the easiest one that solves your issue is to use a simple sleep() method, which i don't prefer is using the sleep() method. I don't prefer it is because it can throw errors at times when elements take longer time to load, because selenium waits for a predefined time that you specify, which is a bad standard of coding. Here's how -

driver.findElement(By.name("btnG")).click();
Thread.sleep(5000); //Use sleep() method to wait for a predefined time
driver.findElement(By.xpath("//ol[@id='rso']//div[1]//div[1]//div//h3//a")).click();

Hope it helps.

Upvotes: 0

Deepak_Mahalingam
Deepak_Mahalingam

Reputation: 454

Following Xpath in your code is in wrong format:

driver.findElement(By.xpath("//ol[@id='rso']//div[1]//div[1]//div//h3//a")).click();

Please use the following Xpath is will work perfectly.

  WebDriver driver= new FirefoxDriver();
            driver.get("https://www.google.co.in");
            driver.manage().window().maximize();
            WebElement searchbox= driver.findElement(By.id("lst-ib"));
            searchbox.sendKeys("gmail");
            driver.findElement(By.name("btnG")).click();
          driver.findElement(By.xpath("//ol[@id='rso']/div[1]/div[1]/div/h3/a")).click();

Xpath what I modified is.

driver.findElement(By.xpath("//ol[@id='rso']/div[1]/div[1]/div/h3/a")).click();

Upvotes: 1

Mona
Mona

Reputation: 352

i am seeing my dynamic id are been used, it not recommended to use dynamic ids[as it will be keep changing], also use necessary wait conditions to avoid such exceptions

driver.findElement(By.id("lst-ib")); //lst-ib is dynamic value. 

i tried to replicate your scenario, no issues observed, please find the coding below,

package testclasses;

import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.*;
import org.testng.annotations.*;

public class classa extends classparent {

    @Test
 public void methoda() throws InterruptedException {
      driver.manage().window().maximize();
      driver.get("https://www.google.co.in/"); 


      WebDriverWait wait = new WebDriverWait(driver, 10);
      wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(text(),'Gmail')]")));

      WebElement close = driver.findElement(By.xpath("//a[contains(text(),'Gmail')]"));


      if(close.isDisplayed()){
         System.out.println("element is visible " +close);
         close.click();
      }

      else{
          System.out.println("element is not visible " +close);
      }
      }
}

console output,

TestNG] Running:
  C:\Users\Mohan Raj S\AppData\Local\Temp\testng-eclipse-1635948262\testng-customsuite.xml

element is visible [[FirefoxDriver: firefox on WINDOWS (6d5bc9d3-cdff-4831-991a-69d7d7ce3d36)] -> xpath: //a[contains(text(),'Gmail')]]
PASSED: methoda

===============================================
    Default test
    Tests run: 1, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

Upvotes: 0

Related Questions