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?

Lin Du
  • 88,126
  • 95
  • 281
  • 483
MK6
  • 67
  • 1
  • 2
  • 7
  • 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

Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • 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` – Lin Du 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