How to enter characters one by one in to a text field in selenium webdriver?
Asked Answered
P

7

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?

Primalia answered 30/6, 2014 at 14:44 Comment(2)
Why don't just pass a string to sendKeys(): getDriver().findElement(By.id("PhoneNumber")).sendKeys("9876544322");?Vasiliu
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.Sterol
C
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.

Carbone answered 1/3, 2016 at 7:13 Comment(6)
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 resultVacant
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.Ornithosis
@Vacant , 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 :)Autolysin
Great stuff! Helped me with a problem I've been having for several hours. Drove me crazy!Malaria
I would recommend a variable delay between characters - what works with 0ms delay may not work with 100ms delay - or 500ms delay, etc.Sterol
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);}Gillead
H
10

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.

Hopehopeful answered 26/2, 2019 at 6:44 Comment(1)
Beautiful! Worked perfectly for me. I loved the nextGaussian! A nice touch. People are random, and computers are precise. LOL! :-)Brisson
M
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.

Monoclinous answered 2/7, 2014 at 4:27 Comment(3)
"...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.Sterol
String is a CharSequence, not a CharSequence[].Hyman
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.Brisson
M
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");
Monoclinous answered 30/6, 2014 at 14:56 Comment(2)
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.Primalia
sendKeys does simulate user keyboard input, typing a string out character by characterTameka
P
3

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)
Pinckney answered 19/5, 2021 at 22:1 Comment(0)
S
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) {
    }
}
Sykes answered 7/9, 2018 at 11:27 Comment(1)
You have not defined clear or typeOn like you did pause.Brisson
F
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();
        }
    }
Friable answered 1/4, 2022 at 14:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.