0

I'm new to Jest and I'm writing test case for the below function,

useEffect(() => {
    fetch("http://ip-api.com/json")
      .then(res => res.json())
      .then(data => {
        cntCode = `country_code=${data.countryCode}`;
        country = `country=${data.country}`;
      });
  });

I tried few ways to cover using but I'm not able to figure out how to cover this function. Can someone help me in writing the testcase for this please?

slideshowp2
  • 63,310
  • 57
  • 191
  • 365
MK6
  • 57
  • 1
  • 2
  • 6
  • Can you check this one https://medium.com/@AndreCalvo/testing-custom-react-hooks-that-use-fetch-or-other-async-functions-5fb128d07f53. – Learner Dec 17 '19 at 06:44

1 Answers1

0

Here is the unit test solution:

index.tsx:

import React, { useEffect, useState } from 'react';

export const MyComponent = () => {
  const [cntCode, setCntCode] = useState('');
  const [country, setCountry] = useState('');

  useEffect(() => {
    fetch('http://ip-api.com/json')
      .then((res) => res.json())
      .then((data) => {
        setCntCode(data.countryCode);
        setCountry(data.country);
      });
  }, [cntCode, country]);

  return (
    <div>
      country: {country}, cntCode: {cntCode}
    </div>
  );
};

index.test.ts:

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

describe('MyComponent', () => {
  afterEach(() => {
    jest.resetAllMocks();
  });
  it('should pass', async () => {
    const mResponse = jest.fn().mockResolvedValue({ countryCode: 123, country: 'US' });
    (global as any).fetch = jest.fn(() => {
      return Promise.resolve({ json: mResponse });
    });
    const wrapper = mount(<MyComponent></MyComponent>);
    expect(wrapper.exists()).toBeTruthy();
    expect(wrapper.text()).toBe('country: , cntCode: ');
    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });
    expect(wrapper.text()).toBe('country: US, cntCode: 123');
    expect((global as any).fetch).toBeCalledWith('http://ip-api.com/json');
  });
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/59368499/index.test.tsx (9.629s)
  MyComponent
    ✓ should pass (73ms)

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

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59368499

slideshowp2
  • 63,310
  • 57
  • 191
  • 365
  • greate answer! but if I am using javascript, what should I do with 'global as any'? – jjzjx118_2 Oct 30 '20 at 07:56
  • @jjzjx118_2 Just remove `as any` – slideshowp2 Oct 30 '20 at 08:08
  • thanks, it works. I have a similar question about this :https://stackoverflow.com/questions/64604039/jest-not-covered-the-function-inside-useeffect. I don't know why it's not 100% covered.can you take a look at it? – jjzjx118_2 Oct 30 '20 at 08:14