Тестирование отложенного кастома React с Jest / Enzyme? - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь протестировать пользовательский хук, который использует useState и useEffect вместе с setTimeout, который имитирует задержку загрузки некоторых данных. Упрощенный

const useCustomHook = (id: number) => {
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(false);
  const [value, setValue] = React.useState<string>();

  React.useEffect(() => {
    const dummy = ["foo", "bar", "baz"];
    // simulate remote call with delay
    setTimeout(() => {
      id < 3 ? setValue(dummy[id]) : setError(true);
      setLoading(false);
    }, 1500);
  }, [id]);

  return [loading, error, value];
};

const App = () => {
  const [loading, error, value] = useCustomHook(1);

  if (loading) { return <div>Loading...</div>; }
  if (error) { return <div>Error</div>; }
  return <h1>{value}</h1>;
};

https://codesandbox.io/s/react-typescript-z1z2b

Как бы вы протестировали все возможные состояния (загрузка, ошибка и значение) этого хука с помощью Jest и Enzyme?

Заранее спасибо !!!

1 Ответ

0 голосов
/ 05 марта 2020

Полагаю, вам действительно нужно отправить запрос API внутри хуков useEffect. (извините, если я неправильно понял вашу цель)

Если это так, я проверю

  • Запрос API отправлен
  • Сначала показать загрузку
  • Показать ошибку при неудачном запросе API
  • Показать результат при успешном выполнении запроса API

Тест должен выглядеть следующим образом.

describe('App', () => {
  beforeEach(() => {
    fetch.resetMocks();
  });

  it('should fetch the request', async () => {
    await act(async () => {
      await mount(<App />)
    })

    expect(fetch).toBeCalledWith('https://dog.ceo/api/breeds/image/random');
  });

  it('should show loading at first', () => {
    // mock useEffect to test the status before the API request
    jest
      .spyOn(React, 'useEffect')
      .mockImplementationOnce(() => {}); 

    const comp = mount(<App />)

    expect(comp.text()).toBe('Loading...');
  });

  it('should display error if api request fail', async () => {
    fetch.mockRejectOnce();
    let comp;

    await act(async () => {
      comp = await mount(<App />);
    })
    comp.update();

    expect(comp.text()).toBe('Error');
  });

  it('should display result if api request success', async () => {
    fetch.mockResponseOnce(JSON.stringify({
      message: "https://images.dog.ceo/breeds/mastiff-tibetan/n02108551_1287.jpg",
      status: "success"
    }));
    let comp;

    await act(async () => {
      comp = await mount(<App />);
    })
    comp.update();


    expect(comp.find('img')).toHaveLength(1);
    expect(comp.find('img').prop('src'))
      .toBe('https://images.dog.ceo/breeds/mastiff-tibetan/n02108551_1287.jpg');
  });
});

Вот репозиторий для справки: https://github.com/oahehc/stackoverflow-answers/tree/60514934/src

Кроме того, вы передаете id в useCustomHook, я думаю, это будет использоваться в качестве параметра в запросе API. Поэтому вы можете добавить дополнительные тестовые примеры для проверки этой части.

...