Erland Nafid
Erland Nafid

Reputation: 53

How to test react functional component correctly using jest and enzyme?

my-component.js

import axios from "axios";
import React from "react";

const UnitTest = () => {
  const [todo, set_todo] = React.useState({});

  React.useState(() => {
    const onMounted = async () => {
      const getTodo = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
      set_todo(getTodo.data);
    };
    onMounted();
  }, []);

  return (
    <div id="UnitTest">
      <p>{todo.title}</p>
    </div>
  );
};

export default UnitTest;

api response

{
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
}

my-component.test.js

import { mount } from "enzyme";

import UnitTest from "../../src/pages/unit-test";

describe("UnitTest component", () => {
  let wrapper = mount(<UnitTest />);

  it("should render the component", () => {
    wrapper = mount(<UnitTest />);
    console.log(wrapper.debug());
    expect(wrapper.find("p").text()).toEqual("delectus aut autem");
  });
});

test result

enter image description here

How to make my <p> tag contain delectus aut autem when console.log(wrapper.debug()) and is it possible if i want to update the state (set_todo) to be

{
    "userId": 2,
    "id": 3,
    "title": "second title",
    "completed": true
}

from my test file and update the assertion become expect(wrapper.find("p").text()).toEqual("second titile"); ?

Upvotes: 2

Views: 4076

Answers (1)

Lin Du
Lin Du

Reputation: 102207

Use jest.spyOn(object, methodName) method create mock for axios.get() method and its resolved value.

Use act() with promise and setTimeout to create macro task to wait the promise of axios.get() method created to be resolved in useEffect hook.

E.g.

MyComponent.jsx:

import axios from 'axios';
import React from 'react';

const UnitTest = () => {
  const [todo, set_todo] = React.useState({});

  React.useEffect(() => {
    const onMounted = async () => {
      const getTodo = await axios.get('https://jsonplaceholder.typicode.com/todos/1');
      set_todo(getTodo.data);
    };
    onMounted();
  }, []);

  return (
    <div id="UnitTest">
      <p>{todo.title}</p>
    </div>
  );
};

export default UnitTest;

MyComponent.test.jsx:

import UnitTest from './MyComponent';
import axios from 'axios';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';

const whenStable = async () => {
  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0));
  });
};

describe('67885144', () => {
  it('should pass', async () => {
    const axiosGetSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({ data: { title: 'delectus aut autem' } });
    const wrapper = mount(<UnitTest />);
    await whenStable();

    expect(wrapper.find('p').text()).toEqual('delectus aut autem');
    expect(axiosGetSpy).toBeCalledWith('https://jsonplaceholder.typicode.com/todos/1');
    axiosGetSpy.mockRestore();
  });
});

test result:

 PASS  examples/67885144/MyComponent.test.jsx (7.902 s)
  67885144
    ✓ should pass (45 ms)

-----------------|---------|----------|---------|---------|-------------------
File             | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------------|---------|----------|---------|---------|-------------------
All files        |     100 |      100 |     100 |     100 |                   
 MyComponent.jsx |     100 |      100 |     100 |     100 |                   
-----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.499 s

Upvotes: 1

Related Questions