6

How to enter characters one by one in to a text field in selenium webdriver? I have used the below code but it's not working

getDriver().findElement(By.id("PhoneNumber")).sendKeys(Keys.chord("9876544322"));

Can anybody suggest how to resolve this?

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • 2
    Why don't just pass a string to `sendKeys()`: `getDriver().findElement(By.id("PhoneNumber")).sendKeys("9876544322");`? – alecxe Jun 30 '14 at 14:50
  • 1
    Because some input fields react as users type, e.g. start a search after 3 characters, cancel it if another character is pressed and start a search for 4-character string, etc. The logic can be quite complex. – Andrei Volgin Aug 12 '17 at 00:27

7 Answers7

12

Here is how I am sending character by character using Selenium Webdriver (in Java). This way in the back-end, I verify at each letter press if the character exists in the input. Normal element.sendKeys() is not working well for me 2 out of 5 times - the last letter is missing, I guess something is buggy with Selenium Webdriver, I don't know. Try the code below, it works 100% of the time for me.

public void TypeInField(String xpath, String value){
    String val = value; 
    WebElement element = driver.findElement(By.xpath(xpath));
    element.clear();

    for (int i = 0; i < val.length(); i++){
        char c = val.charAt(i);
        String s = new StringBuilder().append(c).toString();
        element.sendKeys(s);
    }       
}

As you see, I get the value needed to be typed and in the for loop, I take each character, convert it to string and send it to textbox. Also, I have a search for xpath, you can change that to id, or classname, or whatever you want.

Dmitry Shvedov
  • 3,169
  • 4
  • 39
  • 51
Marțiș Paul
  • 121
  • 1
  • 6
  • 1
    this solution worked perfectly for me except I have to put 100 millisecond sleep after each of the sendkeys call. Our app makes backend call for each of the character type and gives back search result – vikramvi Aug 22 '16 at 15:48
  • Thanks so much. I used several solutions to one of my automation projects. I tried JavaScript, Jquery etc. all solutions but I got some troubles. This solution is like a human like typing and worked like a charm. Thank you very much. – Onur Baskirt Jan 06 '17 at 19:44
  • 1
    @vikramvi , yes if there is a delay between app/server, its a good ideea to put a wait on it, if not,there will be chances that will fail. Onur , glad i could help :) – Marțiș Paul Jan 14 '17 at 07:37
  • Great stuff! Helped me with a problem I've been having for several hours. Drove me crazy! – user3356141 Apr 06 '17 at 12:48
  • I would recommend a variable delay between characters - what works with 0ms delay may not work with 100ms delay - or 500ms delay, etc. – Andrei Volgin Aug 12 '17 at 00:30
  • 1
    Can't i omit StringBuilder and simply write for (int i = 0; i < val.length(); i++) { element.sendKeys(val.charAt(i).toString()); Thread.Sleep(100);} – Abhi3106 Jan 12 '21 at 08:42
9

If you want to make your sendKeys more human like, I've used something like this:

private static void sendHumanKeys(WebElement element, String text) {
    Random r = new Random();
    for(int i = 0; i < text.length(); i++) {
        try {
            Thread.sleep((int)(r.nextGaussian() * 15 + 100));
        } catch(InterruptedException e) {}
        String s = new StringBuilder().append(text.charAt(i)).toString();
        element.sendKeys(s);
    }
}

It sends the keys with a 100ms delay, but only an average of 100ms. It creates a normal distribution with average 100ms and std. deviation 15ms.

Raghav
  • 249
  • 2
  • 12
  • 2
    Beautiful! Worked perfectly for me. I loved the nextGaussian! A nice touch. People are random, and computers are precise. LOL! :-) – Tihamer Apr 08 '20 at 20:34
5

sendKeys() does enter characters in sequence, but it can at times run quickly enough to be perceived as a copy/paste action. Though, it is in fact intended to simulate a user entering text by typing. Per the sendKeys() JavaDoc:

/** Use this method to simulate typing into an element, which may set its value. */

If you wanted to slow it down, you could make a method that accepts WebElement and String args, convert the String to charsequence[], then use a for loop and enter each index of the array in the .sendKeys() followed by a Thread.sleep(). This seems horribly inefficient, though, as sendKeys() recognizes Strings as charsequence[] (String is a charsequence[] in Java). Adding the Thread.sleep() will only slow your test needlessly.

Honestly, sendKeys() fits your described needs. It's the best way to simulate a user at a keyboard, it just does it really fast.

Dmitry Shvedov
  • 3,169
  • 4
  • 39
  • 51
tim-slifer
  • 1,068
  • 1
  • 9
  • 17
  • 1
    "...it just does it really fast" - That's precisely the problem. Some JavaScript does not have time to react - or it does not react as it would for a real user. If an input has logic related to individual characters, you have to create tests that are as close to real human behavior as possible - and "pasting" / rapidly typing an entire string is only one of possible use cases. – Andrei Volgin Aug 12 '17 at 00:32
  • String is a CharSequence, not a CharSequence[]. – JakeRobb Mar 06 '19 at 21:35
  • Just like Andrei Volgin said, sendKeys is sometimes too fast for a web page; especially if it is going back to the server to search for possible completions. – Tihamer Apr 08 '20 at 20:33
3

.chord() will press all keys simultaneously. Not very well suited for field input.

The .sendKeys() method will accept a String. Simply pass your input as such and have a go with it.

driver.findElement(By.id("element")).sendKeys("Field Input Text");
tim-slifer
  • 1,068
  • 1
  • 9
  • 17
  • driver.findElement(By.id("element")).sendKeys("Field Input Text"); sendKeys("Field Input Text") --> It will directly drop the text in the text field. I want a solution where we can enter characters one be one like the way we are typing. – Rajendra Narayan Mahapatra Jul 01 '14 at 10:16
  • sendKeys does simulate user keyboard input, typing a string out character by character – Jess Jul 02 '14 at 04:34
2

I created a Python function of the Java Selenium code. Find attached below and tweak based on the elements you want to use:

def TypeInField(xpath, myValue):
    val = myValue
    elem = driver.find_element_by_xpath(xpath)
    c = ""
    for i in range(0, len(val)):
      c += val[i]
      elem.send_keys(c)
      time.sleep(3)
    elem.send_keys(Keys.ENTER)
1

I use this function in my test when I want to type a string letter by letter.

public void typeOnLetterByLetter(WebElement webElement, String value, long waitBetweenLetters, ChronoUnit unitTime) {
    clear(webElement);
    Arrays.asList(value.toCharArray()).forEach(letter -> {
        typeOn(webElement, String.valueOf(letter));
        pause(waitBetweenLetters, unitTime);
    });
}

private void pause(long time, ChronoUnit unitTime) {
    try {
        Thread.sleep(Duration.of(time, unitTime).toMillis());
    } catch (InterruptedException ignore) {
    }
}
Zeeshan Adil
  • 1,937
  • 5
  • 23
  • 42
1

Here is how I did it in C#

    public void TypeInFieldCharByChar(IWebElement element,string text)
    {
        var strBuilder = new StringBuilder();

        for (int i = 0; i < text.Length; i++)
        {
            Thread.Sleep(100);
            strBuilder.Append(text[i]);
            element.SendKeys(strBuilder.ToString());
            strBuilder.Clear();
        }
    }
Svetlana
  • 11
  • 1