-
Notifications
You must be signed in to change notification settings - Fork 47.5k
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 ReactDOMComponentTree-test to test behavior using Public API #11383
Conversation
I think ideally instead of reading private fields and methods, we should try to test the behavior those fields and methods are used for. This would require some investigation, e.g. where is Does this make sense? |
@gaearon Makes sense. I'll investigate further this weekend. In the mean time, could you provide feedback on the test cases I added to give me an idea of whether I'm on the right track or not. |
That was my feedback: while we could do it this way, it's still testing internals more than the actual behavior. |
Would this be a plausible test for checking behavior that getInstanceFromNode is used for in renderSubtreeIntoContainer? (albeit only in DEV mode)
|
257c334
to
e5a8f23
Compare
a = null; | ||
_onChange = e => { | ||
const node = e.currentTarget; | ||
expect(node.value).toEqual(finishValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with tests like this is that if _onChange
never fires, the test passes (since none of the expectations were called). We need to move those out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comment @gaearon . I'll update to move assertions out of the event handler - this is much simpler.
Though FWIW from my understanding of async tests in Jest if done()
is never called, due to _onChange
not firing, then it would fail - albeit the failure message would not be the most helpful.
e5a8f23
to
d58071f
Compare
@gaearon I've updated the diff, can I get another review? |
2433ef3
to
f5e404c
Compare
const inputEvent = new Event('input', { | ||
bubbles: true, | ||
}); | ||
setUntrackedInputValue.call(elem, value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remind me why this is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReactDOMServer = require('react-dom/server'); | ||
document.innerHTML = ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about following this approach instead? Feels a tiny but more obvious what's going on and why IMO. d7745d6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it. Tests are more focussed on testing and we move set up to where it should be - thanks for the pointer. I'll adopt this approach.
class Component extends React.Component { | ||
it('finds closest instance for node when an event happens', () => { | ||
const nonReactElemID = 'aID'; | ||
const innerHTML = {__html: `<div id="${nonReactElemID}"></div>`}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Smart.
08c7107
to
d0d2c4b
Compare
I've updated the tests to adopt the set up and tear down approach demonstrated in d7745d6. After making changes I watched what happened as I commented out different branches of code in ReactDOMComponentTree to manually verify that the updated tests exercise and provide coverage for the module. Notable Observations:
All other blocks commented out resulted in failing tests. I'm not too sure at this point how to add/update the tests to provide coverage for lines 49-51, 66 and 69 within ReactDOMComponentTree - I'll continue to give it some thought this week. |
It would be nice to try to cover these too. On the other hand, if the original tests didn't cover those either (can you check?) maybe it's okay to merge as is :-) |
expect(currentTargetID).toBe(closestInstanceID); | ||
}); | ||
|
||
it('finds a controlled instance from node and gets its current fiber props', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to test getFiberCurrentPropsFromNode
, I think there are more assertions you might need to make. For example I can currently replace its implementation with
return node[internalInstanceKey].memoizedProps;
and the test still passes. However, this is a wrong implementation (node[internalInstanceKey]
can potentially point to an "alternate" fiber that is not "current". Current and alternate swap places on updates.)
Can we make this test more solid by tracing what happens with "current" props? e.g. maybe they're used in some way where alternate props would've been wrong. You can git blame when getFiberCurrentPropsFromNode
was added to maybe find the cases that were broken before it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detail, I'll check out the blame and track down ways to make the test more robust.
Checking out master and then commenting out those lines (49-51, 66, 69) do not result in failures - so it doesn't look like these lines are covered in the original test. Another thing of note I just realized - commenting out body of |
I appreciate the effort by the way. This is one of the harder ones. Hope you don't feel discouraged that it's not so fast. |
Not at all, it's interesting to dig into - I'm learning a lot. P.S I might be a little slower to update this week as I'm on call, will update latest by the weekend. |
I'll be on vacation this week so sounds good :-) |
- Part of facebook#11299 - I've tried to identify cases where code within ReactDOMComponentTree is exercised and have updated accordingly but I'm not entirely sure whether I'm on the right track. I thought I'd PR to get feedback from the community. Looking forward to comments.
…xhibited after use of getInstanceFromNode
…upon methods in ReactDOMComponentTree
- Use beforeEach and afterEach to set up and tear down container element for use in each test - Move any functions specific to one test to within test body (improves readability imo)
…rrentPropsFromNode - After researching usage of getNodeFromInstance we can test getNodeFromInstance dispatching some events and asserting the id of the currentTarget - After checking git blame for getFiberCurrentPropsFromNode and reading through facebook#8607 I found a test that we can simplify to assert behavior of the function by ensuring event handler props are updated from the fiber props. Swapping out the implementation of this function with `return node[internalInstanceKey].memoizedProps` results in a failure.
d0d2c4b
to
84aa535
Compare
I've replaced the original test for |
You are awesome 👏 |
…acebook#11383) * Rewrite ReactDOMComponentTree-test to test behavior using Public API - Part of facebook#11299 - I've tried to identify cases where code within ReactDOMComponentTree is exercised and have updated accordingly but I'm not entirely sure whether I'm on the right track. I thought I'd PR to get feedback from the community. Looking forward to comments. * Prettier and lint changes * Remove testing of internals and add test cases for testing behavior exhibited after use of getInstanceFromNode * [RFC] Update testing approach to verify exhibited behavior dependent upon methods in ReactDOMComponentTree * Remove tests from event handlers and use sync tests * Prettier changes * Rename variables to be more semantic * Prettier updates * Update test following review - Use beforeEach and afterEach to set up and tear down container element for use in each test - Move any functions specific to one test to within test body (improves readability imo) * Add coverage for getNodeFromInstance and implementation of getFiberCurrentPropsFromNode - After researching usage of getNodeFromInstance we can test getNodeFromInstance dispatching some events and asserting the id of the currentTarget - After checking git blame for getFiberCurrentPropsFromNode and reading through facebook#8607 I found a test that we can simplify to assert behavior of the function by ensuring event handler props are updated from the fiber props. Swapping out the implementation of this function with `return node[internalInstanceKey].memoizedProps` results in a failure.
This is part of #11299
I've tried to identify cases where code within ReactDOMComponentTree is exercised via the public API and have updated accordingly but I'm not entirely sure whether I'm on the right track. I thought I'd PR to get feedback from the community. Looking forward to comments.