diff --git a/package-lock.json b/package-lock.json index 4472ef3..1b22486 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@civicactions/data-catalog-services", - "version": "1.5.0", + "version": "1.6.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@civicactions/data-catalog-services", - "version": "1.5.0", + "version": "1.6.0-alpha.1", "license": "GPL-3.0", "dependencies": { "axios": "^0.21.2", diff --git a/package.json b/package.json index 3facb20..bd9fcf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@civicactions/data-catalog-services", - "version": "1.5.0", + "version": "1.6.0-alpha.1", "description": "Functions and React components to connect to the DKAN api.", "main": "lib/index.js", "scripts": { diff --git a/src/hooks/useDatastore/fetch.js b/src/hooks/useDatastore/fetch.js index 9157058..162b3bc 100644 --- a/src/hooks/useDatastore/fetch.js +++ b/src/hooks/useDatastore/fetch.js @@ -29,36 +29,40 @@ export async function fetchDataFromQuery( if (typeof setLoading === "function") { setLoading(true); } - return await axios({ - method: "GET", - url: `${rootUrl}/datastore/query/${id}`, - params: { - keys: keys, - limit: limit, - offset: offset, - conditions: conditions, - sorts: sort, - properties: properties, - groupings: groupings, - ...additionalParams, - }, - paramsSerializer: (params) => { - return qs.stringify(params); - }, - }).then((res) => { - const { data } = res; - const propertyKeys = - data.schema[id] && data.schema[id].fields - ? Object.keys(data.schema[id].fields) - : []; - setValues(data.results), setCount(data.count); - if (propertyKeys.length) { - setColumns(prepareColumns ? prepareColumns(propertyKeys) : propertyKeys); - } - setSchema(data.schema); - if (typeof setLoading === "function") { - setLoading(false); - } - return data; - }); + + let url = `${rootUrl}/datastore/query/${id}`; + if (Array.isArray(id)) { + url = `${rootUrl}/datastore/query/${id[0]}/${id[1]}`; + } + const params = { + keys: keys, + limit: limit, + offset: offset, + conditions: conditions, + sorts: sort, + properties: properties, + groupings: groupings, + ...additionalParams, + }; + + const res = await axios.get(`${url}?${qs.stringify(params)}`); + const data = res.data; + + let schema_fields = []; + if (Object.keys(data.schema).length > 0) { + const schemaId = Object.keys(data.schema)[0]; + schema_fields = Object.keys(data.schema[schemaId].fields); + } + + setValues(data.results); + setCount(data.count); + if (schema_fields.length) { + setColumns(prepareColumns ? prepareColumns(schema_fields) : schema_fields); + } + setSchema(data.schema); + if (typeof setLoading === "function") { + setLoading(false); + } + + return data; } diff --git a/src/hooks/useDatastore/fetch.test.js b/src/hooks/useDatastore/fetch.test.js index 7d46d2a..b77d380 100644 --- a/src/hooks/useDatastore/fetch.test.js +++ b/src/hooks/useDatastore/fetch.test.js @@ -1,7 +1,10 @@ import axios from "axios"; +import { act } from "@testing-library/react-hooks"; import { fetchDataFromQuery } from "./fetch"; jest.mock("axios"); +jest.useFakeTimers(); + const rootUrl = "http://dkan.com/api/1"; const data = { data: { @@ -18,6 +21,7 @@ const data = { }, }, }; + const distribution = { identifier: "1234-1234", data: { @@ -29,7 +33,7 @@ const distribution = { describe("fetchDataFromQuery", () => { test("returns data from datastore query endpoint", async () => { - axios.mockImplementation(() => Promise.resolve(data)); + axios.get.mockImplementation(() => Promise.resolve(data)); const results = await fetchDataFromQuery(distribution.identifier, rootUrl, { keys: true, limit: 20, @@ -41,6 +45,42 @@ describe("fetchDataFromQuery", () => { setColumns: () => {}, setSchema: () => {}, }); + await act(async () => { + jest.runAllTimers(); + }); + + expect(axios.get).toHaveBeenCalledWith( + `${rootUrl}/datastore/query/1234-1234?keys=true&limit=20&offset=0` + ); + + expect(results.count).toEqual(data.data.count); + expect(results.results).toEqual(data.data.results); + }); + test("returns data from datastore query index endpoint", async () => { + axios.get.mockImplementation(() => Promise.resolve(data)); + const results = await fetchDataFromQuery( + [distribution.identifier, 0], + rootUrl, + { + keys: true, + limit: 20, + offset: 0, + conditions: [], + sorts: [], + setValues: () => {}, + setCount: () => {}, + setColumns: () => {}, + setSchema: () => {}, + } + ); + await act(async () => { + jest.runAllTimers(); + }); + + expect(axios.get).toHaveBeenCalledWith( + `${rootUrl}/datastore/query/1234-1234/0?keys=true&limit=20&offset=0` + ); + expect(results.count).toEqual(data.data.count); expect(results.results).toEqual(data.data.results); }); diff --git a/src/hooks/useDatastore/index.jsx b/src/hooks/useDatastore/index.jsx index cb0a18c..a69677b 100644 --- a/src/hooks/useDatastore/index.jsx +++ b/src/hooks/useDatastore/index.jsx @@ -36,6 +36,14 @@ const useDatastore = ( const prevLimitRef = useRef(); const prevOffsetRef = useRef(); + let queryId = id; + let queryIndex = 0; + + if (Array.isArray(id)) { + queryId = id[0]; + queryIndex = id[1]; + } + useEffect(() => { prevLimitRef.current = limit; prevOffsetRef.current = offset; @@ -83,7 +91,16 @@ const useDatastore = ( } } } - }, [id, rootUrl, offset, conditions, sort, limit, requireConditions]); + }, [ + queryId, + queryIndex, + rootUrl, + offset, + conditions, + sort, + limit, + requireConditions, + ]); return { loading, diff --git a/src/hooks/useDatastore/useDatastore.test.jsx b/src/hooks/useDatastore/useDatastore.test.jsx index 50587f7..af22aac 100644 --- a/src/hooks/useDatastore/useDatastore.test.jsx +++ b/src/hooks/useDatastore/useDatastore.test.jsx @@ -32,8 +32,8 @@ const distribution = { }; describe("useDatastore Custom Hook", () => { - test("returns data from datastore query endpoint", async () => { - axios.mockImplementation(() => Promise.resolve(data)); + test("returns data from datastore query endpoint with distribution id", async () => { + axios.get.mockImplementation(() => Promise.resolve(data)); const { result } = renderHook(() => useDatastore(distribution.identifier, rootUrl, {}) ); @@ -56,4 +56,28 @@ describe("useDatastore Custom Hook", () => { }); expect(result.current.offset).toEqual(25); }); + test("returns data from datastore query endpoint with dataset id", async () => { + axios.get.mockImplementation(() => Promise.resolve(data)); + const { result } = renderHook(() => + useDatastore([distribution.identifier, 0], rootUrl, {}) + ); + await act(async () => {}); + expect(result.current.values).toEqual(data.data.results); + expect(result.current.limit).toEqual(20); + expect(result.current.offset).toEqual(0); + expect(result.current.count).toEqual("1"); + expect(result.current.columns).toEqual([ + "record_id", + "column_1", + "column_2", + ]); + await act(async () => { + result.current.setLimit(100); + }); + expect(result.current.limit).toEqual(100); + await act(async () => { + result.current.setOffset(25); + }); + expect(result.current.offset).toEqual(25); + }); });