Search code examples
angularseleniumselenium-webdriverwebdriverwaitexpected-condition

Invalid element state: Element must be user-editable in order to clear it error trying to click and insert a date on a dropdown-toggle using Selenium


I'm trying to click on this calendar and insert a date automatically using selenium, but I got the error below:

invalid element state: Element must be user-editable in order to clear it.

HTML snippet

<a id="enddate-dropdown" class="dropdown-toggle" role="button" data-toggle="dropdown" data-target="">
                <p class="custom-datepickers__date-prefix ng-binding">To:</p>
                <!-- ngIf: displayEndDate -->
                <!-- ngIf: !displayEndDate --><div ng-if="!displayEndDate" class="custom-datepickers__no-date ng-scope"></div><!-- end ngIf: !displayEndDate -->
</a>

Code snippet

myclass.SetDateByXpath("//*[@id=\"enddate-dropdown\"]/p", myclass.GetDate("yyyy/MM/dd", mydate));

public void SetDateByXpath(String element, String value)
    {
        WebElement webElement = ExplicitWaitOnElement(By.xpath(element));       
        ((JavascriptExecutor) driver).executeScript(
                "arguments[0].removeAttribute('readonly','readonly')",webElement);
        webElement.clear();
        webElement.sendKeys(value);
    }

If I set the date manually, this is the HTML:

<a id="enddate-dropdown" class="dropdown-toggle" role="button" data-toggle="dropdown" data-target="">
                <p class="custom-datepickers__date-prefix ng-binding">To:</p>
                <!-- ngIf: displayEndDate --><p ng-if="displayEndDate" class="ng-binding ng-scope">2019/11/21</p><!-- end ngIf: displayEndDate -->
                <!-- ngIf: !displayEndDate -->
</a>

Probably the website changed, but now I don't know how can I set this value. Any help will be appreciated.

Thanks


Solution

  • This error message...

    invalid element state: Element must be user-editable in order to clear it.
    

    ...implies that the element identified was not in a user-editable state to invoke clear() method.


    To insert a date with in a dropdown-toggle with an Angular element there are two approaches:

    • Either you can click() on the calendar and insert a date using sendKeys()
    • Or you can use executeScript() to invoke removeAttribute() the readonly attribute.

    However, as per the HTML you have shared it seems the element which gets populated with the date string i.e. 2019/11/21 is not readily available within the HTML DOM. So we can infer that the following element gets added to the DOM Tree as a result of interaction with other WebElements which is as follows:

    <p ng-if="displayEndDate" class="ng-binding ng-scope">2019/11/21</p>
    

    Hence the best approach would be,

    • First to invoke click() on the element readily available within the HTML inducing WebDriverWait.
    • Next to invoke sendKeys() on the newly created element WebDriverWait.
    • Code Block:

      //element -> myclass.SetDateByXpath("//a[@class='dropdown-toggle' and @id='enddate-dropdown']"
      // observe the change in the ^^^ xpath ^^^
      //value -> myclass.GetDate("yyyy/MM/dd", mydate));
      
      public void SetDateByXpath(String element, String value)
      {
          WebElement webElement = ExplicitWaitOnElement(By.xpath(element));       
          webElement.click();
          WebElement webElement_new = ExplicitWaitOnElement(By.xpath("//a[@class='dropdown-toggle' and @id='enddate-dropdown']//p[@class='ng-binding ng-scope' and @ng-if='displayEndDate']"));
          webElement_new.clear();
          webElement_new.sendKeys(value);
      }
      

    Reference

    You can find a relevant discussion in: