问题
I'm trying to setup some integration tests of some react components that are connected to our redux store.
Our general pattern is a const (instead of a component) which is "connect"ed with redux to the store (I think this is just background to the issue, as I have the same problem with a normal component).
I am following https://testing-library.com/docs/example-react-redux
I get this error
console.error node_modules/react/cjs/react.development.js:172
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check your code at feedback.test.js:32.
console.error node_modules/react-dom/cjs/react-dom.development.js:19814
The above error occurred in the <Provider> component:
in Provider (at feedback.test.js:26)
This is my test
import React from 'react';
import {createStore} from 'redux'
import {Provider} from 'react-redux'
import {render, getByTitle, fireEvent} from '@testing-library/react'
//import '@testing-library/cleanup-after-each'
import '@testing-library/jest-dom/extend-expect'
import {FeedbackContainer} from '../feedbackContainer'
import {defaultState, reducer} from '../../../../redux/modules/feedback'
function renderWithRedux(
component,
{
initalState, store = createStore(reducer, defaultState)
} = {}
) {
return {
...render(<Provider store={store}>{component}</Provider>)
}
}
it('increments the counter', () => {
console.log(<FeedbackContainer/>)
const {container} = renderWithRedux(<FeedbackContainer />) <-- line 32
})
My container component looks like this:
import { connect } from 'react-redux';
import { Feedback } from './feedback';
import { compose, lifecycle, withHandlers } from 'recompose';
import { actions } from '../../../redux/modules/feedback';
export const mapStateToProps = (state, ownProps) => ({
// snipped state maps
});
export const mapDispatchToProps = {
// snipped functions
};
const enhance = compose(
connect(mapStateToProps, mapDispatchToProps),
withHandlers({
sendFeedbackHandler: props => () => props.sendFeedback(props),
handleResize: props => () => props.setWindowSize(),
}),
lifecycle({
componentDidMount() {
const {handleResize} = this.props
window.addEventListener('resize',handleResize);
},
componentWillUnmount() {
this.props.clearFeedback();
const {handleResize} = this.props
window.removeEventListener('resize', handleResize);
},
}),
);
export const FeedbackContainer = enhance(Feedback);
The feedback.js looks like this:
import React from 'react';
import ReactStars from 'react-stars';
export const Feedback = (props) => {
const ratingChanged = (rating) => {
props.setRating(rating);
}
const {sendFeedbackHandler} = props
var title = null;
switch (props.type) {
case "REF":
title = "Rate this FAQ"
break;
default:
title = "Rate my experience"
break
}
var feebackLayout;
var buttonClassNames = "btn btn-success btn-cons pull-right";
if (props.apertureWidth > 768) {
buttonClassNames += " margin-right-0px ";
feebackLayout = (
<div>
<h5 className="light semi-bold text-center" style={{"margin":"0px"}}>
{title}
</h5>
<div style={{"textAlign":"center"}}>
<div data-test-id='feedback-stars' className="center" style={{"display":"inline-block","float":"none"}}>
<ReactStars
value={props.rating}
count={5}
onChange={ratingChanged}
size={24}
color2={'#ffd700'}
half={false}
/>
</div>
</div>
</div>
)
} else {
buttonClassNames += " margin-right-14px ";
title = "Rate this:"
feebackLayout = (
<div style={{"textAlign":"center"}}>
<h5 className="light semi-bold text-center"
style={{"margin":"0px","display":"inline","verticalAlign":"middle","paddingRight":"10px"}}>
{title}
</h5>
<div style={{"textAlign":"center","display":"inline-block","verticalAlign":"middle"}}>
<ReactStars
value={props.rating}
count={5}
onChange={ratingChanged}
size={24}
color2={'#ffd700'}
half={false}
/>
</div>
</div>
)
}
return (
<div className="card card-default feedbackCard" style={{"height": "100%","borderTopRightRadius": "2px", "borderTopLeftRadius": "2px"}}>
<div className="card-block" style={{padding: '20px 20px 20px 20px'}}>
<div hidden={props.feedbackSubmitted}>
{feebackLayout}
<div hidden={props.feedbackHidden}
style={{"paddingTop": props.apertureWidth > 768 ? "0px" : "10px"}}>
<div>
<textarea
data-test-id='feedback-text'
className="form-control"
style={{"height":"unset"}}
placeholder="Add any comments"
rows={2}
onChange={event => props.setFeedback(event.target.value)}
/>
</div>
<div style={{paddingTop: "5px"}}>
<button
data-test-id='feedback-submit'
className={buttonClassNames}
onClick={sendFeedbackHandler}
>
{props.buttonText}
</button>
</div>
</div>
</div>
<div hidden={!props.feedbackSubmitted}>
<h5 className="light semi-bold text-center">
{props.feedbackSubmittedMessage}
</h5>
</div>
</div>
</div>
)
};
If I change my test to use the underlying Feedback component rather than the container it doesn't crash (but then I don't think the store will be correctly connected as mapstatetoprops isn't going to be called.
If I console.log the components in my test they both return objects from what I can see so I don't quite understand the error.
FeedbackContainer:
{ '$$typeof': Symbol(react.element),
type:
{ mapStateToProps: [Function],
mapDispatchToProps: [Function: mapDispatchToProps],
reactComponent: { [Function: WithHandlers] displayName: 'withHandlers(lifecycle(Component))' },
mockDispatch:
{ [Function: mockConstructor]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockReturnValueOnce: [Function],
mockReturnValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockRestore: [Function] } },
key: null,
ref: null,
props: {},
_owner: null,
_store: {} }
Feedback:
{ '$$typeof': Symbol(react.element),
type: [Function],
key: null,
ref: null,
props: {},
_owner: null,
_store: {} }
From some reading I think this could be down to some version compatabilites, this is what I have in my package.json:
"jest": "^21.2.1",
"@testing-library/jest-dom": "^4.1.0",
"@testing-library/react": "^9.1.4",
"react": "^16.8.6",
"react-dom": "^16.0.0",
"react-redux": "^5.0.5",
"redux": "^3.7.2",
"redux-saga": "^0.15.6",
Where am I going wrong?!
来源:https://stackoverflow.com/questions/57959972/error-when-trying-to-render-component-in-react-testing-library-got-an-object