Error when trying to render component in react-testing-library - got an object

空扰寡人 提交于 2019-12-24 07:38:04

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!