Selenium Webdriver - sendKeys() not sending all keys - Java - java

I use Selenium Webdriver with Java and I've found a problem. When I try to send some text to the textfield, it only sends first char of two. I tried setting it with JavaScriptExecutor, but same thing happened. ChromeDriver is running and working fine. Code below:
public void sendNumberToChrome (int number){
textfield.clear(); // textfield is already set, it's classic input field with max. 10 characters
System.out.println(String.valueOf(number)); // This prints for example 94
textfield.sendKeys(String.valueOf(number)); // But only "9" appears in the browser
}
I also tried to send it character by character:
String[] arr = String.valueOf(number).split("(?<!^)"); // splits number character by character
for (String s : arr){
System.out.println(s); // Prints 9 and then 4
textfield.sendKeys(s); // Also only 9 appears
Thread.sleep(100); // Maybe browser can not work too fast, so I will wait before sending next character
}
JavascriptExecutor also send only one character and every few minutes crashes (don't know why), so I am not using it.
But what is interesting - when I do this:
textfield.sendKeys(String.valueOf(94));
It sends 94 to Chrome! I don't know where the problem is, can someone help me?
EDIT: Chrome version: 29.0.1547.76 m, Selenium Server Standalone 2.35.0, Chromedriver v2.3

Javascript on the page is messing with your input
try this code
static boolean sendKeyIntoElement(WebElement webElement, String value){
webElement.click();
webElement.sendKeys(value);
while(!webElement.getAttribute("value").equals(value)){
webElement.click();
webElement.sendKeys(Keys.CONTROL + "a");
webElement.sendKeys(Keys.DELETE);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return webElement.getAttribute("value").equals(value);
}

Related

JavaFX splitting Clipboard getString() strange behavior

I made a program using JavaFX where I have to paste into an excel like table.
I followed some tutorials online but noticed strange behavior in the way the paste code functions. After a while, I isolated the problem to the following code.
public void handlePaste() {
Clipboard clipboard = Clipboard.getSystemClipboard();
if (clipboard.hasString()) {
//start from the point that has focus
// abort if there's not cell selected to start with
if (getSelectionModel().getSelectedCells().size() == 0) {
return;
}
// get the cell position to start with
TablePosition pasteCellPosition = getFocusModel().getFocusedCell();
String pasteString = Clipboard.getSystemClipboard().getString();
int rowClipboard = -1;
Iterable<String> rowStrings = Splitter.on("\n").omitEmptyStrings().split(pasteString);
System.out.println("Print Rows");
for (String rowString : rowStrings) {
System.out.println(rowString);
System.out.println(rowString + " printing again");
}
for (String rowString : rowStrings) {
rowClipboard++;
Iterable<String> columnStrings = Splitter.on("\t").split(rowString);
int colClipboard = -1;
System.out.println("Printing Columns");
for (String columnString : columnStrings) {
System.out.println(columnString);
System.out.println(columnString + " printing again");
}
}
}
}
I use the output statement to demonstrate the problem.
Basically, I'm splitting the contents of the string based off and '\n' and '\t' characters.
The problem is whenever I try to do anything with the split strings, the string just...DISAPPEARS...
The output statements I put in demonstrate this.
Suppose the string on the clipboard is
l a
l b
l c
Then the expected output should be
Print rows
l a
l a printing again
l b
l b printing again
r c
r c printing again
Printing Columns
l
l again
a
a again
l
l again
b
b again
r
r again
c
c again
But the output ends up being
Print rows
l a
printing again
l b
printing again
r c
printing again
Printing Columns
l
again
a
again
l
again
b
again
r
again
c
again
Notice how when I try to append " printing again" to the split string, I'm simply getting blank strings.
I tried fixing the issue by using substring, and by using the standard java string splitting methods and I got the same behavior.
Finally, to fix it, I just used the java.awt Clipboard instead of the JavaFX clipboard and suddenly...it worked!
java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
java.awt.datatransfer.Clipboard awtClipboard = toolkit.getSystemClipboard();
try {
pasteString = (String) awtClipboard.getData(java.awt.datatransfer.DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException ex) {
} catch (IOException ex) {
}
Using the above line of code to get the pasteString instead of the JavaFX clipboard fixed the problem, and now I get the expected behavior and output.
For now, I will stick with the above fix, but it seems strange that the JavaFX clipboard is producing this behavior when the awt clipboard does not. Can anybody explain why this is happening? Is this a bug with the JavaFX clipboard?
LuxxMiner's comment above appears to offer a solution.
Using System.lineSeparator() also seems to work fine.
Unfortunately I found the above solutions didn't quite work out for me. The problem is that while the system seperator does get me the seperator for my systems, when I copy and paste from another program, it isn't guaranteed that the program I'm copying from is using the systems' seperator. For instance, when I copied from an excel spreadsheet, I kept getting the same strange behavior I got before, and I believe it was because excel didn't use the systems seperator.
So this is the solution I eventually came upon...
Basically it looks for ANY of the basic line seperators and splits on them.
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
Iterable<String> rowStrings = Splitter.on(CharMatcher.anyOf("\n\r")).omitEmptyStrings().split(pasteString);

Selenium sendKeys are not sending all characters

I'm using Java, Selenium, and Chrome for test automation. Our developers recently upgraded our UI from AngularJS to Angular2 (not sure if that matters). But since then, sendKeys is inputting incomplete characters in to the text field. Here's an example:
public void enterCustomerDetails()
{
txtFirstName.sendKeys("Joh201605130947AM");
txtSurname.sendKeys("Doe201605130947AM");
txtEmail.sendKeys("johndoe#gmail.com");
}
I also tried using executeScript. It didn't work. It can enter complete characters but the form thinks the field is null.
public void forceSendKeys(WebElement element, String text)
{
if (element != null)
((JavascriptExecutor) this.webDriver).executeScript("arguments[0].value=arguments[1]", element, text);
}
public void enterCustomerDetails()
{
forceSendKeys(txtFirstName, "Joh201605130947AM");
forceSendKeys(txtSurname, "Doe201605130947AM");
forceSendKeys(txtEmail, "johndoe#gmail.com");
}
I also tried using .click() before .sendKeys and adding in sleep time. They didn't work too.
I got an idea to enter the characters 1 by 1 from this post: How to enter characters one by one in to a text field in selenium webdriver?
It worked but that means I have to rewrite all my codes from sendKeys to the new function:
public void sendChar(WebElement element, String value)
{
element.clear();
for (int i = 0; i < value.length(); i++){
char c = value.charAt(i);
String s = new StringBuilder().append(c).toString();
element.sendKeys(s);
}
}
public void enterCustomerDetails()
{
sendChar(txtFirstName, "Joh201605130947AM");
sendChar(txtSurname, "Doe201605130947AM");
sendChar(txtEmail, "johndoe#gmail.com");
}
If you guys know a better way, please help! :)
I assume this is caused by this Angular2 issue https://github.com/angular/angular/issues/5808
Angular can't process input events when they arrive too fast.
As a workaround you would need to send single characters with a small delay between each.
I stumbled upon this error when doing integration tests with NightwatchJS (which uses selenium).
So I'm writing this for people coming here in the future.
I wrote this extension command for nightwatch:
exports.command = function (selector, value, using) {
var self = this;
self.elements(using || 'css selector', selector, function (elems) {
elems.value.forEach(function (element) {
for (var c of value.split('')) {
self.elementIdValue(element.ELEMENT, c);
}
});
});
return this;
};
Which can be used in this way:
var username = 'integration#test.com';
browser.setValueSlow('input[ngcontrol=username]', username); //Works with ng2!
This issue was also discussed on NightwatchJS's github here
By using Actions class, this issue solved for me
Tried many ways as mentioned above. Also tried to setvalue by js executescript
Finally, found this code and it worked well for grid component built on angular
actions.sendKeys(webElement,
modifiedValue).perform();
I was getting this error too in Java, Selenium. You might also be getting this error too while writing your codes - "sendKeys (CharSequence) from the type Webelement refers to the missing type charSequence"
I tried varying the wait time and even typing extra characters before the main characters, they did not work.
The simple trick I used was to change the Java Compiler version from JRE 9 to JRE 10.
This is due to a bug in Angular apps. Workaround is to put a sleep function.
public void setText(By element, String text) {
sleep(100); // Angular version < 2 apps require this sleep due to a bug
driver.findElement(element).clear();
driver.findElement(element).sendKeys(text);
}
i had the same problem, if you see it carefully selenium is changing the characters, some numbers perform a backspace or other symbols, i read it happens when using selenium with vncserver, i changed to firefox.... and it worked.
if that's not your problem, maybe sending the data in parts:
input1="Joh201605130947AM"
txtFirstName.sendKeys(input1[0:7])
txtFirstName.sendKeys(input1[8:end])
Using
Chromium 78.0.3904.70,
Vaadin Flow Framework 14.1.3,
Selenium 3.141.59
and OpenJDK 11.0.5
the behavior also occurs and is even worse:
I see that the character is typed in and suddenly after that it disappears.
A workaround is to be persistent and just try it again. And again. Until the character is finally typed in.
// Type in every single character
for (int i = 0; i < textToType.length(); i++) {
boolean typingCharacterWasSuccessful = false;
// If typing was not successful before, just type again
while (!typingCharacterWasSuccessful) {
// Type in the character
char singleCharacterToType = textToType.charAt(i);
htmlTextfeld.sendKeys(Character.toString(singleCharacterToType));
// Wait a little. Maybe alternatively/additionally wait.until(...)
Thread.sleep(200);
// Check typed in string.
String inputValueAfterTyping = htmlTextfeld.getAttribute("value");
if (inputValueAfterTyping.length() > i + 1) {
// Alternatively: delete everything and start all over
throw new Exception("Input value too long. Maybe character typed in twice!?");
}
// Typing was successful if the value in the input field is as expected (up to now)
typingCharacterWasSuccessful
= inputValueAfterTyping.equals(textToType.substring(0, i + 1));
}
}
I had a similar issue for big texts in Java.
I overcome the issue using the copy and paste of the text in the keyboard-related methods, as in the following method:
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
public static void clickAndSetMultilineText(WebElement element, String text) {
/** click on element **/
element.click();
/** clear older content of the text using keyboard functionality **/
element.sendKeys(Keys.CONTROL + "a"); // select all text
element.sendKeys(Keys.DELETE); // delete old text
StringSelection stringSelection= new StringSelection(text);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null); // copy text to the keyboard
element.sendKeys(Keys.CONTROL+"v"); // paste text to the field
}
Hope this is helpful.
try this code.. other way to set values using javascript
WebDriver driver = new FirefoxDriver();
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("document.getElementsByName('body')[0].setAttribute('type', 'text');");
driver.findElement(By.xpath("//input[#name='body']")).clear();
driver.findElement(By.xpath("//input[#name='body']")).sendKeys("Ripon: body text");

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

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?
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.
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.
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.
.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");
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)
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) {
}
}
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();
}
}

How many times a text appears in webpage - Selenium Webdriver

Hi I would like to count how many times a text Ex: "VIM LIQUID MARATHI" appears on a page using selenium webdriver(java). Please help.
I have used the following to check if a text appears in the page using the following in the main class
assertEquals(true,isTextPresent("VIM LIQUID MARATHI"));
and a function to return a boolean
protected boolean isTextPresent(String text){
try{
boolean b = driver.getPageSource().contains(text);
System.out.println(b);
return b;
}
catch(Exception e){
return false;
}
}
... but do not know how to count the number of occurrences...
The problem with using getPageSource(), is there could be id's, classnames, or other parts of the code which match your String, but those don't actually appear on the page. I suggest just using getText() on the body element, which will only return the page's content, and not HTML. If I'm understanding your question correctly, I think that is more what you are looking for.
// get the text of the body element
WebElement body = driver.findElement(By.tagName("body"));
String bodyText = body.getText();
// count occurrences of the string
int count = 0;
// search for the String within the text
while (bodyText.contains("VIM LIQUID MARATHI")){
// when match is found, increment the count
count++;
// continue searching from where you left off
bodyText = bodyText.substring(bodyText.indexOf("VIM LIQUID MARATHI") + "VIM LIQUID MARATHI".length());
}
System.out.println(count);
The variable count contains the number of occurrences.
There are two different ways to do this:
int size = driver.findElements(By.xpath("//*[text()='text to match']")).size();
This will tell the driver to find all of the elements that have the text, and then output the size.
The second way is to search the HTML, like you said.
int size = driver.getPageSource().split("text to match").length-1;
This will get the page source, the split the string whenever it finds the match, then counts the number of splits it made.
You can try to execute javascript expression using webdriver:
((JavascriptExecutor)driver).executeScript("yourScript();");
If you are using jQuery on your page you can use jQuery's selectors:
((JavascriptExecutor)driver).executeScript("return jQuery([proper selector]).size()");
[proper selector] - this should be selector that will match text you are searching for.
Try
int size = driver.findElements(By.partialLinkText("VIM MARATHI")).size();

java cli running indicator

I want some ascii characters periodically changing to indicate my CLI program is running, like -|\/-|/.... The old character is replaced by the new, which looks like an animation. Is there any library approaching that?
Kejia
You might want to use the carriage return(CR) character ('\r' in java) to do this. I would do it this way (assuming you are doing the animation at the beginning of the row):
My solution (Test.java):
public class Test
{
public static void main(String[] args)
{
try
{
System.out.print("\\");
Thread.sleep(1000);
System.out.print("\r|");
Thread.sleep(1000);
System.out.print("\r/");
}catch(Exception e)
{
}
}
}
Simplest idea: try replace all console (rows & cols) with new view (frame) of your animation.
I once wrote a test program and part of it worked like curl/wget to download a file. To print the progress I just used System.err.print(n); System.err.print('\r'); which moves the cursor to the start of the line ready for the next progress update. But in your case you could probably print each one of "\\\b" "-\b" "/\b" (\b is backspace) in order repetitively to get the spinning effect.
In Scala:
"-|\\/-|/".toCharArray ().foreach {c => print ("\b" + c); Thread.sleep (250); }
Analog, but more Code in Java, but not tested:
for (c : "-|\\/-|/".toCharArray ())
{
System.out.print ("\b" + c);
Thread.sleep (250);
}

Categories

Resources