Sheikh Rahman
Sheikh Rahman

Reputation: 915

Selenium : How to solve org.openqa.selenium.InvalidElementStateException: invalid element state

I have read a few online articles and they all point to 1 direction and that is when the page is loading the element is not found. In my setData() you can see I have tried a few things such as use of wait, implicitwait and 1st click and then send the username. However nothing seems to be working. I also thought of using "wait" inside pageProperties but later changed my mind because that would probably be a bad design.

Error :

Exception in thread "main" org.openqa.selenium.InvalidElementStateException: invalid element state

System information: Windows 10, ChromeDriver 2.37.544315, chrome=65.0.3

Code:

public class Tour {

    public static WebDriver driver;

    //browser URL information
    public WebDriver getBrowser(String browser, String url){
        System.setProperty("webdriver.chrome.driver", "C:\\Users\\Downloads\\chromedriver.exe");

        if(browser.equals("cc")){
            driver= new ChromeDriver();
        }
        driver.get(url);
        return driver;
    }

    // User name and continue button property from 1st page
    public void pageUserNameProperty(String un){
        WebElement login=driver.findElement(By.xpath("//input[@id='usernameOrEmail']"));
        WebElement cont_btn=driver.findElement(By.xpath("//button[contains(@type,'submit')]"));

        //WebDriverWait wait = new WebDriverWait(driver,30);
        //wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[@id='usernameOrEmail']")));
        login.sendKeys(un);
        cont_btn.click();

    }
    // Password and continue button property from 2nd page
    public void pagePassTourProperty(String psd){
        WebElement password=driver.findElement(By.xpath("//input[@id='password']"));
        WebElement lgn_btn=driver.findElement(By.xpath("//button[contains(@type,'submit')]"));

        //WebDriverWait wait = new WebDriverWait(driver,30);
        //wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[@id='usernameOrEmail']")));
        password.sendKeys(psd);
        lgn_btn.click();

    }

    // Supply Data for test from excel
    public void setData(){
        Tour tour= new Tour();
        tour.getBrowser("cc", "https://wordpress.com/log-in");
        WebDriverWait wait = new WebDriverWait(driver,30);
        WebElement login_field=wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[@id='usernameOrEmail']")));
        login_field.click();
        //driver.manage().timeouts().implicitlyWait(18, TimeUnit.SECONDS);
        tour.pageUserNameProperty("JoeThomas");
        //wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[@id='passTour']")));
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        tour.pagePassTourProperty("psd231");
    }

    public static void main(String[] args) {
        Tour tour= new Tour();
        tour.setData();

    }

}

Error:

Starting ChromeDriver 2.37.544315 (730aa6a5fdba159ac9f4c1e8cbc59bf1b5ce12b7) on port 2644 
Only local connections are allowed. 
Apr 18, 2018 7:09:26 AM org.openqa.selenium.remote.ProtocolHandshake createSession 
INFO: Detected dialect: OSS 
Exception in thread "main" org.openqa.selenium.InvalidElementStateException: invalid element state   (Session info: chrome=65.0.3325.181)   
(Driver info: chromedriver=2.37.544315 (730aa6a5fdba159ac9f4c1e8cbc59bf1b5ce12b7),platform=Windows NT 10.0.15063 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 0 milliseconds Build info: version: '3.11.0', revision: 'e59cfb3', time: '2018-03-11T20:33:15.31Z' System info: host: 'XYZ', ip: '123', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_91' 
Driver info: org.openqa.selenium.chrome.ChromeDriver Capabilities {acceptInsecureCerts: false, acceptSslCerts: false, applicationCacheEnabled: false, browserConnectionEnabled: false, browserName: chrome, chrome: {chromedriverVersion: 2.37.544315 (730aa6a5fdba15..., userDataDir: C:\Users\CHQ-SH~1\AppData\L...}, cssSelectorsEnabled: true, databaseEnabled: false, handlesAlerts: true, hasTouchScreen: false, javascriptEnabled: true, locationContextEnabled: true, mobileEmulationEnabled: false, nativeEvents: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: XP, platformName: XP, rotatable: false, setWindowRect: true, takesHeapSnapshot: true, takesScreenshot: true, unexpectedAlertBehaviour: , unhandledPromptBehavior: , version: 65.0.3325.181, webStorageEnabled: true} 
Session ID: 3298d88e517d756790ab6792e45257f1    
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)    

Thank You for your time and suggestion.

Experiment:

public class Tour {

    public static WebDriver driver;

    //browser URL information
    public WebDriver getBrowser(String browser, String url){
        System.setProperty("webdriver.chrome.driver", "C:\\Users\\chq-sheikhr\\Downloads\\chromedriver.exe");

        if(browser.equals("cc")){
            driver= new ChromeDriver();
        }
        driver.get(url);
        return driver;
    }

    // User name and continue button property from 1st page
    public void pageUserNameProperty(String un){
        WebElement login=driver.findElement(By.xpath("//input[@id='usernameOrEmail']"));
        WebElement cont_btn=driver.findElement(By.xpath("//button[contains(@type,'submit')]"));

        login.sendKeys(un);
        cont_btn.click();

    }
    // Password and continue button property from 2nd page
    public void pagePasswordProperty(String psd){
        WebElement password=driver.findElement(By.xpath("//input[@id='password']"));
        WebElement lgn_btn=driver.findElement(By.xpath("//button[contains(@type,'submit')]"));

        password.sendKeys(psd);
        lgn_btn.click();
    }

    // A method - isElementExists to check whether that element exists or not
    public boolean isElementExists(By xpath){
        return driver.findElements(By.xpath("//input[@id='usernameOrEmail']")).size() > 0;
    }

    /*create a method waitForElement and pass wait time in seconds to it, it is not a hard code wait as it
     *  will continuously check whether that element is exist or not and then it will wait for 1 seconds on 
     *  every iteration of for loop
     */
    public boolean waitForElement(int timeInSeconds, By xpath){
        try{
            for(int i=0;i<timeInSeconds;i++){
                if(isElementExists(xpath))
                    return true;
                Thread.sleep(1000);
            }
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return false;
    }

    public void setData(){
        Tour tour= new Tour();
        tour.getBrowser("cc", "https://wordpress.com/log-in");
        tour.waitForElement(10, By.xpath("//input[@id='usernameOrEmail']"));
        tour.pageUserNameProperty("JoeThoman");
        tour.pagePasswordProperty("pasd123");


    }

    public static void main(String[] args) {
        Tour tour= new Tour();
        tour.setData();
    }

}

Upvotes: 2

Views: 34447

Answers (3)

Rohit Tyagi
Rohit Tyagi

Reputation: 11

This can be handled if your application is dealing with Jquery. This code will wait until your page is fully loaded with all the required data and will avoid invalidelementstateexception .

Exception in thread "main" org.openqa.selenium.InvalidElementStateException: invalid element state

public static boolean waitForJSandJQueryToLoad() {
    WebDriverWait wait = new WebDriverWait(getWebDriver(), 30);

    // wait for jQuery to load
    ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
        @Override
        public Boolean apply(WebDriver driver) {
            try {
                System.out.println(
                        "Request = " + ((JavascriptExecutor) driver).executeScript("return jQuery.active"));
                return ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active") == 0);
            } catch (Exception e) {
                // no jQuery present
                System.out.println("no jQuery present");
                return true;
            }
        }
    };

    // wait for Java script to load
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
        @Override
        public Boolean apply(WebDriver driver) {
            try {
                System.out.println(
                        "Request = " + ((JavascriptExecutor) driver).executeScript("return document.readyState").toString());
                return ((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete");
            } catch (Exception e) {
                // no jQuery present
                System.out.println("no jQuery present");
                return true;
            }
        }
    };

    return wait.until(jQueryLoad) && wait.until(jsLoad);
}

Upvotes: 1

undetected Selenium
undetected Selenium

Reputation: 193108

This error message...

Exception in thread "main" org.openqa.selenium.InvalidElementStateException: invalid element state

...implies that the element with which you are trying to interact is in a state during which actions cannot be performed.


InvalidElementStateException

InvalidElementStateException is a type of WebDriverException which indicates that a WebElement with whom you are trying to interact is in a state in which actions cannot be performed with it. Such instances may arise when an element is being obscured by another element while clicking or the desired element perhaps is not being visible on the HTML DOM.


Solution

You have to consider a few facts as follows :

  • Never mixup implicitlyWait() and WebDriverWait() as the documentation clearly mentions the following :

Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

So you need to remove all the instances of implicitlyWait().

  • As you need to send characters to the Email Address or Username field so instead of ExpectedConditions method visibilityOfElementLocated() you need to use elementToBeClickable() method.
  • A simple script to access the url https://wordpress.com/log-in and send characters to the Email Address or Username field is as follows :

    System.setProperty("webdriver.gecko.driver", "C:/path/to/geckodriver.exe");
    WebDriver driver =  new FirefoxDriver();
    driver.get("https://wordpress.com/log-in");
    new WebDriverWait(driver,30).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@id='usernameOrEmail']"))).sendKeys("JoeThomas");
    
  • Snapshot of the WebClient :

WebClient


Update

As per your counter question within your comments the WebDriverWait polls the HTML DOM at certain intervals (default 500 ms) till the configured amount of time (30 seconds in your case). The element/s is/are returned back as soon as the ExpectedConditions is met. For example, if the desired element is found within 1 second, it is returned and your next line of code executes. There is no delay involved. As per the WebDriverWait constructor you can always configure the timeOutInSeconds and sleepInMillis i.e. polling interval.


Reference

You can find a detailed discussion in:

Upvotes: 5

Pritam Maske
Pritam Maske

Reputation: 2760

To make it consistent please follow below steps :

A) create a method - isElementExists to check whether that element exists or not as follows :

public boolean isElementExists(String xpathOfElement){
    return driver.findElements(By.xpath(xpathOfElement)).size() > 0;
}

B) Now create a method waitForElement and pass wait time in seconds to it, it is not a hard code wait as it will continuously check whether that element is exist or not and then it will wait for 1 seconds on every iteration of for loop as follows :

public boolean waitForElement(int timeInSeconds, String xpathOfElement){
    try{
        for(int i=0;i<timeInSeconds;i++){
            if(isElementExists(xpathOfElement))
                return true;
            Thread.sleep(1000);
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
    return false;
}

C) So once it return true you can perform the action on that element.

I have used xpath for locating element, you can use whichever you want.

Upvotes: 3

Related Questions