Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React/enzyme: How to test for subcomponent?

This is how my Messenger Component looks like. As you can see there is the main component and a list component. The main component is exported as default. With this everything is working as expected in my application.

/imports/ui/components/messenger.jsx

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Container, Segment, Loader, Header } from 'semantic-ui-react'

class Messenger extends Component {
  static get propTypes () {
    return {
      data: PropTypes.array,
      articleId: PropTypes.string,
      isLoading: PropTypes.bool
    }
  }

  render () {
    const { data, articleId, isLoading } = this.props

    if (isLoading) { return (<Loader active inverted size='massive' className='animated fadeIn' />) }
    if (articleId) { return (<MessengerList data={data} articleId={articleId} />) }

    return (
      <Container>
        <Segment id='' className='m-b-1'>
          <Header as='h1'>Title</Header>
          <MessengerList data={data} />
        </Segment>
      </Container>
    )
  }
}

class MessengerList extends Component {
  /* ... */
}

export default Messenger

Now I would like to do some unit testing for the main component using enzyme. This is how I am doing it, but the last test is failing as MessengerList is not defined. So how should this be done.

import React from 'react'
import { expect } from 'meteor/practicalmeteor:chai'
import { shallow } from 'enzyme'

import { Container, Loader } from 'semantic-ui-react'
import Messenger from '/imports/ui/components/messenger.jsx'

describe('<Messenger />', () => {
  const defaultProps = {
    data: [],
    articleId: '',
    isLoading: true
  }

  it('should show <Loader /> while loading data', () => {
    const wrapper = shallow(<Messenger {...defaultProps} />);
    expect(wrapper.exists()).to.be.true
    expect(wrapper.find(Loader).length).to.equal(1)
  })
  it('should show <Container /> data has been loaded', () => {
    defaultProps.isLoading = false
    const wrapper = shallow(<Messenger {...defaultProps} />);
    expect(wrapper.find(Container).length).to.equal(1)
    expect(wrapper.find(Loader).exists()).to.be.false
  })
  it('should show <MessengerList /> if articleID is given', () => {
    defaultProps.articleID = 'dummy'
    defaultProps.isLoading = false
    const wrapper = shallow(<Messenger {...defaultProps} />);
    expect(wrapper.find(MessengerList).length).to.equal(1)
    expect(wrapper.find(Loader).exists()).to.be.false
  })
})

I do not want to change export default Messenger

like image 388
user3142695 Avatar asked Aug 09 '17 18:08

user3142695


People also ask

How do I know if a component is rendered?

Using React DevTools to highlight what components rerendered To enable it, go to "Profiler" >> click the "Cog wheel" on the right side of the top bar >> "General" tab >> Check the "Highlight updates when components render." checkbox.

How do you test a specific component in React?

There are a few ways to test React components. Broadly, they divide into two categories: Rendering component trees in a simplified test environment and asserting on their output. Running a complete app in a realistic browser environment (also known as “end-to-end” tests).


1 Answers

Export your MessengerList class ....

export class MessengerList extends Component {
  /* ... */
}

And then in the test do ....

import React from 'react'
import { expect } from 'meteor/practicalmeteor:chai'
import { shallow } from 'enzyme'

import { Container, Loader } from 'semantic-ui-react'
import Messenger, { MessengerList } from '/imports/ui/components/messenger.jsx';

describe('<Messenger />', () => {
  let wrapper;
  const defaultProps = {
    data: [],
    articleId: '',
    isLoading: true
  }

  beforeEach(() => {
    // render the component once up here in this block. It runs before each test.
    wrapper = shallow(<Messenger {...defaultProps} />);
  });

  it('should show <Loader /> while loading data', () => {
    expect(wrapper.exists()).to.be.true
    expect(wrapper.find(Loader).length).to.equal(1)
  });

  it('should show <Container /> data has been loaded', () => {
    defaultProps.isLoading = false

    expect(wrapper.find(Container).length).to.equal(1)
    expect(wrapper.find(Loader).exists()).to.be.false
  });

  it('should show <MessengerList /> if articleID is given', () => {
    defaultProps.articleID = 'dummy'
    defaultProps.isLoading = false

    expect(wrapper.find(MessengerList).length).to.equal(1);
    expect(wrapper.find(Loader).exists()).to.be.false
  });
});

UPDATE

Ideally, you should state that a prop is being modified first ...

...
describe('and the data has loaded', () => {
  beforeEach(() => {
    defaultProps.isLoading = false;
  });

  it('should show <Container /> component', () => {
    expect(wrapper.find(Container).length).to.equal(1)
    expect(wrapper.find(Loader).exists()).to.be.false
  });
});
...
like image 139
dcodesmith Avatar answered Sep 28 '22 15:09

dcodesmith