Search code examples
reactjsjestjsreact-test-renderer

Element type is invalid - Export default and default import


I'm writing tests for my components, the components work fine in the application. Importing and consuming them works great but getting them to work with react-test-renderer has not been as great. For example, I have a social component that reads config and renders out links.

./components/Social/social.js

import React from 'react'
import PropTypes from 'prop-types'

import config from '../../../content/meta/config'

import GithubIcon from '!svg-react-loader!../../images/svg-icons/github.svg?name=GithubIcon'
import LinkedInIcon from '!svg-react-loader!../../images/svg-icons/linkedin.svg?name=LinkedInIcon'
import TwitterIcon from '!svg-react-loader!../../images/svg-icons/twitter.svg?name=TwitterIcon'
import InstagramIcon from '!svg-react-loader!../../images/svg-icons/instagram.svg?name=InstagramIcon'
import DevIcon from '!svg-react-loader!../../images/svg-icons/dev.svg?name=DevIcon'

const Social = props => {
  const { theme } = props
  const items = config.authorSocialLinks
  const icons = {
    twitter: TwitterIcon,
    github: GithubIcon,
    linkedin: LinkedInIcon,
    instagram: InstagramIcon,
    dev: DevIcon,
  }

  return (
    <React.Fragment>
      <div className="social">
        {items.map(item => {
          const Icon = icons[item.name]
          return (
            <a
              href={item.url}
              key={item.name}
              className="socialLink"
              target="_blank"
              rel="noopener noreferrer"
              title={item.name}
            >
              <Icon className="svg" />
            </a>
          )
        })}
      </div>

      {/* --- STYLES --- */}
      <style jsx global>
        {`
          @media screen and (max-width: 450px) {
            .social {
              width: 95%;
            }
          }
          @media screen and (min-width: 450px) {
            .social {
              width: 40%;
            }
          }
          .social {
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 0 auto;
            padding: 20px;

            :global(svg) {
              width: 30px;
              height: 30px;
              transition: all 0.5s;
            }

            &:hover :global(svg) {
              fill: ${theme.color.special.attention};
            }
          }

          .svg path {
            fill: ${theme.color.brand.primary};
          }

          .socialLink {
            margin: 0 auto;
            display: inline-block;
            padding: 1px;
            text-align: center;
          }
        `}
      </style>
    </React.Fragment>
  )
}

Social.propTypes = {
  theme: PropTypes.object.isRequired,
}

export default Social

./components/Social/index.js

export { default } from './Social'

In my test I'm importing the component and rendering to do snapshot testing. Test:

./components/tests/social.spec.js

import React from 'react'
import { create } from 'react-test-renderer'
import Social from '../Social'
const theme = require('../../theme/theme.json')

describe('Social Component', () => {
  it('renders correctly', () => {
    const tree = create(<Social theme={theme} />).toJSON()
    expect(tree).toMatchSnapshot()
  })
})

I am getting the error only in my test and not in the app.

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of Social.

I've tried many little tweaks to no avail.


Solution

  • When running jest your entire build system doesn't exist - in this case webpack. So imports like this '!svg-react-loader!../../images/svg-icons/github.svg?name=GithubIcon' will throw an error (or in your case maybe return undefined?).

    You need to run jest in a webpack context if you want those - https://jestjs.io/docs/en/webpack