use-async-resource
Version:
A custom React hook for simple data fetching with React Suspense
70 lines (54 loc) • 2.4 kB
text/typescript
import { act, renderHook } from '@testing-library/react-hooks';
import { updateCache } from './updateCache';
import { useAsyncResource } from './useAsyncResource';
import { resourceCache } from './cache';
import { suspendFor } from './test.helpers';
describe('updateCache', () => {
const apiFn = (id: number) =>
id < 10
? Promise.resolve({ id, name: 'test name' })
: Promise.reject({ message: 'error' });
afterEach(() => {
resourceCache(apiFn).clear();
});
it('should transition a data reader without throwing in between', async () => {
// get the data reader from the custom hook, with params
const { result } = renderHook(() => useAsyncResource(apiFn, 1));
const [dataReader, updateDataReader] = result.current;
// wait for it to fulfill
await suspendFor(dataReader);
// should be able to get raw data from the data reader
expect(dataReader()).toStrictEqual({ id: 1, name: 'test name' });
// update the data reader with a transition
const updater = updateCache(apiFn, 2)
.then(() => {
act(() => updateDataReader(2));
});
// while update is in progress, data reader should remain the same
const [prevDataReader] = result.current;
expect(prevDataReader).toStrictEqual(dataReader);
// wait for the update to happen
await updater;
// the new data reader should be available immediately
const [newDataReader] = result.current;
expect(newDataReader).not.toStrictEqual(prevDataReader);
expect(newDataReader()).toStrictEqual({ id: 2, name: 'test name' });
});
it('should throw a failure if update was not successful', async () => {
// get the data reader from the custom hook, with params
const { result } = renderHook(() => useAsyncResource(apiFn, 1));
const [dataReader, updateDataReader] = result.current;
// wait for it to fulfill
await suspendFor(dataReader);
// should be able to get raw data from the data reader
expect(dataReader()).toStrictEqual({ id: 1, name: 'test name' });
// update the data reader with a transition, but expect a failure to happen
await updateCache(apiFn, 10)
.then(() => {
act(() => updateDataReader(10));
});
// verify that the new data reader fails with an error
const [newDataReader] = result.current;
expect(newDataReader).toThrowError(Error('error'));
});
});