Skip to content

Commit

Permalink
Add includes to writeRelated methods (configurable).
Browse files Browse the repository at this point in the history
  • Loading branch information
mrichar1 committed Oct 27, 2022
1 parent b5a11df commit 62fd2ea
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 6 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,8 @@ For many of these options, more information is provided in the [Usage](#usage) s
- `cleanPatchProps` - If cleanPatch is enabled, an array of `_jv` properties that should be preserved - `links`, `meta`, and/or `relationships`. (defaults to `[]`).
- `recurseRelationships` - If `false`, replaces recursive relationships with a normalised resource identifier (i.e `{ _jv: { type: 'x', id: 'y' } }`). (defaults to `false`).
- `maxStatusID` - Sets the highest status ID that will be used in `status` before rolling round to 1 again. (defaults to `-1` - no limit).
- `relatedIncludes` - When returning the original object from `patch|post|deleteRelated` methods, also include related objects (defaults to `true`).


## Endpoints

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonapi-vuex",
"version": "5.9.1",
"version": "5.10.0",
"description": "Access restructured JSONAPI data from a Vuex Store.",
"author": "Matthew Richardson <M.Richardson@ed.ac.uk>",
"scripts": {
Expand Down Expand Up @@ -40,7 +40,7 @@
"babel-polyfill": "^6.26.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chromedriver": "^103",
"chromedriver": "^106",
"concurrently": "^6.2.1",
"core-js": "^3.16.1",
"eslint": "^7.32.0",
Expand Down
12 changes: 8 additions & 4 deletions src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ const actions = (api, conf) => {

// Iterate over all records in rels
let relPromises = []
let includes = []
for (let [relName, relItems] of Object.entries(rels)) {
includes.push(relName)
if (utils.hasProperty(relItems, 'data')) {
let path = `${type}/${id}/relationships/${relName}`
const apiConf = {
Expand All @@ -61,7 +63,12 @@ const actions = (api, conf) => {
// Wait for all individual API calls to complete
await Promise.all(relPromises)
// Get the updated object from the API
return context.dispatch('get', `${type}/${id}`)
let params = {}
// Also include related objects
if (conf.relatedIncludes) {
params['include'] = includes.join()
}
return context.dispatch('get', [`${type}/${id}`, { params: params }])
}

return {
Expand Down Expand Up @@ -208,7 +215,6 @@ const actions = (api, conf) => {
* @memberof module:jsonapi-vuex.jsonapiModule.actions
* @param {object} context - Vuex context object
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
* @return {object} Restructured representation of the 'parent' item
*/
deleteRelated: (context, args) => {
Expand All @@ -221,7 +227,6 @@ const actions = (api, conf) => {
* @memberof module:jsonapi-vuex.jsonapiModule.actions
* @param {object} context - Vuex context object
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
* @return {object} Restructured representation of the 'parent' item
*/
patchRelated: async (context, args) => {
Expand All @@ -234,7 +239,6 @@ const actions = (api, conf) => {
* @memberof module:jsonapi-vuex.jsonapiModule.actions
* @param {object} context - Vuex context object
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
* @return {object} Restructured representation of the 'parent' item
*/
postRelated: async (context, args) => {
Expand Down
2 changes: 2 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* @property {string[]} cleanPatchProps='[]' - If cleanPatch is enabled, which _jv props (links, meta, rels) should be kept?
* @property {boolean} recurseRelationships=false - Allow relationships to be recursive?
* @property {integer} maxStatusID=-1 - The maximum number of status IDs to generate before looping. Default is unlimited.
* @property {boolean} relatedIncludes=true - When returning the original object from *related 'write' methods, also include related objects. Default is true.
*/

export default {
Expand All @@ -24,4 +25,5 @@ export default {
cleanPatchProps: [],
recurseRelationships: false,
maxStatusID: -1,
relatedIncludes: true,
}
20 changes: 20 additions & 0 deletions tests/unit/actions/deleteRelated.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect } from 'chai'

import createStubContext from '../stubs/context'
import createJsonapiModule from '../utils/createJsonapiModule'
import { config } from '../../../src/jsonapi-vuex'
import { jsonFormat as createJsonWidget1, normFormat as createNormWidget1 } from '../fixtures/widget1'

describe('deleteRelated', function () {
Expand Down Expand Up @@ -44,6 +45,24 @@ describe('deleteRelated', function () {
// Expect a delete call to rel url, with rel payload, then get object to update store
expect(this.mockApi.history.delete[0].url).to.equal('widget/1/relationships/widgets')
expect(this.mockApi.history.delete[0].data).to.deep.equal(JSON.stringify(rel))
expect(this.mockApi.history.get[0].params).to.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
})

it('should make a delete request for the object passed in.', async function () {
this.mockApi.onDelete().replyOnce(204)
this.mockApi.onGet().replyOnce(200, { data: jsonWidget1 })

const rel = { data: { type: 'widget', id: '2' } }
normWidget1['_jv']['relationships'] = { widgets: rel }

config.relatedIncludes = false

await jsonapiModule.actions.deleteRelated(stubContext, normWidget1)
// Expect a delete call to rel url, with rel payload, then get object to update store
expect(this.mockApi.history.delete[0].url).to.equal('widget/1/relationships/widgets')
expect(this.mockApi.history.delete[0].data).to.deep.equal(JSON.stringify(rel))
expect(this.mockApi.history.get[0].params).to.not.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
})

Expand All @@ -60,6 +79,7 @@ describe('deleteRelated', function () {
expect(this.mockApi.history.delete[0].data).to.deep.equal(JSON.stringify(rel1))
expect(this.mockApi.history.delete[1].url).to.equal('widget/1/relationships/doohickeys')
expect(this.mockApi.history.delete[1].data).to.deep.equal(JSON.stringify(rel2))
expect(this.mockApi.history.get[0].params).to.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
// Only get the object once at end
expect(this.mockApi.history.get.length).to.equal(1)
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/actions/patchRelated.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect } from 'chai'

import createStubContext from '../stubs/context'
import createJsonapiModule from '../utils/createJsonapiModule'
import { config } from '../../../src/jsonapi-vuex'
import { jsonFormat as createJsonWidget1, normFormat as createNormWidget1 } from '../fixtures/widget1'

describe('patchRelated', function () {
Expand Down Expand Up @@ -44,6 +45,24 @@ describe('patchRelated', function () {
// Expect a patch call to rel url, with rel payload, then get object to update store
expect(this.mockApi.history.patch[0].url).to.equal('widget/1/relationships/widgets')
expect(this.mockApi.history.patch[0].data).to.deep.equal(JSON.stringify(rel))
expect(this.mockApi.history.get[0].params).to.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
})

it('should make a patch request without includes.', async function () {
this.mockApi.onPatch().replyOnce(204)
this.mockApi.onGet().replyOnce(200, { data: jsonWidget1 })

const rel = { data: { type: 'widget', id: '2' } }
normWidget1['_jv']['relationships'] = { widgets: rel }

config.relatedIncludes = false

await jsonapiModule.actions.patchRelated(stubContext, normWidget1)
// Expect a patch call to rel url, with rel payload, then get object to update store
expect(this.mockApi.history.patch[0].url).to.equal('widget/1/relationships/widgets')
expect(this.mockApi.history.patch[0].data).to.deep.equal(JSON.stringify(rel))
expect(this.mockApi.history.get[0].params).to.not.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
})

Expand All @@ -60,6 +79,7 @@ describe('patchRelated', function () {
expect(this.mockApi.history.patch[0].data).to.deep.equal(JSON.stringify(rel1))
expect(this.mockApi.history.patch[1].url).to.equal('widget/1/relationships/doohickeys')
expect(this.mockApi.history.patch[1].data).to.deep.equal(JSON.stringify(rel2))
expect(this.mockApi.history.get[0].params).to.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
// Only get the object once at end
expect(this.mockApi.history.get.length).to.equal(1)
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/actions/postRelated.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect } from 'chai'

import createStubContext from '../stubs/context'
import createJsonapiModule from '../utils/createJsonapiModule'
import { config } from '../../../src/jsonapi-vuex'
import { jsonFormat as createJsonWidget1, normFormat as createNormWidget1 } from '../fixtures/widget1'

describe('postRelated', function () {
Expand Down Expand Up @@ -44,6 +45,24 @@ describe('postRelated', function () {
// Expect a post call to rel url, with rel payload, then get object to update store
expect(this.mockApi.history.post[0].url).to.equal('widget/1/relationships/widgets')
expect(this.mockApi.history.post[0].data).to.deep.equal(JSON.stringify(rel))
expect(this.mockApi.history.get[0].params).to.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
})

it('should make a post request without returning includes.', async function () {
this.mockApi.onPost().replyOnce(204)
this.mockApi.onGet().replyOnce(200, { data: jsonWidget1 })

const rel = { data: { type: 'widget', id: '2' } }
normWidget1['_jv']['relationships'] = { widgets: rel }

config.relatedIncludes = false

await jsonapiModule.actions.postRelated(stubContext, normWidget1)
// Expect a post call to rel url, with rel payload, then get object to update store
expect(this.mockApi.history.post[0].url).to.equal('widget/1/relationships/widgets')
expect(this.mockApi.history.post[0].data).to.deep.equal(JSON.stringify(rel))
expect(this.mockApi.history.get[0].params).to.not.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
})

Expand All @@ -60,6 +79,7 @@ describe('postRelated', function () {
expect(this.mockApi.history.post[0].data).to.deep.equal(JSON.stringify(rel1))
expect(this.mockApi.history.post[1].url).to.equal('widget/1/relationships/doohickeys')
expect(this.mockApi.history.post[1].data).to.deep.equal(JSON.stringify(rel2))
expect(this.mockApi.history.get[0].params).to.have.property('include')
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
// Only get the object once at end
expect(this.mockApi.history.get.length).to.equal(1)
Expand Down

0 comments on commit 62fd2ea

Please sign in to comment.