diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 2e30ab974..3880ded28 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -140,7 +140,7 @@ jobs: with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v7.1.0 + ref: v9.0.1 # DataGateway API file setup - name: Create search_api_mapping.json @@ -288,7 +288,7 @@ jobs: with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v7.1.0 + ref: v9.0.1 # DataGateway API file setup - name: Create search_api_mapping.json @@ -418,7 +418,7 @@ jobs: with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v7.1.0 + ref: v9.0.1 # DataGateway API file setup - name: Create search_api_mapping.json diff --git a/packages/datagateway-common/package.json b/packages/datagateway-common/package.json index 33969ab7f..2623eac36 100644 --- a/packages/datagateway-common/package.json +++ b/packages/datagateway-common/package.json @@ -10,7 +10,7 @@ "@date-io/date-fns": "2.16.0", "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", - "@mui/x-date-pickers": "5.0.9", + "@mui/x-date-pickers": "6.11.2", "@types/lodash.debounce": "4.0.6", "axios": "0.27.2", "connected-react-router": "6.9.1", diff --git a/packages/datagateway-common/src/api/dataPublications.test.tsx b/packages/datagateway-common/src/api/dataPublications.test.tsx index 43f83dcd0..660515e45 100644 --- a/packages/datagateway-common/src/api/dataPublications.test.tsx +++ b/packages/datagateway-common/src/api/dataPublications.test.tsx @@ -36,7 +36,7 @@ describe('data publications api functions', () => { ]; history = createMemoryHistory({ initialEntries: [ - '/?sort={"name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', + '/?sort={"name":"asc","title":"desc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', ], }); params = new URLSearchParams(); @@ -53,7 +53,7 @@ describe('data publications api functions', () => { data: mockData, }); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useDataPublicationsPaginated([ { @@ -74,6 +74,7 @@ describe('data publications api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -103,6 +104,16 @@ describe('data publications api functions', () => { params.toString() ); expect(result.current.data).toEqual(mockData); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(2); }); it('sends axios request to fetch paginated data publications and calls handleICATError on failure', async () => { @@ -143,7 +154,7 @@ describe('data publications api functions', () => { : Promise.resolve({ data: mockData[1] }) ); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useDataPublicationsInfinite([ { @@ -164,6 +175,7 @@ describe('data publications api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -219,6 +231,16 @@ describe('data publications api functions', () => { mockData[0], mockData[1], ]); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(3); }); it('sends axios request to fetch infinite data publications and calls handleICATError on failure', async () => { diff --git a/packages/datagateway-common/src/api/dataPublications.tsx b/packages/datagateway-common/src/api/dataPublications.tsx index c7ceb40bf..00cb55897 100644 --- a/packages/datagateway-common/src/api/dataPublications.tsx +++ b/packages/datagateway-common/src/api/dataPublications.tsx @@ -67,7 +67,7 @@ export const useDataPublicationsPaginated = ( [ string, { - sort: SortType; + sort: string; filters: FiltersType; page: number; results: number; @@ -77,11 +77,16 @@ export const useDataPublicationsPaginated = ( >( [ 'dataPublication', - { sort, filters, page: page ?? 1, results: results ?? 10 }, + { + sort: JSON.stringify(sort), // need to stringify sort as property order is important! + filters, + page: page ?? 1, + results: results ?? 10, + }, additionalFilters, ], (params) => { - const { sort, filters, page, results } = params.queryKey[1]; + const { page, results } = params.queryKey[1]; const startIndex = (page - 1) * results; const stopIndex = startIndex + results - 1; return fetchDataPublications( @@ -110,15 +115,13 @@ export const useDataPublicationsInfinite = ( const location = useLocation(); const { filters, sort } = parseSearchToQuery(location.search); - return useInfiniteQuery< - DataPublication[], - AxiosError, - DataPublication[], - [string, { sort: SortType; filters: FiltersType }, AdditionalFilters?] - >( - ['dataPublication', { sort, filters }, additionalFilters], + return useInfiniteQuery( + [ + 'dataPublication', + { sort: JSON.stringify(sort), filters }, // need to stringify sort as property order is important! + additionalFilters, + ], (params) => { - const { sort, filters } = params.queryKey[1]; const offsetParams = params.pageParam ?? { startIndex: 0, stopIndex: 49 }; return fetchDataPublications( apiUrl, diff --git a/packages/datagateway-common/src/api/datafiles.test.tsx b/packages/datagateway-common/src/api/datafiles.test.tsx index 3e888fa7e..9354faea6 100644 --- a/packages/datagateway-common/src/api/datafiles.test.tsx +++ b/packages/datagateway-common/src/api/datafiles.test.tsx @@ -40,7 +40,7 @@ describe('datafile api functions', () => { ]; history = createMemoryHistory({ initialEntries: [ - '/?sort={"name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', + '/?sort={"name":"asc","title":"desc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', ], }); params = new URLSearchParams(); @@ -58,7 +58,7 @@ describe('datafile api functions', () => { data: mockData, }); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useDatafilesPaginated([ { @@ -76,6 +76,7 @@ describe('datafile api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -102,6 +103,16 @@ describe('datafile api functions', () => { params.toString() ); expect(result.current.data).toEqual(mockData); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(2); }); it('sends axios request to fetch paginated datafiles and calls handleICATError on failure', async () => { @@ -139,7 +150,7 @@ describe('datafile api functions', () => { : Promise.resolve({ data: mockData[1] }) ); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useDatafilesInfinite([ { @@ -157,6 +168,7 @@ describe('datafile api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -209,6 +221,16 @@ describe('datafile api functions', () => { mockData[0], mockData[1], ]); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(3); }); it('sends axios request to fetch infinite datafiles and calls handleICATError on failure', async () => { diff --git a/packages/datagateway-common/src/api/datafiles.tsx b/packages/datagateway-common/src/api/datafiles.tsx index 976bfd410..82cad3bf0 100644 --- a/packages/datagateway-common/src/api/datafiles.tsx +++ b/packages/datagateway-common/src/api/datafiles.tsx @@ -69,7 +69,7 @@ export const useDatafilesPaginated = ( [ string, { - sort: SortType; + sort: string; filters: FiltersType; page: number; results: number; @@ -79,11 +79,16 @@ export const useDatafilesPaginated = ( >( [ 'datafile', - { sort, filters, page: page ?? 1, results: results ?? 10 }, + { + sort: JSON.stringify(sort), // need to stringify sort as property order is important! + filters, + page: page ?? 1, + results: results ?? 10, + }, additionalFilters, ], (params) => { - const { sort, filters, page, results } = params.queryKey[1]; + const { page, results } = params.queryKey[1]; const startIndex = (page - 1) * results; const stopIndex = startIndex + results - 1; return fetchDatafiles(apiUrl, { sort, filters }, additionalFilters, { @@ -107,15 +112,9 @@ export const useDatafilesInfinite = ( const location = useLocation(); const { filters, sort } = parseSearchToQuery(location.search); - return useInfiniteQuery< - Datafile[], - AxiosError, - Datafile[], - [string, { sort: SortType; filters: FiltersType }, AdditionalFilters?] - >( - ['datafile', { sort, filters }, additionalFilters], + return useInfiniteQuery( + ['datafile', { sort: JSON.stringify(sort), filters }, additionalFilters], // need to stringify sort as property order is important! (params) => { - const { sort, filters } = params.queryKey[1]; const offsetParams = params.pageParam ?? { startIndex: 0, stopIndex: 49 }; return fetchDatafiles( apiUrl, diff --git a/packages/datagateway-common/src/api/datasets.test.tsx b/packages/datagateway-common/src/api/datasets.test.tsx index d9d874fe6..1d1d0ccd5 100644 --- a/packages/datagateway-common/src/api/datasets.test.tsx +++ b/packages/datagateway-common/src/api/datasets.test.tsx @@ -45,7 +45,7 @@ describe('dataset api functions', () => { ]; history = createMemoryHistory({ initialEntries: [ - '/?sort={"name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', + '/?sort={"name":"asc","title":"desc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', ], }); params = new URLSearchParams(); @@ -126,7 +126,7 @@ describe('dataset api functions', () => { data: mockData, }); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useDatasetsPaginated([ { @@ -144,6 +144,7 @@ describe('dataset api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -170,6 +171,16 @@ describe('dataset api functions', () => { params.toString() ); expect(result.current.data).toEqual(mockData); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(2); }); it('sends axios request to fetch paginated datasets and calls handleICATError on failure', async () => { @@ -207,7 +218,7 @@ describe('dataset api functions', () => { : Promise.resolve({ data: mockData[1] }) ); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useDatasetsInfinite([ { @@ -225,6 +236,7 @@ describe('dataset api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -277,6 +289,16 @@ describe('dataset api functions', () => { mockData[0], mockData[1], ]); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(3); }); it('sends axios request to fetch infinite datasets and calls handleICATError on failure', async () => { diff --git a/packages/datagateway-common/src/api/datasets.tsx b/packages/datagateway-common/src/api/datasets.tsx index 676b706e2..48aa8a55d 100644 --- a/packages/datagateway-common/src/api/datasets.tsx +++ b/packages/datagateway-common/src/api/datasets.tsx @@ -109,7 +109,7 @@ export const useDatasetsPaginated = ( [ string, { - sort: SortType; + sort: string; filters: FiltersType; page: number; results: number; @@ -119,11 +119,16 @@ export const useDatasetsPaginated = ( >( [ 'dataset', - { sort, filters, page: page ?? 1, results: results ?? 10 }, + { + sort: JSON.stringify(sort), // need to stringify sort as property order is important! + filters, + page: page ?? 1, + results: results ?? 10, + }, additionalFilters, ], (params) => { - const { sort, filters, page, results } = params.queryKey[1]; + const { page, results } = params.queryKey[1]; const startIndex = (page - 1) * results; const stopIndex = startIndex + results - 1; return fetchDatasets(apiUrl, { sort, filters }, additionalFilters, { @@ -147,15 +152,9 @@ export const useDatasetsInfinite = ( const location = useLocation(); const { filters, sort } = parseSearchToQuery(location.search); - return useInfiniteQuery< - Dataset[], - AxiosError, - Dataset[], - [string, { sort: SortType; filters: FiltersType }, AdditionalFilters?] - >( - ['dataset', { sort, filters }, additionalFilters], + return useInfiniteQuery( + ['dataset', { sort: JSON.stringify(sort), filters }, additionalFilters], // need to stringify sort as property order is important! (params) => { - const { sort, filters } = params.queryKey[1]; const offsetParams = params.pageParam ?? { startIndex: 0, stopIndex: 49 }; return fetchDatasets( apiUrl, diff --git a/packages/datagateway-common/src/api/facilityCycles.test.tsx b/packages/datagateway-common/src/api/facilityCycles.test.tsx index 1f8fcf116..7ee87672e 100644 --- a/packages/datagateway-common/src/api/facilityCycles.test.tsx +++ b/packages/datagateway-common/src/api/facilityCycles.test.tsx @@ -36,7 +36,7 @@ describe('facility cycle api functions', () => { ]; history = createMemoryHistory({ initialEntries: [ - '/?sort={"name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', + '/?sort={"name":"asc","title":"desc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', ], }); params = new URLSearchParams(); @@ -88,7 +88,7 @@ describe('facility cycle api functions', () => { data: mockData, }); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useFacilityCyclesPaginated(1), { wrapper: createReactQueryWrapper(history), @@ -98,6 +98,7 @@ describe('facility cycle api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -131,6 +132,16 @@ describe('facility cycle api functions', () => { params.toString() ); expect(result.current.data).toEqual(mockData); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(2); }); it('sends axios request to fetch paginated facility cycles and calls handleICATError on failure', async () => { @@ -184,7 +195,7 @@ describe('facility cycle api functions', () => { : Promise.resolve({ data: mockData[1] }) ); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useFacilityCyclesInfinite(1), { wrapper: createReactQueryWrapper(history), @@ -194,6 +205,7 @@ describe('facility cycle api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -253,6 +265,16 @@ describe('facility cycle api functions', () => { mockData[0], mockData[1], ]); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(3); }); it('sends axios request to fetch infinite facility cycles and calls handleICATError on failure', async () => { diff --git a/packages/datagateway-common/src/api/facilityCycles.tsx b/packages/datagateway-common/src/api/facilityCycles.tsx index 6187918c3..cb82a7afe 100644 --- a/packages/datagateway-common/src/api/facilityCycles.tsx +++ b/packages/datagateway-common/src/api/facilityCycles.tsx @@ -106,7 +106,7 @@ export const useFacilityCyclesPaginated = ( string, number, { - sort: SortType; + sort: string; filters: FiltersType; page: number; results: number; @@ -116,10 +116,15 @@ export const useFacilityCyclesPaginated = ( [ 'facilityCycle', instrumentId, - { sort, filters, page: page ?? 1, results: results ?? 10 }, + { + sort: JSON.stringify(sort), // need to stringify sort as property order is important! + filters, + page: page ?? 1, + results: results ?? 10, + }, ], (params) => { - const { sort, filters, page, results } = params.queryKey[2]; + const { page, results } = params.queryKey[2]; const startIndex = (page - 1) * results; const stopIndex = startIndex + results - 1; return fetchFacilityCycles( @@ -148,15 +153,9 @@ export const useFacilityCyclesInfinite = ( const location = useLocation(); const { filters, sort } = parseSearchToQuery(location.search); - return useInfiniteQuery< - FacilityCycle[], - AxiosError, - FacilityCycle[], - [string, number, { sort: SortType; filters: FiltersType }] - >( - ['facilityCycle', instrumentId, { sort, filters }], + return useInfiniteQuery( + ['facilityCycle', instrumentId, { sort: JSON.stringify(sort), filters }], (params) => { - const { sort, filters } = params.queryKey[2]; const offsetParams = params.pageParam ?? { startIndex: 0, stopIndex: 49 }; return fetchFacilityCycles( apiUrl, diff --git a/packages/datagateway-common/src/api/index.test.tsx b/packages/datagateway-common/src/api/index.test.tsx index e841b362c..ec9a20625 100644 --- a/packages/datagateway-common/src/api/index.test.tsx +++ b/packages/datagateway-common/src/api/index.test.tsx @@ -268,6 +268,7 @@ describe('generic api functions', () => { filters: { name: { value: 'test', type: 'include' }, title: { value: 'test', type: 'exclude' }, + doi: { value: 'test', type: 'exact' }, startDate: { startDate: '2021-08-05', endDate: '2021-08-06', @@ -282,6 +283,7 @@ describe('generic api functions', () => { params.append('order', JSON.stringify('id asc')); params.append('where', JSON.stringify({ name: { ilike: 'test' } })); params.append('where', JSON.stringify({ title: { nilike: 'test' } })); + params.append('where', JSON.stringify({ doi: { eq: 'test' } })); params.append( 'where', JSON.stringify({ startDate: { gte: '2021-08-05 00:00:00' } }) @@ -302,6 +304,7 @@ describe('generic api functions', () => { filters: { name: { value: 'test', type: 'include' }, title: { value: 'test', type: 'exclude' }, + doi: { value: 'test', type: 'exact' }, startDate: { startDate: '2021-08-05', endDate: '2021-08-06', @@ -315,6 +318,7 @@ describe('generic api functions', () => { params.append('order', JSON.stringify('name asc')); params.append('where', JSON.stringify({ name: { ilike: 'test' } })); params.append('where', JSON.stringify({ title: { nilike: 'test' } })); + params.append('where', JSON.stringify({ doi: { eq: 'test' } })); params.append( 'where', JSON.stringify({ startDate: { gte: '2021-08-05 00:00:00' } }) diff --git a/packages/datagateway-common/src/api/index.tsx b/packages/datagateway-common/src/api/index.tsx index 396edd6aa..2107e07c5 100644 --- a/packages/datagateway-common/src/api/index.tsx +++ b/packages/datagateway-common/src/api/index.tsx @@ -254,11 +254,16 @@ export const getApiParams = ( 'where', JSON.stringify({ [column]: { ilike: filter.value } }) ); - } else { + } else if (filter.type === 'exclude') { searchParams.append( 'where', JSON.stringify({ [column]: { nilike: filter.value } }) ); + } else { + searchParams.append( + 'where', + JSON.stringify({ [column]: { eq: filter.value } }) + ); } } } else { diff --git a/packages/datagateway-common/src/api/instruments.test.tsx b/packages/datagateway-common/src/api/instruments.test.tsx index 214864251..1100b4065 100644 --- a/packages/datagateway-common/src/api/instruments.test.tsx +++ b/packages/datagateway-common/src/api/instruments.test.tsx @@ -30,7 +30,7 @@ describe('instrument api functions', () => { ]; history = createMemoryHistory({ initialEntries: [ - '/?sort={"name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', + '/?sort={"name":"asc","title":"desc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', ], }); params = new URLSearchParams(); @@ -47,13 +47,17 @@ describe('instrument api functions', () => { data: mockData, }); - const { result, waitFor } = renderHook(() => useInstrumentsPaginated(), { - wrapper: createReactQueryWrapper(history), - }); + const { result, waitFor, rerender } = renderHook( + () => useInstrumentsPaginated(), + { + wrapper: createReactQueryWrapper(history), + } + ); await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -74,6 +78,16 @@ describe('instrument api functions', () => { params.toString() ); expect(result.current.data).toEqual(mockData); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(2); }); it('sends axios request to fetch paginated instruments and calls handleICATError on failure', async () => { @@ -121,13 +135,17 @@ describe('instrument api functions', () => { : Promise.resolve({ data: mockData[1] }) ); - const { result, waitFor } = renderHook(() => useInstrumentsInfinite(), { - wrapper: createReactQueryWrapper(history), - }); + const { result, waitFor, rerender } = renderHook( + () => useInstrumentsInfinite(), + { + wrapper: createReactQueryWrapper(history), + } + ); await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -174,6 +192,16 @@ describe('instrument api functions', () => { mockData[0], mockData[1], ]); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(3); }); it('sends axios request to fetch infinite instruments and calls handleICATError on failure', async () => { diff --git a/packages/datagateway-common/src/api/instruments.tsx b/packages/datagateway-common/src/api/instruments.tsx index e2822d446..51d9c36a6 100644 --- a/packages/datagateway-common/src/api/instruments.tsx +++ b/packages/datagateway-common/src/api/instruments.tsx @@ -69,16 +69,24 @@ export const useInstrumentsPaginated = ( [ string, { - sort: SortType; + sort: string; filters: FiltersType; page: number; results: number; } ] >( - ['instrument', { sort, filters, page: page ?? 1, results: results ?? 10 }], + [ + 'instrument', + { + sort: JSON.stringify(sort), // need to stringify sort as property order is important! + filters, + page: page ?? 1, + results: results ?? 10, + }, + ], (params) => { - const { sort, filters, page, results } = params.queryKey[1]; + const { page, results } = params.queryKey[1]; const startIndex = (page - 1) * results; const stopIndex = startIndex + results - 1; return fetchInstruments(apiUrl, { sort, filters }, additionalFilters, { @@ -102,15 +110,9 @@ export const useInstrumentsInfinite = ( const location = useLocation(); const { filters, sort } = parseSearchToQuery(location.search); - return useInfiniteQuery< - Instrument[], - AxiosError, - Instrument[], - [string, { sort: SortType; filters: FiltersType }] - >( - ['instrument', { sort, filters }], + return useInfiniteQuery( + ['instrument', { sort: JSON.stringify(sort), filters }], // need to stringify sort as property order is important! (params) => { - const { sort, filters } = params.queryKey[1]; const offsetParams = params.pageParam ?? { startIndex: 0, stopIndex: 49 }; return fetchInstruments( apiUrl, diff --git a/packages/datagateway-common/src/api/investigations.test.tsx b/packages/datagateway-common/src/api/investigations.test.tsx index 35ab47dad..23e8090d9 100644 --- a/packages/datagateway-common/src/api/investigations.test.tsx +++ b/packages/datagateway-common/src/api/investigations.test.tsx @@ -52,7 +52,7 @@ describe('investigation api functions', () => { ]; history = createMemoryHistory({ initialEntries: [ - '/?sort={"name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', + '/?sort={"name":"asc","title":"desc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20', ], }); params = new URLSearchParams(); @@ -133,7 +133,7 @@ describe('investigation api functions', () => { data: mockData, }); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useInvestigationsPaginated([ { @@ -151,6 +151,7 @@ describe('investigation api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -177,6 +178,16 @@ describe('investigation api functions', () => { params.toString() ); expect(result.current.data).toEqual(mockData); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}&page=2&results=20' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(2); }); it('sends axios request to fetch paginated investigations and returns successful response when ignoreIDSort is true', async () => { @@ -205,6 +216,7 @@ describe('investigation api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append( 'where', JSON.stringify({ @@ -270,7 +282,7 @@ describe('investigation api functions', () => { : Promise.resolve({ data: mockData[1] }) ); - const { result, waitFor } = renderHook( + const { result, waitFor, rerender } = renderHook( () => useInvestigationsInfinite([ { @@ -288,6 +300,7 @@ describe('investigation api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append('order', JSON.stringify('id asc')); params.append( 'where', @@ -340,6 +353,16 @@ describe('investigation api functions', () => { mockData[0], mockData[1], ]); + + // test that order of sort object triggers new query + history.push( + '/?sort={"title":"desc", "name":"asc"}&filters={"name":{"value":"test","type":"include"}}' + ); + rerender(); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(axios.get as jest.Mock).toHaveBeenCalledTimes(3); }); it('sends axios request to fetch infinite investigations and returns successful response when ignoreIDSort is true', async () => { @@ -370,6 +393,7 @@ describe('investigation api functions', () => { await waitFor(() => result.current.isSuccess); params.append('order', JSON.stringify('name asc')); + params.append('order', JSON.stringify('title desc')); params.append( 'where', JSON.stringify({ diff --git a/packages/datagateway-common/src/api/investigations.tsx b/packages/datagateway-common/src/api/investigations.tsx index e76c660bd..ce53b0e2e 100644 --- a/packages/datagateway-common/src/api/investigations.tsx +++ b/packages/datagateway-common/src/api/investigations.tsx @@ -111,7 +111,7 @@ export const useInvestigationsPaginated = ( [ string, { - sort: SortType; + sort: string; filters: FiltersType; page: number; results: number; @@ -122,12 +122,17 @@ export const useInvestigationsPaginated = ( >( [ 'investigation', - { sort, filters, page: page ?? 1, results: results ?? 10 }, + { + sort: JSON.stringify(sort), // need to stringify sort as property order is important! + filters, + page: page ?? 1, + results: results ?? 10, + }, additionalFilters, ignoreIDSort, ], (params) => { - const { sort, filters, page, results } = params.queryKey[1]; + const { page, results } = params.queryKey[1]; const startIndex = (page - 1) * results; const stopIndex = startIndex + results - 1; return fetchInvestigations( @@ -158,20 +163,14 @@ export const useInvestigationsInfinite = ( const location = useLocation(); const { filters, sort } = parseSearchToQuery(location.search); - return useInfiniteQuery< - Investigation[], - AxiosError, - Investigation[], + return useInfiniteQuery( [ - string, - { sort: SortType; filters: FiltersType }, - AdditionalFilters?, - boolean? - ] - >( - ['investigation', { sort, filters }, additionalFilters, ignoreIDSort], + 'investigation', + { sort: JSON.stringify(sort), filters }, // need to stringify sort as property order is important! + additionalFilters, + ignoreIDSort, + ], (params) => { - const { sort, filters } = params.queryKey[1]; const offsetParams = params.pageParam ?? { startIndex: 0, stopIndex: 49 }; return fetchInvestigations( apiUrl, diff --git a/packages/datagateway-common/src/table/columnFilters/__snapshots__/dateColumnFilter.component.test.tsx.snap b/packages/datagateway-common/src/table/columnFilters/__snapshots__/dateColumnFilter.component.test.tsx.snap index 10e416a6e..70e1d6028 100644 --- a/packages/datagateway-common/src/table/columnFilters/__snapshots__/dateColumnFilter.component.test.tsx.snap +++ b/packages/datagateway-common/src/table/columnFilters/__snapshots__/dateColumnFilter.component.test.tsx.snap @@ -1,21 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Date filter component CustomClearButton renders correctly 1`] = ` - - - -`; - exports[`Date filter component DatePicker functionality useDateFilter hook returns a function which can generate a working date filter 1`] = `
@@ -28,10 +12,12 @@ exports[`Date filter component DatePicker functionality useDateFilter hook retur