I have an unexpected issue with the sendKeys() method:
A long time before it all worked fine, but unexpectedly the (certain(!)) values are replaced when the code tries to set data into the input field:
For example, if I set value USER_NAME into the field, value replaced with /tmp/7d7b7...../upload123...file/USER_NAME. As we can see - some path was added into the USER_NAME value.
I added logs to the method and we can see a moment when the value was replaced:
clearInputFld(inputFld);
Log.info("INSIDE clearAndTypeIntoInputField() ---------> value after clearing: " + inputElement.getAttribute("value"));
Log.info("INSIDE clearAndTypeIntoInputField() ---------> value to set: " + value);
inputElement.sendKeys(value);
Log.info("INSIDE clearAndTypeIntoInputField() ---------> value after set: " + inputElement.getAttribute("value"));
Output:
INSIDE clearAndTypeIntoInputField() ---------> value after clearing:
INSIDE clearAndTypeIntoInputField() ---------> value to set: USER_NAME
INSIDE clearAndTypeIntoInputField() ---------> value after set: /tmp/7d7b7...../upload123...file/USER_NAME
So we can be sure - value sets exactly at the moment when value sets into the field.
Important to know, and conclusions:
Not all users replaced - Only several certain users! So I suppose a part of users is cached. But I do not understand the process with which this happens, why this happens, and where these users might be cached.
I also restarted the docker, so it seems the problem is not in the automatic side.
Is it possible that this issue occurs via the backend or UI part?
It looks like there is a script running on the page that changes the input you type, as this is a password field.
What I suggest is that you use the Robot object to mimic keyboard strokes.
First click on the text field using Selenium, then launch the Robot code (use package Java.awt):
Robot robot = null;
try {
robot = new Robot();
for (char c : textToType.toCharArray()) {
int keyCode = KeyEvent.getExtendedKeyCodeForChar(c);
if (KeyEvent.CHAR_UNDEFINED == keyCode) {
logger.error("Key code not found for character '" + c + "'");
} else {
try {
robot.keyPress(keyCode);
robot.delay(10);
robot.keyRelease(keyCode);
robot.delay(10);
} catch (Exception e) {
if (c == '_') {
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_MINUS);
robot.keyRelease(KeyEvent.VK_MINUS);
robot.keyRelease(KeyEvent.VK_SHIFT);
}
if (c == ':') {
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_SEMICOLON);
robot.keyRelease(KeyEvent.VK_SEMICOLON);
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}
}
}
robot.keyPress(KeyEvent.VK_ENTER);
} catch (Exception ex) {
logger.error(ex.getMessage());
}
According to Logs, I think there is something come with the value.
Suggest trying :
Get the changed text, do some operation, fill it back
string[] temp;
temp = (inputElement.Text).Split('/');
inputElement.Sendkeys(temp(temp.Length - 1));
Related
I've written a rather simple method for my paper/spigot Minecraft server plugin that detects potential lag machines under construction.
The issue I have is that I want to send a single chat message that, when clicked once, will first run a /vanish command on behalf of the clicker.
Then if (and only if) the vanish was successful, I want to run a teleport command to a location included along with the specific instance of the ClickEvent.
Both of those commands need to be completed from the single user click event.
For reference here is the method that calls notifyOps() and includes the TextComponent in question, msg
if (LagMats.contains(blockType) || mat.contains("MINECART") || mat.contains("DOOR")) {
int counter = 0;
for (Material thisMat: LagMats) {
if (thisMat != Material.GRAVEL) {
counter += Utilities.blockCounter(block.getChunk(), thisMat);
}
}
TextComponent warn = new TextComponent("WARN "); warn.setBold(true);
warn.setColor(ChatColor.RED);
TextComponent msg = new TextComponent("Potential lag-machine at " +
block.getX() + ", " + block.getY() + ", " + block.getZ() + " in " + dimension +
" by " + placer_name + " with UUID: " + placer.getUniqueId());
String cmd = "/execute in " + env + " run tp #s " +
block.getX() + " " + block.getY() + " " + block.getZ();
msg.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, cmd));
if (counter > 256) {
Utilities.notifyOps(new TextComponent(warn, msg));
}
}
Oh and the actual little code of notifyOps where the TextComponent is used in a message:
// send a message to all online ops and console
public static boolean notifyOps(TextComponent msg) {
if (msg == null) return false;
for (Player thisPlayer: Bukkit.getOnlinePlayers()) {
try {
if (thisPlayer.isOp()) thisPlayer.spigot().sendMessage(msg);
} catch (Exception e) {return false;}
}
System.out.println(msg.getText());
return true;
}
So I want to have the user click just once, run two commands, the second only if the first succeeds, and would be best if it could be done within the try block the message is sent from.
I could write a custom command for this purpose, and then just run that command, but I rather avoid adding classes for such a small addition if it's actually possible and I just have no idea.
Thanks for any advice or help!
There is no way of doing that without writing a custom command...
This is impossible because the ClickEvent and HoverEvent are entirely client-side. That means that there are no packets sent from the Player to the server. Therefore, it is impossible to callback the click of the Player and call a method to perform what you are trying to do.
You may notice that all the ClickEvent.Actions do not affect the server. OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, CHANGE_PAGE and COPY_TO_CLIPBOARD are all actions taken on the client-side.
The only way here is to make the client send a command to the server which will trigger a method.
I need to raise a warning during one of my scenario but i don't stop to have this error appearing : "Cannot infer type arguments for Result.Warning<>"
I actually tried to raise the Warning the same way i was raising Failure until now :
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
The custom step i am using it inside is the following : I'm trying to go over a list of Element and checking that the existing value of them is the same or not as the one saved before.
protected void checkXyResourcesValue(Integer xyIterator, List<WebElement> elements, String keyParameter) throws TechnicalException, FailureException {
try {
Integer resIterator = 1;
for(WebElement element : elements) {
String targetKey = "XY" + xyIterator + "RES" + resIterator + keyParameter;
String new_value = element.getAttribute(VALUE) != null ? element.getAttribute(VALUE) : element.getText();
String existing_value = Context.getValue(targetKey) != null ? Context.getValue(targetKey) : targetKey;
if (new_value != existing_value) {
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
}
resIterator++;
}
} catch (Exception e) {
new Result.Failure<>(e.getMessage(), Messages.format(TaroMessages.FAIL_MESSAGE_ACCES_CLIENT_XY_CHECK_RESOURCES_VALUE, keyParameter, xyIterator), true, oscarAccesClientPage.getCallBack());
}
}
For the method to check and saved value I actually inspired myself for the piece of code from NoraUI to save a value on Context or read it from.
I'm using Eclipse Luna 4.4.2 and i try to compile using JDK1.8.0_131.
It may be more related to me not knowing how this work in Java than a real problem so thank you in advance for your help or insights. Don't hesitate to ask if you need more information on the piece of code or the context.
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, 0);
use 0 if you do not use any Model (data serialized) or use id of your Object in the serial.
I have written a code to connect to this webpage: compilerjava.net
1) I found the text-area field within that page which accepts the code to compile.
2) I have found the button that compiles the code.
3) I have found the text-area which returns the result of the code.
The issue is, when I call textarea.setText( "something"), it (I think) doesn't actually change the code in the webpage. So when I click on the compile button, it compiles the default code within that page and returns the output of that default code.
I have tried to set focus to textarea, you can see all of those down below.
I called;
1) textArea.focus();
2) textArea.click();
3) I tried using textArea.setAttribute( "name", "code");
I have searched the internet and found various stackoverflow questions close to this problem, neither of them solved my issue and it just seems to work for everyone when they say textArea.setText().
Another interesting fact I should share with you is,
If I call textArea.setText( "...") and then I say;
HtmlTextArea textArea1 = form.getTextAreaByName( "code");
If I call textArea1.getText(), the value of this text will be "...". This should imply that I have actually managed to change the value of the text-area, but when I compile, it compiles the default text in the text-area and not the text that I have set it to.
Any help with this?
P.S: The reason why I put the result of the compilation on a while loop is related to network connection issues. If you try to run this code it might not work on your first try. Also note that the run-time is around 15 seconds, because it gives thousands of warnings which I blocked to print to console.
P.S2: I also looked at this page and none of these worked;
http://www.programcreek.com/java-api-examples/index.php?api=com.gargoylesoftware.htmlunit.html.HtmlTextArea
public class Test {
public static void main(String[] args) {
try {
// Prevents the program to print thousands of warning codes.
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(java.util.logging.Level.OFF);
java.util.logging.Logger.getLogger("org.apache.http").setLevel(java.util.logging.Level.OFF);
// Initializes the web client and yet again stops some warning codes.
WebClient webClient = new WebClient( BrowserVersion.CHROME);
webClient.getOptions().setThrowExceptionOnFailingStatusCode( false);
webClient.getOptions().setThrowExceptionOnScriptError( false);
webClient.getOptions().setJavaScriptEnabled( true);
webClient.getOptions().setCssEnabled( true);
// Gets the html page, which is the online compiler I'm using.
HtmlPage page = webClient.getPage("https://www.compilejava.net/");
// Succesfully finds the form which has the required buttons etc.
List<HtmlForm> forms = page.getForms();
HtmlForm form = forms.get( 0);
// Finds the textarea which will hold the code.
HtmlTextArea textArea = form.getTextAreaByName( "code");
// Finds the textarea which will hold the result of the compilation.
HtmlTextArea resultArea = page.getHtmlElementById( "execsout");
// Finds the compile button.
HtmlButtonInput button = form.getInputByName( "compile");
textArea.click();
textArea.focus();
// Simple code to run.
textArea.setDefaultValue( "public class HelloWorld\n" +
"{\n" +
" // arguments are passed using the text field below this editor\n" +
" public static void main(String[] args)\n" +
" {\n" +
" System.out.print( \"Hello\");\n" +
" }\n" +
"}");
System.out.println( textArea.getText());
// Compiles.
button.click();
// Result of the compilation.
String str = resultArea.getText();
while ( resultArea.getText() == null || resultArea.getText().substring(0, 3).equals( "exe")) {
System.out.print( resultArea.getText());
}
System.out.println();
System.out.println( resultArea.getText());
} catch ( Exception e) {
e.printStackTrace();
}
}
}
a little patience helps here
// Result of the compilation.
while (resultArea.getText() == null || resultArea.getText().startsWith("exe")) {
System.out.println(resultArea.getText());
Thread.sleep(500);
}
System.out.println();
System.out.println(resultArea.getText());
I am trying to type all the possible keys from Keyboard, irrespective of languages or layout using Java Robot.
We have written a super class which has common methods to print characters KeyEvent.VK_A to KeyEvent.VK_Z, number KeyEvent.VK_0 to KeyEvent.VK_9 along with SHIFT key combination.
Now coming to specific part that is if we are having Italy or Turkish Keyboard which are having Unicode present or if any other special character. How can I stimulate the same keypress or keyrelease ? (as there is no valid KeyCode present for such characters)
Say we have ò,à,ù or *,§, etc
I am trying this on JDK 1.6. Here is Code snippet
protected void keyPressRelease(int keyCode){
try{
this.robot.keyPress(keyCode);
this.robot.keyRelease(keyCode);
}catch(java.lang.IllegalArgumentException e){
logger.error("keyPressRelease() No key present "+KeyEvent.getKeyText(keyCode)+ " for Key Code :"+keyCode);
logger.error("Error in typing ",e);
this.errorBuilder.append("IllegalArgumentException keyPressRelease(), No key present "+KeyEvent.getKeyText(keyCode)+ " for Key Code :"+keyCode+"<br\\>");
}catch(Exception e){
logger.error("keyPressRelease() No key present "+KeyEvent.getKeyText(keyCode)+ " for Key Code :"+keyCode);
logger.error("Error in typing ",e);
this.errorBuilder.append("Exception keyPressRelease(), No key present "+KeyEvent.getKeyText(keyCode)+ " for Key Code :"+keyCode+"<br\\>");
}
}//End of keyPressRelease()
protected void shiftKeyPress(int keyCode){
this.robot.keyPress(KeyEvent.VK_SHIFT);
try{
this.robot.keyPress(keyCode);
this.robot.keyRelease(keyCode);
}catch(java.lang.IllegalArgumentException e){
logger.error("shiftKeyPress() No key present "+KeyEvent.getKeyText(keyCode)+ " for Key Code :"+keyCode);
this.errorBuilder.append("Exception shiftKeyPress(), No key present "+KeyEvent.getKeyText(keyCode)+ " for Key Code :"+keyCode+"<br\\>");
}
this.robot.keyRelease(KeyEvent.VK_SHIFT);
}//End of shiftKeyPress()
protected void typeLableName(int keyCode){
String labelName = KeyEvent.getKeyText(keyCode);
type(labelName+" ");
labelName = null;
}//End of typeLableName
//Windows 7 , normal keyboard, from Control panel changed the layout to Italy
private void checkSplCharacters(){
this.keyPressRelease(KeyEvent.VK_ENTER);
/*Start of --> § Cedilla Small*/
this.typeLableName(KeyEvent.VK_BACK_SLASH);
this.keyPressRelease(KeyEvent.VK_BACK_SLASH);
this.keyPressRelease(KeyEvent.VK_ENTER);
this.typeLableName(KeyEvent.VK_BACK_SLASH);
this.shiftKeyPress(KeyEvent.VK_BACK_SLASH);
this.keyPressRelease(KeyEvent.VK_ENTER);
/*End of --> § Cedilla Small*/
/*Start of --> ì Grave Small*/
this.typeLableName(KeyEvent.VK_PLUS);
this.keyPressRelease(KeyEvent.VK_PLUS);
this.keyPressRelease(KeyEvent.VK_ENTER);
this.typeLableName(KeyEvent.VK_PLUS);
this.shiftKeyPress(KeyEvent.VK_PLUS);
this.keyPressRelease(KeyEvent.VK_ENTER);
/*End of --> ì Grave Small*/
}//End of checkSplCharacters
some of the points running in mind
A dummy point, is it possible to know the position of the Keys say mapping in the format of rows & columns? If so which API will return the keyboards rows? & then I will try to run in loop for that row & that key.
Read some places with Numpad + ALT key, also it seems this works on Windows & what if Numpad is not there ?
Took a refernce from here
Can we create our own customized mapping for same & is there a possible way to overwrite ?(any snippet for it)
Or any other possible way to type/ perform java robot for unicode/special characters.
Am trying some what below thing
Basically want to type ò,à,ù or *,§, using java Robot. So String a = "ò,à,ù or *,§"; //Unicode charactres
try{
Robot robot = new Robot();
for(int i=0;i
robot.keyPress(?);//What would be the equivalent key code for above Unicodes
}
}catch(Exception e){
}
I'm building an application that shows in a WebView some remote data that is cached in SQLite db. The data is being requested by JavaScript function from WebView via JavaScript interface.
When user types into an input element on the page, JavaScript function requests search result by calling Java function, which in turn fires a sql query. Results are then packaged in suitable JSON format and returned.
Fetching data works OK unless you type very quickly. If you type quick enough after few key presses the app quits WITHOUT any exceptions being thrown, it just goes back to home screen.
I have managed to narrow down the cause - commenting out the call to .query method prevents crashing, but renders app useless.
Is there a way to check what caused application to quit, another log or tool that could help?
Java function code:
public Lot[] getLotList(String query, int limitCount) {
...
...
String[] resultColumns = new String[] { LotsSearch._ID };
String queryWhere = LotsSearch.TABLE_NAME + " MATCH ?";
String[] queryArgs = new String[] { query + "*" };
String sortOrder = LotsSearch.COLUMN_NAME_NUMBER + " ASC, " + LotsSearch.COLUMN_NAME_TITLE + " ASC";
String limit = null;
Cursor cursor = null;
if (limitCount != -1)
limit = "0," + limitCount;
try {
cursor = mDb.query(LotsSearch.TABLE_NAME, resultColumns, queryWhere, queryArgs, null, null, sortOrder, limit);
if (cursor != null && cursor.moveToFirst()) {
result = new Lot[cursor.getCount()];
try {
int idColumnIndex = cursor.getColumnIndexOrThrow(LotsSearch._ID);
int lotId;
Lot lot;
do {
lotId = cursor.getInt(idColumnIndex);
lot = mLots.get(lotId);
if (lot != null)
result[index++] = lot;
} while (cursor.moveToNext());
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
} catch (SQLiteException e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
...
...
return result;
}
UPDATE:
I have discovered that there is another log that could be accessed by issuing
logcat -b events
when the app crashes there is just one entry
I/am_proc_died( 59): [11473,com.example.app]
and when the app exits gracefuly this log shows set of entries:
I/am_finish_activity( 59): [1157978656,22,com.example.app/.MainActivity,app-request]
I/am_pause_activity( 59): [1157978656,com.example.app/.MainActivity]
I/am_on_paused_called(11473): com.example.app.MainActivity
I/am_destroy_activity( 59): [1157978656,22,com.example.app/.MainActivity]
I'd make a change to my auto search function. Namely, only perform the search if the user hasn't pressed a key for about 1/2 a second.
If you are typing fast, then this function is being executed several times right on top of itself, before the results are even able to come back. Meanwhile you are probably have too many cursor resources going at once causing the app to just completely fail.
update. If you consider it, typing 10 keys fairly quickly in a row could potentially mean that you have 10 different queries executing and parsing results... There could certainly be some deadlocking issues with the code that actually calls the getLotList method if it's spun multiple threads to try and update the UI. This can lead to some programs simply giving up the ghost not knowing what to do or even what thread to report the issue on.
Of course, all of that's hard to tell from the small snippet we have.