fix useRequest error bug

This commit is contained in:
Keith Grant 2020-03-12 17:08:21 -07:00
parent eea80c45d1
commit ac9f526cf0
3 changed files with 174 additions and 89 deletions

View File

@ -34,7 +34,7 @@ export function getQSConfig(
*/
export function parseQueryString(config, queryString) {
if (!queryString) {
return config.defaultParams;
return config.defaultParams || {};
}
const params = stringToObject(config, queryString);
return addDefaultsToObject(config, params);

View File

@ -70,8 +70,10 @@ export function useDismissableError(error) {
}, [error]);
return {
error: showError && error,
dismissError: () => setShowError(false),
error: showError ? error : null,
dismissError: () => {
setShowError(false);
},
};
}
@ -81,7 +83,10 @@ export function useDeleteItems(
) {
const location = useLocation();
const history = useHistory();
const { requestError, isLoading, request } = useRequest(makeRequest, null);
const { error: requestError, isLoading, request } = useRequest(
makeRequest,
null
);
const { error, dismissError } = useDismissableError(requestError);
const deleteItems = async () => {

View File

@ -1,7 +1,8 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';
import useRequest from './useRequest';
import { mountWithContexts } from '@testUtils/enzymeHelpers';
import useRequest, { useDeleteItems } from './useRequest';
function TestInner() {
return <div />;
@ -10,100 +11,179 @@ function Test({ makeRequest, initialValue = {} }) {
const request = useRequest(makeRequest, initialValue);
return <TestInner {...request} />;
}
function DeleteTest({ makeRequest, args = {} }) {
const request = useDeleteItems(makeRequest, args);
return <TestInner {...request} />;
}
describe('useRequest', () => {
test('should return initial value as result', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mount(
<Test
makeRequest={makeRequest}
initialValue={{
initial: true,
}}
/>
);
describe('useRequest hooks', () => {
describe('useRequest', () => {
test('should return initial value as result', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mount(
<Test
makeRequest={makeRequest}
initialValue={{
initial: true,
}}
/>
);
expect(wrapper.find('TestInner').prop('result')).toEqual({ initial: true });
expect(wrapper.find('TestInner').prop('result')).toEqual({
initial: true,
});
});
test('should return result', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mount(<Test makeRequest={makeRequest} />);
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('result')).toEqual({ data: 'foo' });
});
test('should is isLoading flag', async () => {
const makeRequest = jest.fn();
let resolve;
const promise = new Promise(r => {
resolve = r;
});
makeRequest.mockReturnValue(promise);
const wrapper = mount(<Test makeRequest={makeRequest} />);
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('isLoading')).toEqual(true);
await act(async () => {
resolve({ data: 'foo' });
});
wrapper.update();
expect(wrapper.find('TestInner').prop('isLoading')).toEqual(false);
expect(wrapper.find('TestInner').prop('result')).toEqual({ data: 'foo' });
});
test('should invoke request function', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mount(<Test makeRequest={makeRequest} />);
expect(makeRequest).not.toHaveBeenCalled();
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(makeRequest).toHaveBeenCalledTimes(1);
});
test('should return error thrown from request function', async () => {
const error = new Error('error');
const makeRequest = () => {
throw error;
};
const wrapper = mount(<Test makeRequest={makeRequest} />);
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('error')).toEqual(error);
});
test('should not update state after unmount', async () => {
const makeRequest = jest.fn();
let resolve;
const promise = new Promise(r => {
resolve = r;
});
makeRequest.mockReturnValue(promise);
const wrapper = mount(<Test makeRequest={makeRequest} />);
expect(makeRequest).not.toHaveBeenCalled();
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.unmount();
await act(async () => {
resolve({ data: 'foo' });
});
});
});
test('should return result', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mount(<Test makeRequest={makeRequest} />);
describe('useDeleteItems', () => {
test('should invoke delete function', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mountWithContexts(
<DeleteTest
makeRequest={makeRequest}
args={{
qsConfig: {},
fetchItems: () => {},
}}
/>
);
await act(async () => {
wrapper.find('TestInner').invoke('request')();
expect(makeRequest).not.toHaveBeenCalled();
await act(async () => {
wrapper.find('TestInner').invoke('deleteItems')();
});
wrapper.update();
expect(makeRequest).toHaveBeenCalledTimes(1);
});
wrapper.update();
expect(wrapper.find('TestInner').prop('result')).toEqual({ data: 'foo' });
});
test('should is isLoading flag', async () => {
const makeRequest = jest.fn();
let resolve;
const promise = new Promise(r => {
resolve = r;
test('should return error object thrown by function', async () => {
const error = new Error('error');
const makeRequest = () => {
throw error;
};
const wrapper = mountWithContexts(
<DeleteTest
makeRequest={makeRequest}
args={{
qsConfig: {},
fetchItems: () => {},
}}
/>
);
await act(async () => {
wrapper.find('TestInner').invoke('deleteItems')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('deletionError')).toEqual(error);
});
makeRequest.mockReturnValue(promise);
const wrapper = mount(<Test makeRequest={makeRequest} />);
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('isLoading')).toEqual(true);
await act(async () => {
resolve({ data: 'foo' });
});
wrapper.update();
expect(wrapper.find('TestInner').prop('isLoading')).toEqual(false);
expect(wrapper.find('TestInner').prop('result')).toEqual({ data: 'foo' });
});
test('should dismiss error', async () => {
const error = new Error('error');
const makeRequest = () => {
throw error;
};
const wrapper = mountWithContexts(
<DeleteTest
makeRequest={makeRequest}
args={{
qsConfig: {},
fetchItems: () => {},
}}
/>
);
test('should invoke request function', async () => {
const makeRequest = jest.fn();
makeRequest.mockResolvedValue({ data: 'foo' });
const wrapper = mount(<Test makeRequest={makeRequest} />);
expect(makeRequest).not.toHaveBeenCalled();
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(makeRequest).toHaveBeenCalledTimes(1);
});
test('should return error thrown from request function', async () => {
const error = new Error('error');
const makeRequest = () => {
throw error;
};
const wrapper = mount(<Test makeRequest={makeRequest} />);
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('error')).toEqual(error);
});
test('should not update state after unmount', async () => {
const makeRequest = jest.fn();
let resolve;
const promise = new Promise(r => {
resolve = r;
});
makeRequest.mockReturnValue(promise);
const wrapper = mount(<Test makeRequest={makeRequest} />);
expect(makeRequest).not.toHaveBeenCalled();
await act(async () => {
wrapper.find('TestInner').invoke('request')();
});
wrapper.unmount();
await act(async () => {
resolve({ data: 'foo' });
await act(async () => {
wrapper.find('TestInner').invoke('deleteItems')();
});
wrapper.update();
await act(async () => {
wrapper.find('TestInner').invoke('clearDeletionError')();
});
wrapper.update();
expect(wrapper.find('TestInner').prop('deletionError')).toEqual(null);
});
});
});