Protractor: clear() or sendKeys('') not working on input types: date, time, datetime-local, month, or week

Created on 1 Mar 2014  Â·  20Comments  Â·  Source: angular/protractor

This directly relates to the documentation tests on a pull request on the Angular.js project: https://github.com/angular/angular.js/pull/5864

For now I'm going to work around it, I guess. But the issue seems to be that due to the custom controls in browsers like Chrome, protractor simply doesn't know what to do to interact with them in order to clear them. It's sort of late, and I haven't dug any further into than that for now.

I did, however see a few StackOverflow questions that seemed to relate, although none of the workarounds I found there worked.

http://stackoverflow.com/questions/15360362/clear-date-input-fails-on-chromewebdriver

Also possibly related?

http://stackoverflow.com/questions/21295314/how-to-set-html5-type-date-input-fields-e-g-in-chrome-using-selenium-protra

external bug filed

Most helpful comment

This is a weird but easy solution

/**
 * Usage: clear(element(by.model('my.model')));
 */
function clear(elem, length) {
    length = length || 100;
    var backspaceSeries = '';
    for (var i = 0; i < length; i++) {
        backspaceSeries += protractor.Key.BACK_SPACE;
    }
    elem.sendKeys(backspaceSeries);
}

All 20 comments

FYI... I've opened a related issue in Angular here, that shows the workaround:

https://github.com/angular/angular.js/issues/6523

The basics of it are:

  1. use executeScript to set the value programmatically.
  2. If you're using Angular, you need to trigger validation manually by calling $setViewValue.
  3. Likewise if you're not using Angular, you'll need to call any event handlers you care about (e.g. "change", "keydown", etc) manually.

This is a webdriver thing so I'm labeling as 'external bug', but it's definitely something we should work with webdriver implementations to fix. Related: #510, #301

So, I'm thinking that maybe for now a nice workaround would be to have a protractor method that would do the work of sending an executeScript to force an update to the input, and make sure validation has been called. I'm not entirely sure how this would fit into your API, but I'm willing to implement it, since the workaround is fresh in my head. Some sort of: element.forceValue("new value"); or protractor.forceValue(element, "new value") type thing, as a helper method. Thoughts?

Yeah, this seems like a pretty reasonable shim. What about:

element(<selector>).setValue("new value")?

If you'd like to put together a PR, I'd be happy to work with you on one! You'll want to add it to the wrapper around WebElement here: https://github.com/angular/protractor/blob/master/lib/protractor.js#L557

and tests should go hereish: https://github.com/angular/protractor/blob/master/spec/basic/findelements_spec.js#L566

:+1: I'll try to crank something out sometime this week. At the very least it would really clean up the e2e tests in the input[date], input[time] type docs for my other PR.

Well i will comment here as well but i think my problem is not really related to this issues however i received reference to this issue after i had written my problem on another one.

So i will describe it in a brief (will try in understandable) way.
I have a form which has a button. So far nothing new. When i click the button it gets the created object and send it to a function. After that it clears the model ( create new empty object).

When i'm doing testing with protractor i specify my input field, sendKeys work fine with me but when i get the button and click it and after that verify the values of the fields, they are again with the values of the previously created object. That means the model hasn't been updated at all.

        element(by.model('unknown.readKey')).sendKeys('readKey 1');
        element(by.model('unknown.writeKey')).sendKeys('writeKey 1');

        element(by.id('configure')).click().then(function(){
            ptor.waitForAngular();
            expect(element(by.model('unknown.readKey')).getAttribute('value')).toBe('');
            expect(element(by.model('unknown.writeKey')).getAttribute('value')).toBe('');
        });

FYI: @juliemr I haven't forgotten about this. I had a... sudden career change... and I'm in the process of moving to Silicon Valley from Pittsburgh. I'll look into adding an extension method (or two?) after I'm moved out there.

This is a weird but easy solution

/**
 * Usage: clear(element(by.model('my.model')));
 */
function clear(elem, length) {
    length = length || 100;
    var backspaceSeries = '';
    for (var i = 0; i < length; i++) {
        backspaceSeries += protractor.Key.BACK_SPACE;
    }
    elem.sendKeys(backspaceSeries);
}

@ivkremer: superb, thanks for that – using your code as a base, I've created an includable module (I've called the file form-input-object.js) :

var _ = require('lodash');

module.exports = {
    clear: function (element) {
        return element.getAttribute('value').then(function (text) {
            var backspaceSeries = '',
                textLength = text.length;

            _.times(textLength, function () {
                backspaceSeries += protractor.Key.BACK_SPACE;
            });

            return element.sendKeys(backspaceSeries);
        });
    }
};

It returns a promise, so it's then()able.

Note: I've used lodash, cos I'm lazy – and I also added a test for the length of the existing text in the input, so that the number of backspaces sent is exact.

Have tested it in Chrome and Firefox.

Thanks again... you saved me a load of time!

@mcalthrop

Note: I've used lodash, cos I'm lazy – and I also added a test for the length of the existing text in the input, so that the number of backspaces sent is exact.

Then I'd suggest this:

function clear(elem) {
  elem.getAttribute('value').then(function (text) {
    var len = text.length
    var backspaceSeries = Array(len+1).join(protractor.Key.BACK_SPACE);
    elem.sendKeys(backspaceSeries);
  })
}

Not good at js. Can someone tell me how the workaround will work for me? I am also using protractor to a non-angular page here, so guess I do not have to worry about the model validation here

I do not have an id for my dtepicker, hence I cannot do the workaround browser.executeScript("document.getElementById('someElem').value = '2011-11-11';");
I can lookup the element using the css selector like
element(by.css('.mySubSection .dateInput > input')).
Please help!!

I have protractor 2.2.0. The clear() function does not work on input of type number. I have tried most of the solutions given here. Please help me. Below is my code:
element(by.model('lineup.voltage_limit')).click().clear().sendKeys(value);

I have tried to even resolve the promise from clear() like below
element(by.model('lineup.voltage_limit')).click().clear().then(function(){
element(by.model('lineup.voltage_limit')).sendKeys(value);
});

clear() just does not seem to work! It just keeps on appending to the text in the input box.

Why not injecting a "browser script command" to just set the field value to
zero?

On Mon, 31 Aug 2015 at 22:55 nehaw07 [email protected] wrote:

I have protractor 2.2.0. The clear() function does not work on input of
type number. I have tried most of the solutions given here. Please help me.
Below is my code:
element(by.model('lineup.voltage_limit')).click().clear().sendKeys(value);

I have tried to even resolve the promise from clear() like below
element(by.model('lineup.voltage_limit')).click().clear().then(function(){
element(by.model('lineup.voltage_limit')).sendKeys(value);
});

clear() just does not seem to work! It just keeps on appending to the text
in the input box.

—
Reply to this email directly or view it on GitHub
https://github.com/angular/protractor/issues/562#issuecomment-136363105.

@kayhadrin Thanks for your suggestion. I was able to clear the existing numerical text from the input box using executeScript but then it does not clear the text it inserts a 0 if I say
browser.executeScript("document.getElementById('lineup_voltage_limit').value = ' ';");
I want to clear the value which somehow I am unable to do.

I'm testing this kind of numerical input field with a value as "" and it
shows effectively nothing in it.
So what's the HTML of your input field atm?
And what browser version are you using?

<input id="test" value="" type="number">

@cnishina we need to confirm whether this is still a problem and file an appropriate webdriver bug if so.

I am facing similar issue on Chromium Version 49.0.2623.108, however Firefox (45.0.2) works fine.

protractor version 3.3.0
selenium standalone versions available: 2.52.0 [default]
chromedriver versions available: 2.21 [default]

Also checked with newes selenium (2.53.1) chromedriver (2.22) versions -- result is the same.

...

Input clear problem occurs when i start entering invalid values (like "e") to the number input. Furthermore when entered invalid value getAttibute('value') returns empty string and i have a feeling that those two issues are related.

Here is a yet another workaround:

input.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a'));
input.sendKeys(protractor.Key.DELETE);

Sending keys appears to work:

    let tab = protractor.Key.TAB;
    element(by.css('.myform-date')).sendKeys('01/01/1970');
    element(by.css('.myform-time')).sendKeys('02:30PM');
    element(by.css('.myform-datetime')).sendKeys('01/01/1970 ' + tab + '02:30AM');
    element(by.css('.myform-month')).sendKeys('January' + tab + '2016');
    element(by.css('.myform-week')).sendKeys('51 2017');

Clearing the input field throws an error:

Started
F

Failures:
1) date form should do this
  Message:
    Failed: invalid element state: Element must be user-editable in order to clear it.
      (Session info: chrome=55.0.2883.95)
      (Driver info: chromedriver=2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1),platform=Mac OS X 10.12.2 x86_64)
  Stack:
    InvalidElementStateError: invalid element state: Element must be user-editable in order to clear it.
      (Session info: chrome=55.0.2883.95)
      (Driver info: chromedriver=2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1),platform=Mac OS X 10.12.2 x86_64)
        at WebDriverError (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/error.js:27:5)
        at InvalidElementStateError (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/error.js:138:5)
        at Object.checkLegacyResponse (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/error.js:639:15)
        at parseHttpResponse (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/http/index.js:538:13)
        at client_.send.then.response (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/http/index.js:472:11)
        at ManagedPromise.invokeCallback_ (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/promise.js:1379:14)
        at TaskQueue.execute_ (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/promise.js:2913:14)
        at TaskQueue.executeNext_ (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/promise.js:2896:21)
        at asyncRun (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/promise.js:2820:25)
        at /Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/promise.js:639:7
    From: Task: WebElement.clear()
        at Driver.schedule (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/webdriver.js:377:17)
        at WebElement.schedule_ (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/webdriver.js:1744:25)
        at WebElement.clear (/Users/cnishina/src/protractor-cookbook/protractor-forms/node_modules/selenium-webdriver/lib/webdriver.js:2099:17)

My proposal is before we run the command .clear, we would check the attribute type of the input and if it is one of these, we send the right amount of back spaces and tabs to clear the field out. So for type="date" or type="time", we would:

.sendKeys(protractor.Key.BACK_SPACE + protractor.Key.TAB + protractor.Key.BACK_SPACE + protractor.Key.TAB + protractor.Key.BACK_SPACE);

Added clearByBs function to ngpo if you're using that for Protractor page objects. See How to append custom fns for example to clear a date field. Thanks @FilipZawada for your code.

Was this page helpful?
0 / 5 - 0 ratings