Webelement input not interactable (when choosing a specific one from list)

Viewed 40

I'm trying to find a specific input and sendkeys to it on this website. I have no problem locating it in the browser's console with for example (//input)[4] . However, when I'm trying to find it and sendkeys in my IDE (using Java with Selenium) I got the org.openqa.selenium.ElementNotInteractableException: element not interactable* exception. I tried to do it with following methods:

  1. With simple findelement and sendkeys:

    WebElement ebookAddInput = driver.findElement(By.xpath("(//input)[4]"));
    ebookAddInput.clear();
    ebookAddInput.sendKeys("4");
    
  2. Using list of items to choose specific one:

    List<WebElement> allInputs = driver.findElements(By.xpath("//input[@name='commerce-add-to-cart-quantity-input']"));
    System.out.println(allInputs.size());
    allInputs.get(4).sendKeys("4");
    

In both cases I got the mentioned error. The only way it works is through not specifying which input i want to choose and then there is no error and first input on the website gets filled:

WebElement ebookAddInput = driver.findElement(By.xpath("//input[@name='commerce-add-to-cart-quantity-input']"));
ebookAddInput.clear();
ebookAddInput.sendKeys("4");

Does someone know why is that happening and if theres way to solve it? Will really appreciate the help.

1 Answers

When searching by following xpath //input[@name='commerce-add-to-cart-quantity-input'] webdriver is able to find 18 elements (see amount of matches at the very bottom on my picture). But as a user, when you open that page, you see only 8 products (1 - in the header, and 7 - in the 'products' section below). Which means that others 10 elements are hidden and not interactable. That's why you get ElementNotInteractableException. So your xpath must be more specific, so that webdriver is able to find exactly visible/interactable elements.

enter image description here

Solution:

import io.github.bonigarcia.wdm.WebDriverManager;
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.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.Test;

import java.util.List;

public class SeleniumNotInteractable {
    WebDriver driver;

    @Test
    public void test() throws Exception {
        // download driver if not exist (for more details google 'how to use bonigarcia selenium')
        WebDriverManager.chromedriver().setup();

        driver = new ChromeDriver();
        driver.get("https://www.trychomaster.com/sklep");

        // wait until section with all products appear at the bottom of the page. You can wait for some specific products
        // to be visible/clickable, or, like I am showing below, you can wait for the whole section to be visible:
        WebElement contentSection = driver.findElement(By.cssSelector("div.content-section"));
        new WebDriverWait(driver, 10)
                .until(ExpectedConditions.attributeContains(contentSection, "style", "opacity: 1"));
        System.out.println("Content section of the page become visible!");

        // fill price for that single product at the top of the page
        String headerPriceInputXpath = "//*[@class='heading-30']//following::div[1]//input[@name='commerce-add-to-cart-quantity-input']";
        WebElement headerProductInput = driver.findElement(By.xpath(headerPriceInputXpath));
        headerProductInput.clear();
        headerProductInput.sendKeys("5");

        // fill prices for all other products at the bottom of the page
        String allOtherProductsInputsXpath = "//div[@data-w-tab='Produktys']//div[@role='listitem']//input[@name='commerce-add-to-cart-quantity-input']";
        List<WebElement> allOtherProductInputs = driver.findElements(By.xpath(allOtherProductsInputsXpath));
        for (WebElement productInput : allOtherProductInputs) {
            productInput.clear();
            productInput.sendKeys("5");
        }

        Thread.sleep(10 * 1000); // sleep 10 secs, to prevent browser closing, can be removed
    }

    @AfterTest
    public void tearDown() {
        // quit
        if (driver != null) {
            driver.quit();
        }
    }
}
Related