Sendkeys dropping letters inconsistently - java

I'm using (new Actions(driver).sendKeys(String).perform() to send input to webdriver. However, I keep getting inconsistent results. Sometimes String is sent in perfectly, sometimes missing one or the other letter, even when the string itself is just a few characters in length.
I even tried sending the string one character at a time (using a for loop) and I'm still getting the same inconsistent behaviour - it's dropping keys less than before, but still not 100% accurate.
What could be possible reason for this, and how to solve this issue?
I'm using Chromedriver, Java/JUnit and the keyboard layout is set to US.

I'm still unclear exactly what was causing this - I see inconsistent failure to send all keys to some extjs components. I'm not sure if this is extjs doing something wierd or selenium being a bit flaky. We weren't doing anything odd in making the string or in calling send keys (except the additional wait to check the element is enabled and displayed) though so it doesn't feel like its something in our code.
My solution was to repeatedly send the keys until they visibly stick. I've wrapped the selenium api for a number of reasons so all calls to WebElements are routed through a class called WrappedElement which has the send keys method:
public void SendKeys(string text)
{
Func<string> errorMessage = () => string.Format("couldn't send keys {0} entered either {1} or {2}", text, Text, Value);
Action actionToTry = () =>
{
_element.Clear();
RawSendKeys(text);
};
Wait.RepeatedlyTry(actionToTry, () => Text == text || Value == text, errorMessage);
}
public void RawSendKeys(string text)
{
_element.SendKeys(text);
}
A simplified version of the wait method looks like this:
public void RepeatedlyTry(Action actionToTry, Func<bool> completed, Func<string> errorMessage)
{
Wait.Until(d =>
{
actionToTry();
return completed();
});
}
Where Until just calls Until on a configured DefaultWait

Related

How to pass conditional varible in using Selenium Java?

private static final String Accept = "Accept & continue";
public void acceptWorkspaceCreation() {
//Wait for Set up a Work Profile Screen for Android 9 Pixel
waitUtilByText(180, Accept);
assertTrue("Couldn't click on Accept & continue.",
findElementByIdAndClick("com.android.managedprovisioning", "next_button"));
}
public boolean waitUtilByText(int seconds, String text){
String textStr = "//*[#text='" + text + "//*[#id='";
return !new WebDriverWait(this.driver, seconds).until(ExpectedConditions.presenceOfAllElementsLocatedBy(By
.xpath(textStr))).isEmpty();
}
For some cases Accept value comes in caps 'ACCEPT & CONTINUE', How to validate both the strings in selenium.
The condition you are waiting for only checks for one thing:
ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(textStr))
So, presumably (as I am not familiar with Selenium), you can use the ExpectedConditions.or method to check a number of conditions, and wait for just one to be true:
ExpectedConditions.or(
ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(textStr)),
ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(textStr2)))
where textStr2 is the alternative text you are looking for.
I'd suggest using native Android UiSelector's textMatches method where You'd write matcher for both upper and lower case texts. If you want to stick to the Xpath anyways - it also has a text matcher. But first of all, investigate why the text changes - that's not a good practice.

Wicket IFormValidator - Mark multiple FormComponents as invalid

I have an IFormValidator that checks if the values of multiple FormComponents are coherent.
Now if validation fails, I'd like to highlight all related FormComponents and respective HTML label tags, just like it happens with Validators, that are responsible for only a single FormComponent (e.g. StringValidator).
My first try was calling FormComponent#invalid() on all related FormComponents, but that doesn't seem to do the trick, since it just calls FormComponent#onInvalid(), which does nothing by default.
The second thing I tried was calling FormComponent#error(String) on each component but that of course generates an additional error message for each FormComponent, which is not the desired behaviour. But at least it does highlight the individual invalid FormComponents.
What would be the correct way to do this? Is there a simple way I'm overlooking, since the IFormValidator#getDependentFormComponents() method, which I'm supposed to implement, already tells the Validator, which FormComponents will be invalid as a result failing the validation?
Here is a stripped down example of what I tried with Wicket 8.3:
wicketForm.add(new IFormValidator() {
#Override
public FormComponent<?>[] getDependentFormComponents() {
return new FormComponent<?>[] {formComponent1, formComponent2, formComponent3};
}
#Override
public void validate(Form<?> form) {
if (/*values of formComponent1-3 are not coherent*/) {
form.error("<error message>");
/* No highlighting at all */
formComponent1.invalid();
formComponent2.invalid();
formComponent3.invalid();
/* Highlighting works, but obviously produces same error message multiple times */
formComponent1.error("<error message>");
formComponent2.error("<error message>");
formComponent3.error("<error message>");
}
}
}
);
A FormComponent is deemed as invalid only when its #error() methods are called - see org.apache.wicket.markup.html.form.FormComponent#isValid().
If you want to show only the error feedback message of the Form then you need to instantiate your FeedbackPanel as:
new FencedFeedbackPanel("id", new ComponentFeedbackMessageFilter(form));
This way it will render the feedback messages only of the Form.
You can use the feedback messages of the form components to show their specific errors next to the respective HTML form element (input, select, etc.)

Selenium made a sendKeys for two fields instead of one for some reason

I made a pretty simple selenium test, where I want to open web page, clear field value, start entering text for this field, select first value from the hint drop down.
Web site is aviasales.com (I just found some site with a lot of controls, this is not an advertisement)
I did
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).clear();
and it was working perfectly, I also checked via console that this is the only one object on a page like:
document.getElementById('flights-origin-prepop-whitelabel_en')
So, in next line I'm sending value:
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).sendKeys("LAX");
but it send LAX value for both "flights-origin-prepop-whitelabel_en" and "flights-destination-prepop-whitelabel_en" for some reason, then i tried
DriverFactory.getDriver().findElement(By.id("//input[#id='flights-destination-prepop-whitelabel_en'][#placeholder='Destination']")).sendKeys(destinationAirport);
but I got the same result:
What could be a reason and how to fix this?
Thank you!
Yep... there's some weird behavior going on there. The site is copying whatever is entered into the first field into the second for reason I don't understand. I gave up trying to understand it and found a way around it.
Whenever I write code that I know I'm going to reuse, I put them into functions. Here's the script code
driver.navigate().to(url);
setOrigin("LAX");
setDestination("DFW");
...and since you are likely to use these repeatedly, the support functions.
public static void setOrigin(String origin)
{
WebElement e = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(origin);
e.sendKeys(Keys.TAB);
}
public static void setDestination(String dest)
{
WebElement e = driver.findElement(By.id("flights-destination-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(dest);
e.sendKeys(Keys.TAB);
}
You can see the functions but basically I click in the field, clear the text (because usually there's something already in there), send the text, and then press to move out of the field and choose the default (first choice).
The reason of your issue is the ORIGIN and DESTINATION inputbox binded keyboard event which used to supply an autocomplete list according to your typed characters.
The binded keyborad event breaks the normal sendKeys() functionality. I met similar case in my projects and questions on StackOverFlow.
I tried input 'GSO' into DESTINATION by sendKeys('GSO'), but I get 'GGSSOO' on page after the sendKeys() complete.
To resolve your problem, we can't use sendKeys(), we have to use executeScript() to set the value by javascript in backgroud. But executeScript() won't fire keyborad event so you won't get the autocomplete list. So we need find out a way to fire keyborady event after set value by javascript.
Below code snippet worked on chrome when i tested on aviasales.com:
private void inputAirport(WebElement targetEle, String city) {
String script = "arguments[0].value = arguments[1]";
// set value by javascript in background
((JavascriptExecutor) driver).executeScript(script, targetEle, city + "6");
// wait 1s
Thread.sleep(1000);
// press backspace key to delete the last character to fire keyborad event
targetEle.sendKeys(Keys.BACK_SPACE);
// wait 2s to wait autocomplete list pop-up
Thread.sleep(2000);
// choose the first item of autocomplete list
driver.findElement(By.cssSelector("ul.mewtwo-autocomplete-list > li:nth-child(1)")).click();
}
public void inputOrigin(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
return inputAirport(target, city);
}
public void inputDestination(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepopflights-destination-prepop-whitelabel_en"));
return inputAirport(target, city);
}

ContentProposalAdapter prevent new line on select proposal

I use the ContentProposalAdapter to provide content assist to my StyledText fields. I wrote an adapter that implements IControlContentAdapter, IControlContentAdapter2 to support the StyledText. My problem is that, when I press return to insert the proposal the return key is inserted into the StyledText and after that the proposal is inserted.
Why are the UP and DOWN arrows not traversed, but the return key is.
How to prevent the return key from begin inserted into the StyledText field when used to select a proposal.
maybe the question is old, but as I googled and this Post nearly covered my problem, but without a solution, I thought to provide my solution I found now.
My Problem was exactly the same but the newline got inserted after the selected proposal.
Selecting the proposal via double click works just fine so I agreed with you that it´s probably the StyledTextWidget that gets notified about the Enter...
First I tried setPropagateKeys(false) on my ContentProposalAdapter, as the doc says it "indicates whether key events (including auto-activation characters) received by the content proposal popup should also be propagated to the adapted control when the proposal popup is open". But this does not work either.
What actually worked for me is the following:
I added an VerifyKeyListener to the StyledTextWidget and just filtered the Enter Event when the ProposalPopup is open. I thought that maybe wouldn´t work as the newline gets inserted after the proposal but on my program it works fine so it seems the closure of the proposal popup is done after the Enter Key is passed to the StyledTextWidget.
Heres the code:
styledText.addVerifyKeyListener(new VerifyKeyListener() {
#Override
public void verifyKey(VerifyEvent arg0) {
try {
KeyStroke k = KeyStroke.getInstance("Enter");
if(k.getNaturalKey() == arg0.keyCode && contentProposalAdapter.isProposalPopupOpen()) {
arg0.doit = false;
}
} catch (ParseException e) {
e.printStackTrace();
}
} });
I don't know how did you implement IControlContentAdapter, IControlContentAdapter2 in your code. Did you try this? I use that in my custom StyledText implementation. But all of them are SWT.SINGLE Text fields. I hope it may help you.

IPhone password field in AWT/SWT?

I want to create a special Password Dialog for my eclipse product, which is used with an on screen keyboard.
It would be very nice, if i could use a component like the IPhone Password field. In this field, the added character is shown for a second and after the second it is converted into the '*' character for hiding the complete password.
Did a jar/library exists, this is implemented in AWT or SWT?
Edit:
I could trying to implement it from scratch (SWT), but for these i would have to create a very special and complicated KeyListener for the password Text component. I would have to catch the keyReleased event and set the characters manually into the field.
So far i was not able to find any libraries in the web. Suggestion how this can be implemented are welcome too.
This is not really a full answer, rather than a discussion starter and I don't know of any out-of-the-box widgets which can do that.
My first idea was to inheriting the swt Text widget and overriding setEchoChar et al., but after looking at the code this doesn't really seem feasible, because this method is merely a wrapper around:
OS.SendMessage (handle, OS.EM_SETPASSWORDCHAR, echo, 0);
If anyone would know the OS specific low-level implementation, that might be helpful.
Anyway, on to a different approach. I would avoid the KeyListener and use a ModifyListener on the Text-Widget.
void addModifyListener(ModifyListener listener)
You could then build a wrapper which catches the entered text using this listener, appends it to a locally held string/stringbuffer (or e.g. the Eclipse Preferencestore) and send a modified full text to the Text widget using setText(String s), replacing all characters except the last by an echo character (e.g. *).
myText.setText((s.substring(0, s.length()-1)).replaceAll("[\\s\\S]","*")+s.charAt(s.length()-1));
This is a bit of a kludge, but it should work.
The not so straightforward bit is the 1 second timing, without stalling the whole view...
Depending on what Jules said the following code is some kind of working.
The code is quick and fast and i would like to have a more thread safe solution.
originalString = new StringBuffer();
passwordField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
synchronized (passwordField) {
String s = passwordField.getText();
String newS = s.replaceAll("[\\s\\S]", "*");
if (newS.equals(s)) {
while (originalString.length() > s.length()) {
originalString = originalString.deleteCharAt(originalString.length() - 1);
}
usernameField.setText(originalString.toString());
return;
}
if (originalString.length() < s.length()) {
originalString.append(s.charAt(s.length() - 1));
}
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
}
passwordField.setText(newS);
}
passwordField.redraw();
passwordField.setSelection(passwordField.getText().length());
}
});
Key Events are cached, so you can add more characters, also when the Thread is waiting.
Another Problem is the Cursor handling. the Cursor always moves to the first position, when you set the Text.
I think when this is working it is very near to the iphone solution.

Categories