0
votes

I am pretty new to the React world. Here's what I have in react-hooks.

export default function MyComponent() {
 const [data, setData] = useState(null);

 useEffect( () => {
   getData().then(setData)
 }, []);

 return(
   data ? <AnotherComponent /> : <LoadingComponent />
 );
}

getData() is in another component with 'fetch'.

export function getData() {
  return fetch('/api/v2/user').then(response => {
    if(response.status === 200) {
      return response.json()
    } else {
      return {};
    }
  });
}

I am using Jest/Enzyme as a testing framework and want to test the scenario with mock data so I can test LoadingComponent is not present in DOM. This is what I am trying but it seems mock values are not being returned.

const mockValues = {
 data: {}
 count: 10
 result: []
};

jest.mock('../DataService');

const mockService = require('../DataService');
mockService.getData = jest.fn().mockResolvedValue(mockValues);

...
const component = mount(<MyComponent />);
expect(component.html()).toEqual(expect.not.stringContaining('LoadingComponent')); 

I see the "mount" works fine but it seems mock values are not being returned and hence LoadingComponent is present.

1

1 Answers

0
votes

Here is the unit test solution:

index.tsx:

import React, { useState, useEffect } from 'react';
import { AnotherComponent } from './AnotherComponent';
import { LoadingComponent } from './LoadingComponent';
import { getData } from './dataService';

export default function MyComponent() {
  const [data, setData] = useState(null);
  useEffect(() => {
    getData().then(setData);
  }, []);
  return data ? <AnotherComponent /> : <LoadingComponent />;
}

AnotherComponent.jsx:

export const AnotherComponent = () => <div>AnotherComponent</div>;

LoadingComponent.jsx:

export const LoadingComponent = () => <div>LoadingComponent</div>;

dataService.js:

export function getData() {
  return fetch('/api/v2/user').then((response) => {
    if (response.status === 200) {
      return response.json();
    } else {
      return {};
    }
  });
}

index.test.jsx:

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

jest.mock('./dataService');

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

describe('60913717', () => {
  it('should pass', async () => {
    const mockValues = {
      data: {},
      count: 10,
      result: [],
    };
    DataService.getData = jest.fn().mockResolvedValueOnce(mockValues);
    const wrapper = mount(<MyComponent></MyComponent>);
    expect(wrapper.find('LoadingComponent')).toBeTruthy();
    await whenStable();
    expect(wrapper.find('AnotherComponent')).toBeTruthy();
  });
});

unit test results with coverage report:

 PASS  stackoverflow/60913717/index.test.jsx (28.041s)
  60913717
    ✓ should pass (48ms)

----------------------|---------|----------|---------|---------|-------------------
File                  | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------------|---------|----------|---------|---------|-------------------
All files             |      80 |       50 |   66.67 |      75 |                   
 AnotherComponent.jsx |     100 |      100 |     100 |     100 |                   
 LoadingComponent.jsx |     100 |      100 |     100 |     100 |                   
 dataService.js       |      20 |        0 |       0 |      20 | 2-4,6             
 index.jsx            |     100 |      100 |     100 |     100 |                   
----------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        29.721s

source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60913717