How to use webkeys() to insert text in a webview and trigger onChange event with Espresso

Viewed 803

I have a webview containing an input field and a button below it (webview is 3rd party code) When I open the view on my phone, as soon as I insert a digit into the field, the button changes color and is enabled.

The input field is

 <input type="tel" name="input" id="input" class="inputbox"  autocomplete="off" placeholder="number" value="">

When I run my automatic test with Espresso I can put text into the field but the button is not enabled

 onWebView().withElement(findElement(Locator.ID, "input"))
            .perform(clearElement())
            .perform(DriverAtoms.webKeys("22222222"))
            .perform(webClick())
            .withElement(findElement(Locator.ID, "continueButton"))
            .perform(webClick());

Firefox inspector shows there is an event listener for the onChange event whose listener I suppose is this one:

            function(e) {
          e.persist();
          var t = /^[0-9\b]+$/;
          d((function(a) {
            return Object(c.a)(Object(c.a)({}, a), {}, Object(M.a)({}, e.target.name, t.test(e.target.value) ? e.target.value : e.target.value.replace(/[^0-9]/g, "")))
          })), e.target.value.replace(/[^0-9]/g, "").length > 0 ? (j(!1), b("primary"), k(""), R("")) : (b("primary disabled"), k("hidden"), R("paddingTop20"))
        }

So I tried triggering the onchange with no luck:

   onWebView().forceJavascriptEnabled().withElement(findElement(Locator.ID,    "input"))
            .perform(clearElement())
            .perform(webClick())
            .perform(DriverAtoms.webKeys("22222222"))
            .perform(webClick())
            .perform(SimpleAtom("function(elem) {\n" +
                    "var e = document.createEvent('Event');\n" +
                    "e.initEvent('change', false, true);\n" +
                    "elem.dispatchEvent(e);}"))
            .perform(webClick())
            .withElement(findElement(Locator.ID, "continueButton"))
            .perform(webClick());

If I insert numbers with keyboard continueButton becomes enabled and I can click it and proceed with the text, but using webkeys() does not work. How can I trigger the onChange event (or whatever event is needed) similar like using the keyboard and perform the webclick() with Espresso?

1 Answers

I made a Node.js web server and I downloaded Android Studio to make some tests. Here is the HTML page I tested based on your informations :

var input = document.getElementById("input"),
    button = document.getElementById("continueButton"),
    result = document.getElementById("result"),
    label = document.querySelector('.button_label');

input.addEventListener('input', (event) => {
  button.addEventListener('click', (event) => {
    result.innerHTML = "click success!";
  });
  
  button.classList.remove("disabled");
});
.disabled {
  background-color: red;
}
<form onclick="event.preventDefault();">
  <input type="tel" name="input" id="input" class="inputbox"  autocomplete="off" placeholder="number" value="">
  <button class="disabled" id="continueButton"><span class="button_label">number</span><i class="spinner"></i></button>
</form>

<p type="text" name="result" id="result"></p>

I used your Espresso tests and both of them work fine for me. Simple version which works also :

onWebView().withElement(findElement(Locator.ID, "input"))
               .perform(DriverAtoms.webKeys("22222222"))
               .withElement(findElement(Locator.ID, "continueButton"))
               .perform(webClick());

To me, your code is good. It works in my local computer.

Now, it is difficult to debug without the third party webview to reproduce exactly the problem. Maybe it comes from the event which is not good. webKeys could triggered the wrong event which is not listenned by the webapp. Also, to your second try to trigger event manually, it is probably not the change event that you should use because change doesn't get triggered by keyboard which is the case in your situation.

Another explanation could be that you don't choose the good elements to click on : .button_label instead of continueButton ? Indeed, if you replace in my example button.addEventListener by label.addEventListener, the Espresso test won't work anymore, but it will work if you do it manually with your keyboard.

To investigate more, I need the URL of the page load in the webview.

Little note, your way of firing event is deprecated. You should use the constructor :

var event = new Event('change');
input.dispatchEvent(event);
Related