Search code examples
javaselenium-webdriverselenium-chromedriverwebdriver

Trying to make a simple selenium starter app with Java, but keep getting element not interactable errors on a search button


So, i'm trying to learn Selenium with Java, making a simple method to open google, and do a basic search. However, I get an error org.openqa.selenium.ElementNotInteractableException: element not interactable

Here is the full code for reference:

public static void SeleniumTest() {
    WebDriver Chrome = new ChromeDriver();
    Chrome.get("https://www.google.co.uk");

    WebElement AcceptCookies = Chrome.findElement(By.id("L2AGLb"));//find cookie prompt and accept button
    AcceptCookies.click();

    WebElement SearchBox = Chrome.findElement(By.className("gLFyf")); //find search field
    SearchBox.click();
    SearchBox.sendKeys("Selenium");
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        System.out.print("thread sleep failed with error " + e);
    }

    WebElement SearchButton = Chrome.findElement(By.className("gNO89b")); //find the search button
    SearchButton.click(); // and click it - error occurs here
}

From what I can tell, it looks like the search button class name is applied to two different buttons, and I think it's trying to find the one here (see attached) in the suggestions drop down, when I want to use the one in the default UI.

I've tried adding waits, moving the cursor and dismissing the suggestion box, but I still end up getting the error when the only search box visible is the one on the main page.

Do I need to do a clearer find for the specific element, or am I missing some other quirk of Selenium to make it correctly find the expected button?

I've tried adding a waituntil to ensure the button is visible, but that hasn't worked.

WebDriverWait wait = new WebDriverWait(Chrome, java.time.Duration.ofSeconds(10));
    WebElement newButton = wait.until(news -> news.findElement(By.className("gNO89b")));
    newButton.click();

I've also tried dismissing the context menu to ensure the only button is the one in the main UI, but that also fails to work as expected.

Actions action = new Actions(Chrome);
action.keyDown(Keys.ESCAPE).sendKeys().perform(); //remove?


Solution

  • So the problem is as you suspected... there are two elements that match the locator, classname of "gNO89b". The first element found is not interactable because the script is going so fast, the search results panel isn't open yet with the first element fully visible and interactable. You can solve this a couple ways.

    Method #1
    Use a proper wait

    String url = "https://www.google.co.uk";
    
    driver = new ChromeDriver();
    driver.manage().window().maximize();
    driver.get(url);
    
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    wait.until(ExpectedConditions.elementToBeClickable(By.className("gLFyf"))).sendKeys("Selenium");
    wait.until(ExpectedConditions.elementToBeClickable(By.className("gNO89b"))).click();
    

    Method #2
    Send a carriage return with the search term

    String url = "https://www.google.co.uk";
    
    driver = new ChromeDriver();
    driver.manage().window().maximize();
    driver.get(url);
    
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    wait.until(ExpectedConditions.elementToBeClickable(By.className("gLFyf"))).sendKeys("Selenium\n");
    

    I've tested both and they both work so it's down to personal preference which one you want to use.


    Tip #1
    Either way you choose, it's always a best practice to use WebDriverWait on each call. Even if it's not necessary, it doesn't slow down your code but will help prevent intermittent failures if the site runs a little slow today, etc.

    Tip #2
    Always test your locators in the dev console. Use $$() for CSS selectors and $x() for XPaths. This will greatly help you find unique locators and identify problems long before you actually run any code. For example, $$(".gNO89b") for the search button in CSS selector syntax. This returns 2 elements. If you expand the search results, you can hover over each element returned and see it highlighted on the page. You can then see that the second element returned is the one you want... thus identifying a problem before you ever run the script.