RemovePostEmotions should return deleted object

@mattwr18 I prefer (I believe it's even best practice) that a delete
mutation should return the deleted object. If you run the delete
mutation again, it should return `null` because there is no object like
that anymore. That way the client knows if a delete mutation has changed
any state in the database.

Also I fixed another bug in the resolver. If your graphql mutation looks
like this:

```gql
mutation {
  RemovePostEmotions(to:{ id:"p15"}, data:{emotion: angry}) {
    from {
      id
      name
    }
    to {
      id
      title
    }
    emotion
  }
}
```

Then you get errors because your resolver does not return the name for
the user or the title for the post anymore. Just use spread operator...
and it's fixed.
This commit is contained in:
Robert Schäfer 2019-08-08 23:51:26 +02:00
parent f3e545a913
commit 963cbbef32
6 changed files with 50 additions and 20 deletions

View File

@ -84,9 +84,9 @@ export default {
session.close() session.close()
const [emoted] = transactionRes.records.map(record => { const [emoted] = transactionRes.records.map(record => {
return { return {
from: { id: record.get('userFrom').properties.id }, from: { ...record.get('userFrom').properties },
to: { id: record.get('postTo').properties.id }, to: { ...record.get('postTo').properties },
emotion: record.get('emotedRelation').properties.emotion, ...record.get('emotedRelation').properties,
} }
}) })
return emoted return emoted
@ -98,16 +98,18 @@ export default {
const transactionRes = await session.run( const transactionRes = await session.run(
`MATCH (userFrom:User {id: $from})-[emotedRelation:EMOTED {emotion: $data.emotion}]->(postTo:Post {id: $to.id}) `MATCH (userFrom:User {id: $from})-[emotedRelation:EMOTED {emotion: $data.emotion}]->(postTo:Post {id: $to.id})
DELETE emotedRelation DELETE emotedRelation
RETURN userFrom RETURN userFrom, postTo`,
`,
{ from, to, data }, { from, to, data },
) )
session.close() session.close()
const [userFrom] = transactionRes.records.map(record => { const [emoted] = transactionRes.records.map(record => {
return record.get('userFrom') return {
from: { ...record.get('userFrom').properties },
to: { ...record.get('postTo').properties },
emotion: data.emotion,
}
}) })
if (!userFrom) throw new Error('Not Authorised!') return emoted
return Boolean(userFrom)
}, },
}, },
Query: { Query: {

View File

@ -588,7 +588,15 @@ describe('emotions', () => {
let removePostEmotionsVariables, postsEmotionsQueryVariables let removePostEmotionsVariables, postsEmotionsQueryVariables
const removePostEmotionsMutation = gql` const removePostEmotionsMutation = gql`
mutation($to: _PostInput!, $data: _EMOTEDInput!) { mutation($to: _PostInput!, $data: _EMOTEDInput!) {
RemovePostEmotions(to: $to, data: $data) RemovePostEmotions(to: $to, data: $data) {
from {
id
}
to {
id
}
emotion
}
} }
` `
beforeEach(async () => { beforeEach(async () => {
@ -616,21 +624,31 @@ describe('emotions', () => {
describe('authenticated', () => { describe('authenticated', () => {
describe('but not the emoter', () => { describe('but not the emoter', () => {
it('throws an authorization error', async () => { it('returns null if the emotion could not be found', async () => {
user = someUser user = someUser
const removePostEmotions = await postMutationAction( const removePostEmotions = await postMutationAction(
user, user,
removePostEmotionsMutation, removePostEmotionsMutation,
removePostEmotionsVariables, removePostEmotionsVariables,
) )
expect(removePostEmotions.errors[0]).toHaveProperty('message', 'Not Authorised!') expect(removePostEmotions).toEqual(
expect.objectContaining({ data: { RemovePostEmotions: null } }),
)
}) })
}) })
describe('as the emoter', () => { describe('as the emoter', () => {
it('removes an emotion from a post', async () => { it('removes an emotion from a post', async () => {
user = owner user = owner
const expected = { data: { RemovePostEmotions: true } } const expected = {
data: {
RemovePostEmotions: {
to: { id: postToEmote.id },
from: { id: user.id },
emotion: 'cry',
},
},
}
await expect( await expect(
postMutationAction(user, removePostEmotionsMutation, removePostEmotionsVariables), postMutationAction(user, removePostEmotionsMutation, removePostEmotionsVariables),
).resolves.toEqual(expect.objectContaining(expected)) ).resolves.toEqual(expect.objectContaining(expected))

View File

@ -92,7 +92,7 @@ type Mutation {
categoryIds: [ID] categoryIds: [ID]
): Post ): Post
AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED
RemovePostEmotions(to: _PostInput!, data: _EMOTEDInput!): Boolean! RemovePostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED
} }
type Query { type Query {

View File

@ -26,7 +26,6 @@ describe('Emotions.vue', () => {
.mockResolvedValueOnce({ .mockResolvedValueOnce({
data: { data: {
AddPostEmotions: { AddPostEmotions: {
from: { id: 'u176' },
to: { id: 'p143' }, to: { id: 'p143' },
data: { emotion: 'happy' }, data: { emotion: 'happy' },
}, },
@ -34,7 +33,11 @@ describe('Emotions.vue', () => {
}) })
.mockResolvedValueOnce({ .mockResolvedValueOnce({
data: { data: {
RemovePostEmotions: true, RemovePostEmotions: {
from: { id: 'u176' },
to: { id: 'p143' },
data: { emotion: 'happy' },
},
}, },
}), }),
query: jest.fn().mockResolvedValue({ query: jest.fn().mockResolvedValue({
@ -85,7 +88,7 @@ describe('Emotions.vue', () => {
it('sends the AddPostEmotionsMutation for an emotion when clicked', () => { it('sends the AddPostEmotionsMutation for an emotion when clicked', () => {
expectedParams = { expectedParams = {
mutation: PostMutations().AddPostEmotionsMutation, mutation: PostMutations().AddPostEmotionsMutation,
variables: { from: { id: 'u176' }, to: { id: 'p143' }, data: { emotion: 'funny' } }, variables: { to: { id: 'p143' }, data: { emotion: 'funny' } },
} }
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams)) expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
}) })
@ -106,7 +109,7 @@ describe('Emotions.vue', () => {
it('sends the RemovePostEmotionsMutation when a user clicks on an active emotion', () => { it('sends the RemovePostEmotionsMutation when a user clicks on an active emotion', () => {
expectedParams = { expectedParams = {
mutation: PostMutations().RemovePostEmotionsMutation, mutation: PostMutations().RemovePostEmotionsMutation,
variables: { from: { id: 'u176' }, to: { id: 'p143' }, data: { emotion: 'funny' } }, variables: { to: { id: 'p143' }, data: { emotion: 'funny' } },
} }
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams)) expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
}) })

View File

@ -56,7 +56,6 @@ export default {
? PostMutations().RemovePostEmotionsMutation ? PostMutations().RemovePostEmotionsMutation
: PostMutations().AddPostEmotionsMutation, : PostMutations().AddPostEmotionsMutation,
variables: { variables: {
from: { id: this.currentUser.id },
to: { id: this.post.id }, to: { id: this.post.id },
data: { emotion }, data: { emotion },
}, },

View File

@ -75,7 +75,15 @@ export default () => {
`, `,
RemovePostEmotionsMutation: gql` RemovePostEmotionsMutation: gql`
mutation($to: _PostInput!, $data: _EMOTEDInput!) { mutation($to: _PostInput!, $data: _EMOTEDInput!) {
RemovePostEmotions(to: $to, data: $data) RemovePostEmotions(to: $to, data: $data) {
emotion
from {
id
}
to {
id
}
}
} }
`, `,
} }