Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite SelectEventPlugin-test to test behavior using Public API (#11299) #11676

Merged
merged 8 commits into from
Nov 29, 2017

Conversation

skiritsis
Copy link
Contributor

I rewrote one of the two tests to use Public API, but I'm not sure about the other.

The test is supposed to verify that in case we have no event listeners attached, the events are not extracted. Isn't this decision taken internally by react though? And since they are not extracted in the first place how can you verify it without tapping into React internals? Any ideas or feedback are welcome.

);
var node = ReactDOM.findDOMNode(rendered);
document.body.appendChild(childContainer);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind doing this in beforeEach and then cleaning up in afterEach? Like here.


node.selectionStart = 0;
node.selectionEnd = 0;
var node = ReactDOM.findDOMNode(childNode);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to findDOMNode. render() already gave you the right node. Old test just wasn't updated to reflect this.


var focus = extract(node, 'topFocus');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be testing that a focus DOM event would have been ignored at this point. Shouldn't the new test also verify this?


var focus = extract(node, 'topFocus');
expect(focus).toBe(null);
var nativeEvent = document.createEvent('Event');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the newer API for this? e.g. new MouseEvent('mousedown', {bubbles: true, cancelable: true})

Use newer API when creating events
@gaearon
Copy link
Collaborator

gaearon commented Nov 28, 2017

Is something blocking you from changing the second test?

@skiritsis
Copy link
Contributor Author

@gaearon Thank you for taking the time to review the changes. Like I mentioned on the description, the other test that has not been changed is supposed to "skip extraction if no listeners are present". This means that in order to test it we should not add any React event listeners on the element and make sure that the events were not emitted. Since React though internally does not emit the event if the listener is not present how can we verify the behavior without accessing its internals?

@gaearon
Copy link
Collaborator

gaearon commented Nov 28, 2017

The test was originally written in 47b147f (found it via blame). The commit description describes the issue that it was trying to solve:

For instance, if topMouseDown has been registered but not topMouseUp, event extraction will set the mouseDown flag to true but never unset it. This leads to bugs when onSelect is registered and should be firing during normal key behavior. Since no topMouseUp has yet occurred to unset the flag, onSelect fails to fire.

Perhaps you can manage to reproduce this exact problem in a new test? You can then "undo" some parts of the fix in 47b147f to verify your code still tests it.

@skiritsis
Copy link
Contributor Author

Thank you again. I will try to reproduce it with a different test and let you know.

@gaearon
Copy link
Collaborator

gaearon commented Nov 29, 2017

Please let me know if you get stuck!

@skiritsis
Copy link
Contributor Author

Sorry for the late response, I rewrote the other test as well. It may look weird and I could be way wrong here, but l'm looking at the code path and it seems to me that is exactly the same.

@gaearon
Copy link
Collaborator

gaearon commented Nov 29, 2017

If I comment out this line on master, the test fails. But it doesn't fail in this branch. Doesn't this mean we're no longer verifying that behavior?

@gaearon
Copy link
Collaborator

gaearon commented Nov 29, 2017

I think what #3639 says is not that mouseup didn't fire, but that it fired but there was no React listener for it (and thus SelectEventPlugin didn't "see" this even). React attaches top-level listeners lazily.

});
node.dispatchEvent(nativeEvent);

nativeEvent = new MouseEvent('keyup', {bubbles: true, cancelable: true});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: keyup is not a mouse event.

@gaearon
Copy link
Collaborator

gaearon commented Nov 29, 2017

I think the correct test would be:

  // See https://github.com/facebook/react/pull/3639 for details.
  it('does not get confused when dependent events are registered independently', () => {
    var select = jest.fn();
    var onSelect = event => select(event.currentTarget);

    // Pass `onMouseDown` so React registers a top-level listener.
    var node = ReactDOM.render(
      <input type="text" onMouseDown={function() {}} />,
      container,
    );
    node.focus();

    // Trigger `mousedown` and `mouseup`. Note that
    // React is not currently listening to `mouseup`.
    node.dispatchEvent(
      new MouseEvent('mousedown', {
        bubbles: true,
        cancelable: true,
      }),
    );
    node.dispatchEvent(
      new MouseEvent('mouseup', {
        bubbles: true,
        cancelable: true,
      }),
    );

    // Now subscribe to `onSelect`.
    ReactDOM.render(<input type="text" onSelect={select} />, container);
    node.focus();

    // This triggers a `select` event in our polyfill.
    node.dispatchEvent(
      new KeyboardEvent('keydown', {bubbles: true, cancelable: true}),
    );
    node.dispatchEvent(
      new KeyboardEvent('keyup', {bubbles: true, cancelable: true}),
    );

    // Verify that it doesn't get "stuck" waiting for
    // a `mouseup` event that it has "missed" because
    // a top-level listener didn't exist yet.
    expect(select.mock.calls.length).toBe(1);
  });

Copy link
Collaborator

@gaearon gaearon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I edited a bit. I think this should be good now.

@skiritsis
Copy link
Contributor Author

Thanks for editing. I believe this

but that it fired but there was no React listener for it (and thus SelectEventPlugin didn't "see" this even). React attaches top-level listeners lazily.

made it a lot more clear to me.

@gaearon
Copy link
Collaborator

gaearon commented Nov 29, 2017

Yea, took me a bit of time to figure out myself. Reading what SelectEventPlugin actually does helped.

@gaearon gaearon merged commit d83916e into facebook:master Nov 29, 2017
madeinfree pushed a commit to madeinfree/react that referenced this pull request Nov 30, 2017
…ebook#11299) (facebook#11676)

* Rewrite SelectEventPlugin-test to test behavior using Public API

* Minor refactor

* Make sure that we test that "focus" event is ignored
Use newer API when creating events

* Rewrote the other test to use Public API as well

* Tweak the test

* Remove -internal suffix

* Oops
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants