Search code examples
reactjsunit-testingjestjsenzymetesting-library

Writing tests for React JS


I've just started to study about tests and i'm trying to test a component that has a initial state = false. On click, it should change to !state and if it's true, render a Child Component. I'm trying to write, at least, a test to check if it changes the state on click through some exemples that I've found. I'm using Jest, Testing Library/React and Jest.

index.test.js

/* eslint-disable no-return-assign */
import { render, screen, fireEvent } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { shallow } from 'enzyme';
import PropTypesExemple from './index';
import ChildComponent from './ChildComponent';

describe('Testing the rendering of components', () => {
  let wrapper;
  beforeEach(() => {
    wrapper = shallow(<PropTypesExemple state={false} />);
  });
  test('should render component prop types exemple', () => {
    render(
      <MemoryRouter>
        <PropTypesExemple />
      </MemoryRouter>,
    );
    fireEvent(
      screen.getByText('Me Aperte!!!'),
      new MouseEvent('click'),
    );
  });

  test('should render child component', () => {
    render(
      <ChildComponent />,
    );
  });
  it('sould render child component on click', () => {
    wrapper.setProps({ state: false });
    wrapper.find('button').simulate('click');
    expect(wrapper.state('state').toEqual(true));
  });
});

Parent Component

import React, { useState } from 'react';
import './index.scss';
import PageDefault from '../../components/PageDefault';
import ChildComponent from './ChildComponent';

function PropTypesExemple() {
  const [state, setState] = useState(false);
  const [text, setText] = useState();
  const handleClick = () => {
    setState((prev) => !prev);
  };
  return (
    <PageDefault>
      <div className="prop-types-container">
        <h1>Olá, Mundo!</h1>
        <input
          value={text}
          onChange={(event) => setText(event.target.value)}
        />
        <button type="button" onClick={handleClick}>Me Aperte!!!</button>
        {state && (<ChildComponent nome={!text ? undefined : text} />)}
      </div>
    </PageDefault>
  );
}

export default PropTypesExemple;

Child Component

/* eslint-disable react/destructuring-assignment */
/* eslint-disable arrow-body-style */
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';

const ChildComponent = (props) => {
  useEffect(() => {
    document.title = props.nome;
    return () => { };
  }, [props.nome]);

  useEffect(() => {
    const intervalId = setInterval(() => { }, 1000);
    return () => {
      clearInterval(intervalId);
    };
  }, []);

  return (
    <div>
      Olá,
      {props.nome}
      !
    </div>
  );
};

ChildComponent.defaultProps = {
  nome: 'React App2',
};

ChildComponent.propTypes = {
  nome: PropTypes.string,
};

export default ChildComponent;

I'm running into the following errors

src/pages/PropTypes/index.test.js
  ● Testing the rendering of components › should render component prop types exemple


          Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
          To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
          before using any of Enzyme's top level APIs, where `Adapter` is the adapter
          corresponding to the library currently being tested. For example:

          import Adapter from 'enzyme-adapter-react-15';

          To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html

       9 |   let wrapper;
      10 |   beforeEach(() => {
    > 11 |     wrapper = shallow(<PropTypesExemple state={false} />);
         |               ^
      12 |   });
      13 |   test('should render component prop types exemple', () => {
      14 |     render(

          
      at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
      at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
      at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
      at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
      at shallow (node_modules/enzyme/src/shallow.js:10:10)
      at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)

  ● Testing the rendering of components › should render child component


          Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
          To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
          before using any of Enzyme's top level APIs, where `Adapter` is the adapter
          corresponding to the library currently being tested. For example:

          import Adapter from 'enzyme-adapter-react-15';

          To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html

       9 |   let wrapper;
      10 |   beforeEach(() => {
    > 11 |     wrapper = shallow(<PropTypesExemple state={false} />);
         |               ^
      12 |   });
      13 |   test('should render component prop types exemple', () => {
      14 |     render(

          
      at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
      at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
      at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
      at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
      at shallow (node_modules/enzyme/src/shallow.js:10:10)
      at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)

  ● Testing the rendering of components › sould render child component on click


          Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
          To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
          before using any of Enzyme's top level APIs, where `Adapter` is the adapter
          corresponding to the library currently being tested. For example:

          import Adapter from 'enzyme-adapter-react-15';

          To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html

       9 |   let wrapper;
      10 |   beforeEach(() => {
    > 11 |     wrapper = shallow(<PropTypesExemple state={false} />);
         |               ^
      12 |   });
      13 |   test('should render component prop types exemple', () => {
      14 |     render(

          
      at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
      at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
      at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
      at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
      at shallow (node_modules/enzyme/src/shallow.js:10:10)
      at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)

Test Suites: 1 failed, 7 passed, 8 total
Tests:       3 failed, 7 passed, 10 total
Snapshots:   0 total
Time:        2.118 s
Ran all test suites related to changed files.

Solution

  • As Alexander Staroselsky said, the documentation doesn't mention it, but there's a non official Adapter for React 17.0.x. You can find it here: @wojtekmaj/enzyme-adapter-react-17

    And configure it this way:

    import Enzyme from 'enzyme';
    import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
    
    Enzyme.configure({ adapter: new Adapter() });