Reputation: 93
I'm using jest in order to use snapshot testing.
I run into a bug within react-test-renderer, Invariant Violation: getNodeFromInstance: Invalid argument.
Minimal code to replicate the bug:
import React from 'react';
import DateTime from 'react-datetime';
import CalendarContainer from 'react-datetime/src/CalendarContainer';
export default class CalendarTimer extends DateTime {
render() {
return ( <div className = "rdtPicker" >
<CalendarContainer view = {
this.state.currentView
}/>
</div>
);
}
}
Here is the test spec file
import React from 'react';
import renderer from 'react-test-renderer';
import CalendarTimer from 'components/Input/CalendarTimer';
describe('CalendarTimer', () => {
it('rendered Calendar', () => {
const calendarTimer = renderer.create( <
CalendarTimer / >
);
expect(calendarTimer).toMatchSnapshot();
});
});
The Error:
● CalendarTimer › rendered Calendar
Invariant Violation: getNodeFromInstance: Invalid argument.
at invariant (node_modules/fbjs/lib/invariant.js:44:15)
at Object.getNodeFromInstance (node_modules/react-dom/lib/ReactDOMComponentTree.js:162:77)
at Object.findDOMNode (node_modules/react-dom/lib/findDOMNode.js:49:41)
at componentDidMount (node_modules/react-onclickoutside/index.js:153:40)
at chainedFunction [as componentDidMount] (node_modules/create-react-class/factory.js:617:11)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:265:25
at measureLifeCyclePerf (node_modules/react-test-renderer/lib/ReactCompositeComponent.js:75:12)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:264:11
at CallbackQueue.notifyAll (node_modules/react-test-renderer/lib/CallbackQueue.js:76:22)
at ReactTestReconcileTransaction.close (node_modules/react-test-renderer/lib/ReactTestReconcileTransaction.js:36:26)
at ReactTestReconcileTransaction.closeAll (node_modules/react-test-renderer/lib/Transaction.js:206:25)
at ReactTestReconcileTransaction.perform (node_modules/react-test-renderer/lib/Transaction.js:153:16)
at batchedMountComponentIntoNode (node_modules/react-test-renderer/lib/ReactTestMount.js:69:27)
at ReactDefaultBatchingStrategyTransaction.perform (node_modules/react-test-renderer/lib/Transaction.js:140:20)
at Object.batchedUpdates (node_modules/react-test-renderer/lib/ReactDefaultBatchingStrategy.js:62:26)
at Object.batchedUpdates (node_modules/react-test-renderer/lib/ReactUpdates.js:97:27)
at Object.render (node_modules/react-test-renderer/lib/ReactTestMount.js:125:18)
at Object.<anonymous> (tests/components/Input/CalendarTimer_spec.js:8:53)
at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
at process._tickCallback (internal/process/next_tick.js:103:7)
Can someone please point me what am I doing wrong , and guide me to fix the same.
Upvotes: 5
Views: 3133
Reputation: 1744
I solved it using mount of enzyme.
Testing Code
import React from 'react';
import ReactTestRenderer from 'react-test-renderer';
import { shallow, mount } from 'enzyme'; // helps to handle refs
import thunk from 'redux-thunk';
import TestComponent from 'pathtocomponent';
describe('<TestComponent />', () => {
it('should render a action model when order is approved', () => {
const component = mount(
<TestComponent
message="sample message" level="success" title="title sample"
/>
);
component.instance().componentDidMount();
expect(component).toBeDefined();
});
});
Component with Ref:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactNotificationSystem from 'react-notification-system';
export default class TestComponent extends Component {
constructor(props) {
super(props);
this.addNotification = this.addNotification.bind(this);
this.notificationSystem = null;
}
componentDidMount() {
this.notificationSystem = this.refs.notificationSystem;
this.addNotification();
}
addNotification() {
let that = this;
this.notificationSystem.addNotification({
message: that.props.message,
level: that.props.level,
position: 'tc',
autoDismiss: 4,
title: that.props.title,
});
}
render() {
return (<div>
<TestComponent ref="notificationSystem" />
</div>);
}
}
Upvotes: 0
Reputation: 11714
Relevant issue discussed here
As mentioned this happens as expected because
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!
You can see that your package react-datetime
does make use of ReactDOM for some of its inner components.
The suggested solution for third-party components is to mock them yourself with jest
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 third-party-button (replace this with your component) will become a string (e.g. ThirdPartyButton) so the component will become a “leaf” in the snapshot, like a div. Of course this won't actually test it, but it makes sense to only test your own code.
Upvotes: 2