useAsyncState.test.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { renderHook } from '@testing-library/react-hooks';
  2. import { useAsyncState } from './useAsyncState';
  3. interface WaitableMock extends jest.Mock<any, any> {
  4. waitToBeCalled(): Promise<unknown>;
  5. }
  6. function createWaitableMock() {
  7. let resolve: Function;
  8. const mock = jest.fn() as WaitableMock;
  9. mock.mockImplementation(() => {
  10. resolve && resolve();
  11. });
  12. mock.waitToBeCalled = () => {
  13. return new Promise((_resolve) => (resolve = _resolve));
  14. };
  15. return mock;
  16. }
  17. describe('useAsyncState', () => {
  18. const MOCKED_RANDOM_VALUE = 0.42069;
  19. beforeEach(() => {
  20. jest.spyOn(global.Math, 'random').mockReturnValue(MOCKED_RANDOM_VALUE);
  21. });
  22. afterEach(() => {
  23. jest.spyOn(global.Math, 'random').mockRestore();
  24. });
  25. it('should return data from an async function', async () => {
  26. const apiCall = () => Promise.resolve(['a', 'b', 'c']);
  27. const setError = jest.fn();
  28. const { result, waitForNextUpdate } = renderHook(() => useAsyncState(apiCall, setError, []));
  29. await waitForNextUpdate();
  30. expect(result.current).toEqual(['a', 'b', 'c']);
  31. });
  32. it('should report errors through setError', async () => {
  33. const error = new Error();
  34. const apiCall = () => Promise.reject(error);
  35. const setError = createWaitableMock();
  36. const { result, waitForNextUpdate } = renderHook(() => useAsyncState(apiCall, setError, []));
  37. await Promise.race([waitForNextUpdate(), setError.waitToBeCalled()]);
  38. expect(result.current).toEqual([]);
  39. expect(setError).toHaveBeenCalledWith(MOCKED_RANDOM_VALUE, error);
  40. });
  41. it('should clear the error once the request is successful', async () => {
  42. const apiCall = () => Promise.resolve(['a', 'b', 'c']);
  43. const setError = createWaitableMock();
  44. const { waitForNextUpdate } = renderHook(() => useAsyncState(apiCall, setError, []));
  45. await Promise.race([waitForNextUpdate(), setError.waitToBeCalled()]);
  46. expect(setError).toHaveBeenCalledWith(MOCKED_RANDOM_VALUE, undefined);
  47. });
  48. });