Daniel
Daniel

Reputation: 3272

Importing components from a module works in the browser, but breaks in tests

I'm currently writing tests for my Song component. The code works as expected in the browser, however, it's breaking in my tests.

Although I've figured out what the issue is and a bad workaround, I don't understand exactly what the problem is and why my solution works.

The rundown

The Song component imports AlbumArtContainer and AvatarContainer:

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

import './_styles/Song.scss'
import { ListGroupItemLink } from 'Desktop/components/common'
import { Action, ActionList } from 'Desktop/components/common/actions'
import {
  AlbumArtContainer,
  ArtistContainer } from 'Desktop/containers/common/music'

export default class Song extends React.Component {
  // ... redacted code
}

I have a SongContainer component inside the same directory as AlbumArtContainer and AvatarContainer:

import { connect } from 'react-redux'

import { songs } from 'Common/api'
import { Song } from 'Desktop/components/common/music'

const mapStateToProps = (state, { id }) => {
  // ... redacted code
}

const SongContainer = connect(mapStateToProps)(Song)

export default SongContainer

Inside that directory, I have an index.js file to export everything:

export AlbumArtContainer from './AlbumArtContainer'
export ArtistContainer from './ArtistContainer'
export SongContainer from './SongContainer'

Song.test.jsx imports Song:

import Action from 'Desktop/components/common/actions/Action'
import Song from 'Desktop/components/common/music/Song'

describe("<Song>", () => {
  // ... redacted tests
})

Running the test for this file throws the following error:

-> % npm run test client/src/Desktop/components/common/music/__tests__/Song.test.jsx

> @ test /home/mightyspaj/Dev/Projects/vibite/client
> jest "client/src/Desktop/components/common/music/__tests__/Song.test.jsx"

 FAIL  src/Desktop/components/common/music/__tests__/Song.test.jsx
  ● Test suite failed to run

    Invariant Violation: You must pass a component to the function returned by connect. Instead received undefined

      at invariant (node_modules/invariant/invariant.js:42:15)
      at wrapWithConnect (node_modules/react-redux/lib/components/connectAdvanced.js:101:29)
      at Object.<anonymous> (src/Desktop/containers/common/music/SongContainer.jsx:19:62)
      at Object.<anonymous> (src/Desktop/containers/common/music/index.js:1:521)
      at Object.<anonymous> (src/Desktop/components/common/music/Song.jsx:8:14)
      at Object.<anonymous> (src/Desktop/components/common/music/__tests__/Song.test.jsx:2:13)
      at next (native)
      at next (native)
at process._tickCallback (internal/process/next_tick.js:109:7)

This is because it's reading SongContainer, and Song is being imported as undefined inside SongContainer. This means that connect() throws an error when Song is passed to it because it expects a component.

But if I import AlbumArtContainer and AvatarContainer inside SongContainer directly from their files instead of their module:

import AlbumArtContainer from 'Desktop/containers/common/music/AlbumArtContainer'
import ArtistContainer from 'Desktop/containers/common/music/ArtistContainer'

Then Song imports correctly inside SongContainer and it works just fine. I'm not sure why this is, or why it works fine in the browser but not my tests, so what exactly is the issue here?

I also don't want to import components directly from their file (which is why I import them from their module), so my current solution is only a workaround.

Upvotes: 0

Views: 521

Answers (1)

Daniel
Daniel

Reputation: 3272

From further investigation I realised the issue was due to circular dependencies.

Although it wasn't the solution I'd initially wanted, I've removed the index.js files, and have also changed my imports to import components directly from their files using default imports.

This has prevented circular dependencies.

Upvotes: 0

Related Questions