How do I enter text in textfield with onkeyup/onfo

2019-02-28 23:50发布

问题:

We have a web application that I am trying to automate testing for, using Java, Web Driver and TestNG. The biggest challenge I'm facing (failing at) is to stay ahead of development and prevent the test framework from breaking with even minor code changes.

Problem

  • There's a text field that accepts numbers. Up till now, sendKeys did the job for me.
  • In a recent change to the page source, when numbers are entered, commas get automatically inserted.
  • So "50000" becomes "50,000" for example.
  • Now sendKeys enters the value correctly, but after I move out of the field to editing other fields, the value resets to 0.

Here's the source for the element. Note the values for onkeyup and onfocus:

<input type="text" class="form-control tooltip-default" id="my_budget" value="" data-mask="fdecimal" data-rad="." data-toggle="tooltip" data-placement="top" data-original-title="test tooltip" onfocus="removeErrors('my_budget');" onkeyup="removeNegativeSign('my_budget');">

I've faced this issue before, and tried to hack a solution using W3Schools and other research.

Approach 1: Keys.TAB

I've read that sendKeys(Keys) can trigger a keyup event, so I tried sending Keys.TAB

driver.findElement(By.id("my_budget")).sendKeys(Keys.TAB);

This had no effect whatsoever.

Approach 2: send keyDown-keyUp

I used this question as a reference, and just simulated pressing the Ctrl-key.

    new Actions(driver).keyDown(driver.findElement(By.id("my_budget")), Keys.CONTROL).keyUp(driver.findElement(By.id("my_budget")), Keys.CONTROL).perform();

This had no effect whatsoever.

Approach 3: execute Javascript manually

Finally, I tried manually executing the Javascript, first for onfocus, then when that didn't work, for onkeyup.

    SeleniumHelper.doJavascriptOnElement(driver, driver.findElement(By.id("my_budget")), driver.findElement(By.id("my_budget")).getAttribute("onfocus"));

    SeleniumHelper.doJavascriptOnElement(driver, driver.findElement(By.id("my_budget")), driver.findElement(By.id("my_budget")).getAttribute("onkeyup"));

This caused errors that indicate that the Javascript was not found:

Caused by: java.lang.Exception: org.openqa.selenium.WebDriverException: unknown error: removeErrors is not defined

Question

So -

  • How do I enter text in textfields where an onkeyup or onfocus (or other) Javascript is active?
  • How do I program around this situation (where the code changes on me) in the future? Is there perhaps an "intelligent" sendKeys that I am unaware of?

回答1:

And I found the answer after a day of digging.

To enter text in text-fields with an onfocus Javascript, I need to click() the text-field webelement:

driver.findElement(By.id("my_budget")).click();

This worked - the Javascript executed upon entering the value.

To make entering text + generating events a little easier, I have created a method:

To call this:

sendKeysWithEvent(driver, driver.findElement(By.id("my_budget")), "50000", "onfocus");

Methods:

public static void sendKeysWithEvent(WebDriver driver, WebElement element, String text, String event) throws Exception {
    element.sendKeys(text);
    switch(event) {
    case "keyup":
        new Actions(driver).keyDown(element, Keys.CONTROL).keyUp(element, Keys.CONTROL).perform();
        break;
    case "onblurJS":
        doJavascriptOnElement(driver, element, element.getAttribute("onblur"));
        break;
    case "onfocus":
        element.click();
        break;
    case "keyupJS": 
        doJavascriptOnElement(driver, element, element.getAttribute("onkeyup"));
        break;
    case "keyupTAB":
        element.sendKeys(Keys.TAB);
        break;
    }

}
public static void doJavascriptOnElement(WebDriver driver, WebElement element, String javascript) throws Exception {
    ApiHelper.doLog("Running Javascript: " + javascript);
    ((JavascriptExecutor) driver).executeScript(javascript, element);

}