learner
learner

Reputation: 33

How to get all the child elements inside a component in unit test using react and enzyme?

During unit testing, I am getting error: TeamMemberList › should show an empty section if the team has no members.

expect(received).toBe(expected) // Object.is equality

Expected: 1
Received: 0

But the element is present in the component. Is there any way to get the structure of the component and see all the element present in it?

My component code (TeamMembersList.js) :

import React, { useState } from 'react'
import { withRouter } from 'react-router-dom'
import styled from 'styled-components'
import Card from '../../components/common/Card'
import { tiffanyBlueColor } from '../../styles'
import TeamMemberListItem from './TeamMemberListItem'
import Button from '../../components/common/Button'
import { AddMemberListItem } from './AddMemberListItem'
import { addUserToTeam } from '../create-team/EnterpriseCreateTeamActions'
import i18n from '../../i18n/i18n'
import EmptySection from '../../components/common/EmptySection'
import { FaUserSlash, FaInfoCircle } from 'react-icons/fa'
import { parsePhoneNumberFromString } from 'libphonenumber-js'

function TeamMembersList(props) {
  const [isAddingMember, setIsAddingMember] = useState(false)
  const [loadingAddingMember, setLoadingAddingMember] = useState(false)
  const [addMemberError, setAddMemberError] = useState('')
  const { team, loading } = props
  let users = []
  let teamId = ''
  if (team && team.users) {
    users = Object.keys(team.users)
  }
  if (team && team.id) {
    teamId = team.id
  }
  const onPressAddMember = () => {
    setIsAddingMember(true)
  }

  const onPressSave = async ({ phoneNumber, name }) => {
    setAddMemberError('')
    setLoadingAddingMember(true)
    try {
      const parsedNumber = parsePhoneNumberFromString(phoneNumber, 'NL')
      const response = await addUserToTeam({
        teamId,
        phoneNumber: parsedNumber.number,
        name
      })

      if (response.statusCode === 200) {
        setIsAddingMember(false)
      } else {
        if (response.code === 'already-exists') {
          const {
            currentTeam: { name: teamName }
          } = response.details
          setAddMemberError(
            i18n.t('enterprise.teamMember.UserAlreadyInTeam', { teamName })
          )
        } else {
          setAddMemberError(i18n.t('enterprise.teamMember.CouldNotAddUser'))
        }
      }
    } catch (error) {
      setAddMemberError(i18n.t('enterprise.teamMember.CouldNotAddUser'))
    } finally {
      setLoadingAddingMember(false)
    }
  }

  const onPressCancel = () => {
    setIsAddingMember(false)
    setLoadingAddingMember(false)
    setAddMemberError('')
  }
  const renderTooltip = () => {
    return (
      <div>
        <FaInfoCircle
          data-tip={i18n.t('enterprise.teamMember.TooltipInfo')}
          size={20}
          color={tiffanyBlueColor}
        />
      </div>
    )
  }
  return (
    <Card
      title={i18n.t('enterprise.teamMember.TeamMembers')}
      containerStyle={{ minWidth: '1024px' }}
      renderHeaderRight={renderTooltip}
      isLoading={loading}
    >
      <UsersContentContainer>
        {users.length === 0 ? (
          <EmptySection
            text={i18n.t('enterprise.teamMember.NoTeamMembersYet')}
            Icon={FaUserSlash}
          />
        ) : null}
        {users.map(userId => (
          <TeamMemberListItem userId={userId} key={userId} />
        ))}

        {isAddingMember ? (
          <AddMemberListItem
            onPressCancel={onPressCancel}
            onPressSave={onPressSave}
            isLoading={loadingAddingMember}
            error={addMemberError}
          />
        ) : (
          <AddMemberButtonContainer>
            <Button
              testId="button-add-member"
              buttonText={i18n.t('enterprise.teamMember.AddMember')}
              onPress={onPressAddMember}
            />
          </AddMemberButtonContainer>
        )}
      </UsersContentContainer>
    </Card>
  )
}
export default withRouter(TeamMembersList)

const UsersContentContainer = styled.div`
  flex-grow: 1;
  display: flex;
  justify-content: center;
  flex-direction: column;
`

const AddMemberButtonContainer = styled.div`
  margin-top: 0.5rem;
  width: 150px;
  align-self: flex-end;
`

My component test code (TeamMembersList.test.js) :

 import React from 'react'
 import { BrowserRouter as Router } from 'react-router-dom'
 import { shallow } from 'enzyme'
 import { EmptySection } from '../../../components/common'
 import TeamMembersList from '../TeamMembersList'
 import TeamMemberListItem from '../TeamMemberListItem'

 describe('TeamMemberList', () => {
   beforeEach(() => {
      expect.hasAssertions()
      jest.clearAllMocks()
   })
   it('should show an empty section if the team has no members.', () => {
      const team = {
      name: 'Test team',
      phoneNumber: '+31851234567',
      status: 'active',
      users: {}
      }
      const loading = false
      const wrapper = shallow(
      <Router>
        <TeamMembersList team={team} loading={loading} />
      </Router>
      )

      expect(wrapper.find(EmptySection).length).toBe(1)
   })
 })

Upvotes: 0

Views: 1439

Answers (2)

Mahdiyeh
Mahdiyeh

Reputation: 1184

import {mount} from 'enzyme';
const testComponent =  mount(<TestComponent/>)

If you use shallow, it renders each component inside the TestComponent as it is, but with mount you can get all child elements inside the TestComponent.

Upvotes: 0

H S W
H S W

Reputation: 7129

You can use console.log(wrapper.debug()) to print an HTML-like string of the wrapper for debugging purposes. It is useful to print out to the console when tests are not passing when you expect them to.

In my case I was using export default withRouter(MyChildComponent) and it was not required to use withRouter in MyChildComponent. Removing the withRouter and Router from the MyChildComponent and MyChildComponent.test worked for me.

Upvotes: 1

Related Questions