getting TypeError: expect(...).toBeInTheDocument is not a function

Viewed 1838

I am trying to do unit testing with my sidebar component, to check if the text rendered is in the document flow or not, well it is in the document flow but the test case gets failed saying "TypeError: expect(...).toBeInTheDocument is not a function". I don't know why it is so, I also imported the jest library in the file still getting same error, please help me.

sidebar.spec.js file

import React from 'react';
import { shallow } from 'enzyme';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import configureStore from 'redux-mock-store';
import toJson from 'enzyme-to-json';
import { Provider } from 'react-redux';

import Sidebar from './sidebar';

describe('Testing Sidebar component', () => {
    let wrapper, store;
    const mockStore = configureStore();
    const initialProp = {
        auth: {
            userAuth: {
                firstName: "savitha",
                lastName: "goel"
            }
        },
        meta: {
            productsMeta: [
                { label: "CX Admin Application" },
                { label: "Application Configuration Management" }
            ]
        }
    };

    beforeEach(() => {
        store = mockStore(initialProp);
        wrapper = shallow(<Sidebar store={store} />);
    });

    it('should be defined', () => {
        expect(wrapper).toBeDefined();
    });

    it('renders correctly', () => {
        expect(toJson(wrapper)).toMatchSnapshot();
    });

    it('render sidebar options as a text', () => {
        store = mockStore(initialProp);
        wrapper = shallow(
            <Provider store={store}>
                <Sidebar />
            </Provider>
        );

        console.log(store);

        console.log(screen.debug(null, Infinity))
        // const sidebarElement = screen.getByText('Application Manager');
        // expect(sidebarElement).toBeInTheDocument();
    });
});

my sidebar.js file

import React, { Component } from 'react'
import { connect } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faAngleDown, faWrench, faUserCircle, faHome, faDigitalTachograph, faMicrophone, faRecordVinyl } from '@fortawesome/free-solid-svg-icons';
import './_sidebar.scss';

class Sidebar extends Component {
    handleProductSelection(product) {
        this.props.props.history.push(product.path);
    }

    renderProducts = () => {
    if(this.props.products) {
      return this.props.products.map((product) => {
        return (<li onClick={() => this.handleProductSelection(product)}>{product.label}</li>);
      });
    }
    }

    render() {
        return(
      <div className="sidebar">
        <div className="profileWrap">
          <div>
            <div className="userNameWrap">
              <FontAwesomeIcon icon={faUserCircle} />
              <span className="userName">{this.props.firstName} {this.props.lastName}</span>
              <span className="angleIcon"><FontAwesomeIcon icon={faAngleDown} /></span>
            </div>
            <div className="userInfoWrap">
              <ul>
                <li>My profile</li>
                <li>Help with Console</li>
                <li>Contact us</li>
                <li>Log out</li>
              </ul>
            </div>
            <div className="divisionWrap">
              Division:
            </div>
          </div>
        </div>
        <div className="sidebarNavigation">
          <ul>
            <li>
              <div className="mainMenu">
                <FontAwesomeIcon icon={faHome} />
                <span className="menuName">Home</span>
              </div>
            </li>
            <li>
              <div className="mainMenu">
                <FontAwesomeIcon icon={faDigitalTachograph} />
                <span className="menuName">Mosaic Insights</span>
                <span className="angleIcon"><FontAwesomeIcon icon={faAngleDown} /></span>
              </div>
              <div className="subMenu">
                <ul>
                  {this.renderProducts()}
                </ul>
              </div>
            </li>
            <li>
              <div className="mainMenu">
                <FontAwesomeIcon icon={faWrench} />
                <span className="menuName">Application Manager</span>
                <span className="angleIcon"><FontAwesomeIcon icon={faAngleDown} /></span>
              </div>
              <div className="subMenu">
                <ul>
                  {this.renderProducts()}
                </ul>
              </div>
            </li>
            <li>
              <div className="mainMenu">
                <FontAwesomeIcon icon={faMicrophone} />
                <span className="menuName">Call Recording</span>
                <span className="angleIcon"><FontAwesomeIcon icon={faAngleDown} /></span>
              </div>
              <div className="subMenu">
                <ul>
                  {this.renderProducts()}
                </ul>
              </div>
            </li>
            <li>
              <div className="mainMenu">
                <FontAwesomeIcon icon={faWrench} />
                <span className="menuName">Console Administration</span>
                <span className="angleIcon"><FontAwesomeIcon icon={faAngleDown} /></span>
              </div>
              <div className="subMenu">
                <ul>
                  {this.renderProducts()}
                </ul>
              </div>
            </li>
          </ul>
        </div>
      </div>
    );
    }
}


const mapStateToProps = (state) => {
  return{
    firstName: state.auth.userAuth.firstName,
    lastName: state.auth.userAuth.lastName,
    products: state.meta.productsMeta
  };
};

export default connect(mapStateToProps)(Sidebar);

1 Answers

You need to wrap your SideBar with the Provider from react-redux . Because your SideBar is a connected Component .

import {Provider} from 'react-redux';

 <Provider store={store}>
     <Sidebar />
 </Provider>

Also testing library gives many different utils to check whether the Component is rendered correctly . One such helpful util is screen.debug .

it('render sidebar options as a text', () => {   
        render( <Provider store={store}>
                 <Sidebar />
               </Provider>
         );

        console.log(screen.debug(null, Infinity)) 
    });

Now this will log the entire DOM in the console in your terminal .

You are using both the enzyme and react testing library . So you need to wrap your Sidebar with the Provider in 2 places.

describe('Testing Sidebar component', () => {
  let wrapper, store;
  const mockStore = configureStore();
  const initialProp = {
    auth: {
      userAuth: {
        firstName: 'savitha',
        lastName: 'goel',
      },
    },
    meta: {
      productsMeta: [
        {label: 'CX Admin Application'},
        {label: 'Application Configuration Management'},
      ],
    },
  };

  beforeEach(() => {
    store = mockStore(initialProp);
    wrapper = shallow(
      // wrap it here .
      <Provider store={store}>
        <Sidebar />
      </Provider>
    );
  });

  it('should be defined', () => {
    expect(wrapper).toBeDefined();
  });

  it('renders correctly', () => {
    expect(toJson(wrapper)).toMatchSnapshot();
  });

  it('render sidebar options as a text', () => {
    store = mockStore(initialProp);
    render(
      // wrap it here as well .
      <Provider store={store}>
        <Sidebar />
      </Provider>
    );

    console.log(store);
    // screen is an API provided by testing library . You cannot use it with `shallow` from enzyme . So you need to use `render` instead of `shallow` for this IT block 
    console.log(screen.debug(null, Infinity));
    // const sidebarElement = screen.getByText('Application Manager');
    // expect(sidebarElement).toBeInTheDocument();
  });
});
Related