diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index eb792ecb8..d4775b235 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -2,18 +2,41 @@ import { neo4jgraphql } from 'neo4j-graphql-js' import { UserInputError } from 'apollo-server' const COMMENT_MIN_LENGTH = 1 +const NO_POST_ERR_MESSAGE = 'Comment cannot be created without a post!' + export default { Mutation: { CreateComment: async (object, params, context, resolveInfo) => { const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim() + const { postId } = params + // Adding relationship from comment to post by passing in the postId, + // but we do not want to create the comment with postId as an attribute + // because we use relationships for this. So, we are deleting it from params + // before comment creation. + delete params.postId if (!params.content || content.length < COMMENT_MIN_LENGTH) { throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`) } - const { postId } = params - const comment = await neo4jgraphql(object, params, context, resolveInfo, false) + if (!postId.trim()) { + throw new UserInputError(NO_POST_ERR_MESSAGE) + } const session = context.driver.session() + const postQueryRes = await session.run(` + MATCH (post:Post {id: $postId}) + RETURN post`, { + postId + } + ) + const [post] = postQueryRes.records.map(record => { + return record.get('post') + }) + + if (!post) { + throw new UserInputError(NO_POST_ERR_MESSAGE) + } + const comment = await neo4jgraphql(object, params, context, resolveInfo, false) await session.run(` MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}), (author:User {id: $userId}) diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index 9a54acd17..87a0df270 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -6,6 +6,8 @@ const factory = Factory() let client let createCommentVariables let createPostVariables +let createCommentVariablesSansPostId +let createCommentVariablesWithNonExistentPost beforeEach(async () => { await factory.create('User', { @@ -34,6 +36,13 @@ describe('CreateComment', () => { } } ` + const commentQueryForPostId = ` + query($content: String) { + Comment(content: $content) { + postId + } + } + ` describe('unauthenticated', () => { it('throws authorization error', async () => { createCommentVariables = { @@ -54,6 +63,12 @@ describe('CreateComment', () => { postId: 'p1', content: 'I\'m authorised to comment' } + createPostVariables = { + id: 'p1', + title: 'post to comment on', + content: 'please comment on me' + } + await client.request(createPostMutation, createPostVariables) }) it('creates a comment', async () => { @@ -67,12 +82,6 @@ describe('CreateComment', () => { }) it('assigns the authenticated user as author', async () => { - createPostVariables = { - id: 'p1', - title: 'post to comment on', - content: 'please comment on me' - } - await client.request(createPostMutation, createPostVariables) await client.request(createCommentMutation, createCommentVariables) const { User } = await client.request(`{ @@ -86,7 +95,7 @@ describe('CreateComment', () => { expect(User).toEqual([ { comments: [ { content: 'I\'m authorised to comment' } ] } ]) }) - it('throw an error if an empty string is sent as content', async () => { + it('throw an error if an empty string is sent from the editor as content', async () => { createCommentVariables = { postId: 'p1', content: '
' @@ -96,7 +105,7 @@ describe('CreateComment', () => { .rejects.toThrow('Comment must be at least 1 character long!') }) - it('throws an error if a comment does not contain a single character', async () => { + it('throws an error if a comment sent from the editor does not contain a single character', async () => { createCommentVariables = { postId: 'p1', content: '' @@ -105,5 +114,65 @@ describe('CreateComment', () => { await expect(client.request(createCommentMutation, createCommentVariables)) .rejects.toThrow('Comment must be at least 1 character long!') }) + + it('throws an error if postId is sent as an empty string', async () => { + createCommentVariables = { + postId: 'p1', + content: '' + } + + await expect(client.request(createCommentMutation, createCommentVariables)) + .rejects.toThrow('Comment must be at least 1 character long!') + }) + + it('throws an error if content is sent as an string of empty characters', async () => { + createCommentVariables = { + postId: 'p1', + content: ' ' + } + + await expect(client.request(createCommentMutation, createCommentVariables)) + .rejects.toThrow('Comment must be at least 1 character long!') + }) + + it('throws an error if postId is sent as an empty string', async () => { + createCommentVariablesSansPostId = { + postId: '', + content: 'this comment should not be created' + } + + await expect(client.request(createCommentMutation, createCommentVariablesSansPostId)) + .rejects.toThrow('Comment cannot be created without a post!') + }) + + it('throws an error if postId is sent as an string of empty characters', async () => { + createCommentVariablesSansPostId = { + postId: ' ', + content: 'this comment should not be created' + } + + await expect(client.request(createCommentMutation, createCommentVariablesSansPostId)) + .rejects.toThrow('Comment cannot be created without a post!') + }) + + it('throws an error if the post does not exist in the database', async () => { + createCommentVariablesWithNonExistentPost = { + postId: 'p2', + content: 'comment should not be created cause the post doesn\'t exist' + } + + await expect(client.request(createCommentMutation, createCommentVariablesWithNonExistentPost)) + .rejects.toThrow('Comment cannot be created without a post!') + }) + + it('does not create the comment with the postId as an attribute', async () => { + const commentQueryVariablesByContent = { + content: 'I\'m authorised to comment' + } + + await client.request(createCommentMutation, createCommentVariables) + const { Comment } = await client.request(commentQueryForPostId, commentQueryVariablesByContent) + expect(Comment).toEqual([{ postId: null }]) + }) }) })