diff --git a/awx/ui_next/src/util/qs.js b/awx/ui_next/src/util/qs.js index c2d25024a9..b97f3ce9ac 100644 --- a/awx/ui_next/src/util/qs.js +++ b/awx/ui_next/src/util/qs.js @@ -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); diff --git a/awx/ui_next/src/util/useRequest.js b/awx/ui_next/src/util/useRequest.js index 9f0ea0c91f..6c06cc0a34 100644 --- a/awx/ui_next/src/util/useRequest.js +++ b/awx/ui_next/src/util/useRequest.js @@ -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 () => { diff --git a/awx/ui_next/src/util/useRequest.test.jsx b/awx/ui_next/src/util/useRequest.test.jsx index 1cf7ed955b..1d8185229a 100644 --- a/awx/ui_next/src/util/useRequest.test.jsx +++ b/awx/ui_next/src/util/useRequest.test.jsx @@ -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
; @@ -10,100 +11,179 @@ function Test({ makeRequest, initialValue = {} }) { const request = useRequest(makeRequest, initialValue); return ; } +function DeleteTest({ makeRequest, args = {} }) { + const request = useDeleteItems(makeRequest, args); + return ; +} -describe('useRequest', () => { - test('should return initial value as result', async () => { - const makeRequest = jest.fn(); - makeRequest.mockResolvedValue({ data: 'foo' }); - const wrapper = mount( - - ); +describe('useRequest hooks', () => { + describe('useRequest', () => { + test('should return initial value as result', async () => { + const makeRequest = jest.fn(); + makeRequest.mockResolvedValue({ data: 'foo' }); + const wrapper = mount( + + ); - 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(); + + 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(); + + 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(); + + 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(); + + 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(); + + 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(); + describe('useDeleteItems', () => { + test('should invoke delete function', async () => { + const makeRequest = jest.fn(); + makeRequest.mockResolvedValue({ data: 'foo' }); + const wrapper = mountWithContexts( + {}, + }} + /> + ); - 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( + {}, + }} + /> + ); + + await act(async () => { + wrapper.find('TestInner').invoke('deleteItems')(); + }); + wrapper.update(); + expect(wrapper.find('TestInner').prop('deletionError')).toEqual(error); }); - makeRequest.mockReturnValue(promise); - const wrapper = mount(); - 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( + {}, + }} + /> + ); - test('should invoke request function', async () => { - const makeRequest = jest.fn(); - makeRequest.mockResolvedValue({ data: 'foo' }); - const wrapper = mount(); - - 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(); - - 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(); - - 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); }); }); });