Skip to content

Rewrite ReactDOMInput-test depending on internal API (#11299) #11309

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

Merged
merged 29 commits into from
Oct 26, 2017

Conversation

SadPandaBear
Copy link
Contributor

@SadPandaBear SadPandaBear commented Oct 20, 2017

Should help on #11299.

I hope these changes may help with the public APIs on the other tests (especially inputValueTracking-test).

I'm pretty sure it needs more refactoring and I would appreciate if you could help me pointing the most whopping ones.

As @sebmarkbage stated, ReactTestUtils should be considered a non-public API, since it reaches into internals in a way.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

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

We're trying to test what happens when the browser changes its internal value of a field. Which it can do without invoking the setter.

What you could do is extract the native setter before we can mutate it. E.g. in beforeEach before the requires.

setUntrackedValue = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set;

Then later use:

setUntrackedValue.call(node, 'giraffe');

Note the use of .call.

var nativeEvent = document.createEvent('Event');
nativeEvent.initEvent('change', true, true);
node.dispatchEvent(nativeEvent);
ReactTestUtils.SimulateNative.change(node, {target: {value: 'giraffe'}});
Copy link
Collaborator

Choose a reason for hiding this comment

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

How do we know that this actually does anything at all? I'm not sure this actually tests the behavior we're trying to test. Since this is a no-change test.

Copy link
Contributor Author

@SadPandaBear SadPandaBear Oct 21, 2017

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but ReactTestUtils.SimulateNative.change actually needs to have an element listening to an event to be applied. Any change dispatched to this element won't have any consequences (e.g the value will still be the same). So, judging that in this case, where there's no event at all, makes more sense this way.

You can check a similar case here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sebmarkbage Thank you for the hint with setUntrackedValue.call(node, 'giraffe');!
It's way more flexible too! Working on right now!

@SadPandaBear
Copy link
Contributor Author

SadPandaBear commented Oct 21, 2017

Doubt: Will the changes with setUntrackedValue.call be applied for all the node.value settings tests or just the ones using native event dispatchers?

@gaearon gaearon changed the title Rewrite tests depending on internal API (#11299) Rewrite ReactDOMInput-test depending on internal API (#11299) Oct 21, 2017
@gaearon gaearon mentioned this pull request Oct 21, 2017
26 tasks
nativeEvent.initEvent('change', true, true);
node.dispatchEvent(nativeEvent);
setUntrackedValue.call(node, 'giraffe');
ReactTestUtils.SimulateNative.change(node);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hm. What happens if you use the native event dispatching like it was before? Does the test still pass? If so, we should ideally use that mechanism instead since it doesn't rely on by-passing the document event listeners.

ReactTestUtils.SimulateNative is reaching into internals in a way. That's exactly what we'd like to avoid with these changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally agree, I'm gonna check it out right now and post here the results.

Copy link
Contributor Author

@SadPandaBear SadPandaBear Oct 23, 2017

Choose a reason for hiding this comment

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

@sebmarkbage Yes, the tests are passing indeed.

Plus, I think using something like the node.dispatchEvent(nativeEvent); seems to be a very flexible way to obtain the expected results without reaching those internals.

Copy link
Collaborator

@gaearon gaearon Oct 26, 2017

Choose a reason for hiding this comment

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

Btw I verified that using SimulateNative would have still (incorrectly) passed the test if I removed this line. Whereas with native dispatch it is covered (and fails as it should).

// I don't know how to simulate a change event on a text box.
this.a.dispatchEvent(changeEvent);
this.b.focus();
dispatchEventOnNode(this.a, 'change');
Copy link
Collaborator

Choose a reason for hiding this comment

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

This has lost the focus() call. It is important. I verified that removing the fix in 84b8bbd (where this test was introduced) fails on master, but doesn't fail here anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gaearon Wow, I really wasn't aware of that fix. Thank you! 😃

setUntrackedValue(instance.a, 'giraffe');

instance.a.dispatchEvent(inputEvent);
setUntrackedValue.call(instance.a, 'giraffe');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same, but for blur().

They are necessary to cover for the fix in facebook#8240.
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.

This looks good to me now. I verified that reverting the fixes added with those tests also breaks the tests now.

@gaearon gaearon merged commit 55b3172 into facebook:master Oct 26, 2017
@gaearon
Copy link
Collaborator

gaearon commented Oct 26, 2017

Sweet. Thanks so much. Do you want to help out reviewing other related PRs now that you have some experience with the kind of issues that come up testing these corner cases?

@SadPandaBear
Copy link
Contributor Author

SadPandaBear commented Oct 26, 2017

Yes, I would appreciate to help out!

Actually, I'm sure we got time, but we must verify if there's any inactive individual assigned with a test in order to liberate it so more people can come out and help with the issue

@gaearon
Copy link
Collaborator

gaearon commented Oct 26, 2017

Yeah, I plan to reach out to folks who took other tests within a few days. Need to review existing ones first :-)

Ethan-Arrowood pushed a commit to Ethan-Arrowood/react that referenced this pull request Dec 8, 2017
…facebook#11309)

* Rewrite tests depending on internal API

* Remove focus being called when there was no blur event function before

* Remove triggering function and just let ReactTestUtils take care

* Use native events

* Remove duplicate

* Simulate native event when changing value on reentrant

* Change wasn't being called

* Use Simulate only

* Use React event handlers on test

* Move commentary

* Lint commit

* Use native event

* Comment native event dispatching

* Prettier

* add setUntrackedValue

* Prettier-all

* Use dispatchEvent instead of ReactTestUtils Simulates;

* Prettier

* Fix lint

* Remove useless arg

* Wrap event dispatcher into function

* Remove deprecated Event

* Remove unused change event dispatcher

* Fix merge

* Prettier

* Add missing focus/blur calls

They are necessary to cover for the fix in facebook#8240.
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.

4 participants