10

We have a relatively simple React component with an input element in it:

export class MyInput extends Component {
  componentDidMount() {
    function log(e) {
      console.log(`Event: ${e.type}, isTrusted: ${e.isTrusted}, input value: ${e.target.value}`, e);
    }

    this.rawInput.addEventListener("change", log);
    this.rawInput.addEventListener("input", log);
  }

  onChanged(e) {
    console.log("raw-input.onChanged: e.target.value", e.target.value);

    this.props.onChanged(e.target.value);
  }

  render() {
    return (
      <div className="my-class">
        <input
          value={this.props.value}
          onChange={this.onChanged.bind(this)}
          ref={(input) => { this.rawInput = input; }}
          />
      </div>
    );
  }
}

Basically, this is just a slightly wrapped input element, while the logging added on top is for debug purposes.

It handles typing just fine in regular usage, it also handles SendKeys under Selenium WebDriver in Chrome, Firefox and IE 11 (provided that WebDriver's EnableNativeEvents is true).

However, when run in Internet Explorer 11 by WebDriver and with EnableNativeEvents = false, the onChanged event is not fired when SendKeys is executed. What's most weird is that the HTML input event is fired. Below is the console output: Missing onChange under WebDriver

Notice that the input's value is changing while "test" is being typed, but there's no onChange.

Below is an expanded input event in case of WebDriver: Detailed input event from WebDriver

If a user then types via keyboard in the same input, the onChange event is there: onChange is successfully fired on real typing

Below is an expanded input event in case of user typing: Detailed input event when user is typing

Close analysis shows that the only difference in the input events is that under WebDriver isTrusted: false, while on real typing isTrusted: true.

The question is why in the first case onChange events are not fired by React?

I assume this is because React skips events with isTrusted: false because this means they are simulated, not real user events. However, I was not able to find any proof for this. If it's the case, would you mind providing a link to a post or a line in React sources that handles it?

  • React: 16.7.0
  • Selenium.WebDriver.IEDriver: 3.14.0
Pavel Gatilov
  • 7,579
  • 1
  • 27
  • 42
  • Did you try to compare event objects from both actions? – r g Apr 12 '19 at 14:25
  • @fard, if you mean comparing WebDriver's SendKeys and user typing - yes, I have compared the objects, and at least on the first level of properties the only difference is the `isTrusted` property value – Pavel Gatilov Apr 12 '19 at 14:30
  • I mean whole event object – r g Apr 12 '19 at 14:31
  • @fard, added to the question. On the first level, I don't see any differences other than `isTrusted`. Not sure if it makes sense to expand deeper. Events' `srcElement` and `target` point to the same correct input element. Should I investigate something specific? – Pavel Gatilov Apr 12 '19 at 14:44
  • The `onChange` event is not fired because the driver doesn't emulate this event when `EnableNativeEvents` is false. This has nothing to do with `isTrusted`. The issue lies with the [injected code](https://github.com/SeleniumHQ/selenium/blob/master/javascript/atoms/keyboard.js) used by the driver. – Florent B. Apr 18 '19 at 08:52
  • @FlorentB., thank you, it's an interesting thought. However, I would not expect any driver to emulate this event, as this is a React-specific synthetic event. As far as I can tell, React handles the raw `input` and `change` events from HTML DOM, and converts them into its own `onChange` event. From HTML DOM perspective, I don't see any differences: both user typing and web driver `SendKeys` fire only `input` events in IE 11 (while focus stays in the input element). I would say the web driver behavior seems fine. – Pavel Gatilov Apr 22 '19 at 09:31

1 Answers1

7

When setting the nativeEvents capability to false (which is what you’re setting with the EnableNativeEvents property), you’re telling the IE driver to use JavaScript to simulate the events. Events simulated via JavaScript cannot have the isTrusted property set to true. That property is designed to detect exactly the scenario you’re experiencing. The driver implementations for Firefox and Chrome are produced and maintained by the vendors for those browsers (Mozilla and Google, respectively), and as such, those drivers have access to internals of the browser in ways that the IE driver does not (and likely never will) have. If React is indeed keying off that property to fire the onChanged event, then the proper thing to do here is set EnableNativeEvents = true.

JimEvans
  • 27,201
  • 7
  • 83
  • 108
  • Thank you for your explanation. It confirms my general assumptions. Any chance you know if React does filter by `isTrusted`? I wasn't able to find anything like this in the sources, so I wonder if something else is getting in the way – Pavel Gatilov Apr 12 '19 at 16:00