diff --git a/.npmignore b/.npmignore index 7aa125f..fa0d3e8 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,5 @@ src/ .babelrc webpack.config.js +.idea/ +test/ diff --git a/package.json b/package.json index 648d439..4011ed5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redux-json-api", - "version": "2.2.0", + "version": "2.2.3", "description": "A bunch of Redux actions, action creators and reducers to integrate with a JSON API", "main": "lib/jsonapi.js", "scripts": { diff --git a/src/jsonapi.js b/src/jsonapi.js index 4be1952..c34629c 100644 --- a/src/jsonapi.js +++ b/src/jsonapi.js @@ -207,7 +207,7 @@ export const requireResource = (resourceType, endpoint = resourceType) => { }; }; -export const readRelated = (resource, relationship) => { +export const readRelated = (resource, relationship, queryString = '') => { return (dispatch, getState) => { let endpoint; @@ -225,7 +225,7 @@ export const readRelated = (resource, relationship) => { endpoint = `${resource.type}/${resource.id}/${relationship}`; } - return dispatch(readEndpoint(endpoint)); + return dispatch(readEndpoint(`${endpoint}${queryString}`)); }; }; @@ -243,10 +243,10 @@ const getRelationshipEndpoint = (resource, relationship, axiosConfig) => { return `${resource.type}/${resource.id}/relationships/${relationship}`; }; -export const readRelationship = (resource, relationship) => { +export const readRelationship = (resource, relationship, queryString = '') => { return (dispatch, getState) => { const { axiosConfig } = getState().api.endpoint; - const endpoint = getRelationshipEndpoint(resource, relationship, axiosConfig); + const endpoint = getRelationshipEndpoint(resource, relationship, axiosConfig) + queryString; dispatch(apiWillRead(endpoint)); @@ -621,7 +621,7 @@ export const getResource = createCachedSelector( const getType = (identifiers) => { let type = identifiers; - if (Array.isArray(identifiers)) { + if (Array.isArray(identifiers) && identifiers.length > 0) { [{ type }] = identifiers; } @@ -651,5 +651,9 @@ export const getRelatedResources = (state, identifier, relationship) => { } const relationshipData = resource.relationships[relationship].data; + if (!relationshipData) { + return null; + } + return Array.isArray(relationshipData) ? getResources(state, relationshipData) : getResource(state, relationshipData); }; diff --git a/test/selectors.test.js b/test/selectors.test.js index e4591fe..4f00800 100644 --- a/test/selectors.test.js +++ b/test/selectors.test.js @@ -197,6 +197,14 @@ describe('Resources selector', () => { expect(resourceTree) .toEqual([]); }); + + it('should not break if identifiers is an empty array', () => { + state.types = {}; + const resourceTree = getResources(state, []); + + expect(resourceTree) + .toEqual([]); + }); }); describe('Relationship selector', () => { @@ -206,4 +214,16 @@ describe('Relationship selector', () => { expect(relationshipResources) .toEqual([state.api.transactions.data[0]]); }); + + it('should not break if use incorrect relationship name', () => { + const relationshipResources = getRelatedResources(state, state.api.users.data[1], 'incorrect_relationship'); + expect(relationshipResources) + .toEqual(null); + }); + + it('should not break if relationship does not have exist', () => { + const relationshipResources = getRelatedResources(state, state.api.users.data[1], 'companies'); + expect(relationshipResources) + .toEqual(null); + }); }); diff --git a/test/state-mutation.test.js b/test/state-mutation.test.js index 2542703..b12bf7c 100644 --- a/test/state-mutation.test.js +++ b/test/state-mutation.test.js @@ -312,6 +312,37 @@ describe('[State Mutation] Update or Reverse relationships', () => { updatedState.zenAccounts.data[0].relationships.expenseItems.data.length ).toEqual(1); }); + + it('should correctly identifies and mutate one-to-many reverse relationship', () => { + const localresource = { + type: 'companies', + id: '1', + attributes: { + name: 'ABC', + createdAt: '2016-02-19T11:52:43+0000', + updatedAt: '2016-02-19T11:52:43+0000' + }, + relationships: { + user: { + data: { + type: 'users', + id: '1' + } + }, + }, + links: { + self: 'http://localhost/companies/1' + } + }; + + const updatedState = updateOrInsertResource( + state, + localresource + ); + + expect(updatedState.users.data[0].relationships.companies.data) + .toStrictEqual([{ type: 'companies', id: '1' }]); + }); }); describe('[State Mutation]: Set is invalidating for existing resource', () => {