-
Notifications
You must be signed in to change notification settings - Fork 46.4k
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
ReactTestRenderer doesn't work with refs or ReactDOM.findDOMNode #7371
Comments
Thanks for the well documented issue! I'll leave it to @spicyj since he did the hard work on this. |
Hm, after #7258 (which should be in 15.3.0) it give you null for any ref and should not throw. It's expected that ReactDOM.findDOMNode doesn't work. |
So would it be safe to say that snapshot testing on something like react-frame-component wouldn't work? |
Looks like React also logs a warning when using refs with
caused by code similar to this example: const DummyComponent = React.createClass({
render() {
return <div ref="main">content</div>;
}
}); (I can put up an example on github if you want) |
It wouldn’t, but there are a few possible options:
Any solutions you prefer? |
We had the same problem, but solved it using the componentWillMount: function() {
this._refs = {};
},
componentDidMount: function() {
this._refs[`textRefId`].focus();
},
render: function() {
return <TextInput ref={(c) => this._refs[`textRefId`] = c; } />;
}, |
@gaearon sorry missed your comment.
That would be the preference as I'm asserting the children of the frame component. |
I don't think providing a mock DOM node would be the best solution here. We'd have to implement the full DOM node API so that when it's actually used it doesn't throw. It would be better if we could have an optional integration with jsdom (or whatever the user chooses to use), so that we can use a full implementation of the DOM and avoid having to implement and maintain our own mock API. |
Refs work with test renderer in master, and you can even mock them to return something else instead of null: import React from 'react';
export default class MyInput extends React.Component {
componentDidMount() {
this.input.focus();
}
render() {
return (
<input ref={node => this.input = node} />
);
}
} import React from 'react';
import MyInput from './MyInput';
import renderer from 'react-test-renderer';
function createNodeMock(element) {
if (element.type === 'input') {
return {
focus() {},
};
}
return null;
}
it('renders correctly', () => {
const tree = renderer.create(
<MyInput />,
{createNodeMock}
).toJSON();
expect(tree).toMatchSnapshot();
}); There are no plans to support |
For some reason I still can't use |
React test renderer is not coupled to React DOM. It can't "guess" which DOM APIs your component relies on. You need to mock the nodes yourself, as noted in 15.4.0 release notes. I hope this helps! |
* Upgrade dependencies to fix build breakages We've had some lint-related build failures: https://travis-ci.org/graphql/graphiql/builds/181453346 lately. Unfortunately, these masked test failures introduced by 35d8d38. When we fixed the lint (1eeb36c), the test failures showed up: https://travis-ci.org/graphql/graphiql/builds/182431531 This commit fixes that by upgrading our deps: - Replace "react-addons-test-utils", which access a path that doesn't exist in current "react-dom", with "react-test-renderer". This required some API updates in the tests, but also some changes to use ref-based DOM node access rather than `ReactDOM.findDOMNode`, which doesn't work in "react-test-renderer". See: - facebook/react#7371 - facebook/react#8324 > Yea sorry, refs can work but `findDOMNode()` can't (we tried). * Update package.json
What is the recommended heuristic to detect that Edit: to elaborate: this is for a component library, so mocking (inside the library at least) is not an option |
Is there any idea how to overcome this bug? I have few third party components (like https://github.com/ericgio/react-bootstrap-typeahead/) which uses |
any help for the 10-thumbs-up comment will be really appreciated :D |
This is not a bug. As explained above it is intentional. The workaround is simple if you use jest. Just mock the third party component causing issues. For example: jest.mock('third-party-button', () => 'ThirdPartyButton'); Put this at the top of your test file. Now any imports of For libraries exporting multiple components, the workaround is similar but you'd want to provide a different mock. Something like: jest.mock('third-party-lib', () => {
return {
ThirdPartyButton: 'ThirdPartyButton',
OtherThing: 'OtherThing',
};
})); Finally, as last option, you can mock jest.mock('react-dom', () => ({
findDOMNode: () => ({}),
}); Note you can return anything there and adjust it to match the expectations of the tested code. All of this works if you use Jest. Unfortunately I don’t have good solutions for other runners. |
Thanks a lot for this helpful comment 👍🏻 |
This is how I mocked 3rd party dependency that used react-dom findDOMNode in my app.
Drawback in this is that if that 3rd party dependency changes diretory structure etc, then this will break. |
Mocking refs and canvas was easy using:
|
Jest snapshot testing uses ReactTestRenderer but if my component contains a ref or uses
ReactDOM.findDOMNode
it throwsTypeError: component.getPublicInstance is not a function
.Component
Test
stack trace
The text was updated successfully, but these errors were encountered: