From f7ef09acbf9e6927c08ed1739d40ee0a5fdd991b Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Sat, 18 May 2019 18:20:43 -0700 Subject: [PATCH 01/22] add UpdateComment mutation --- backend/src/resolvers/comments.js | 96 +++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 12 deletions(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index d4775b235..8023fb334 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -16,18 +16,22 @@ export default { delete params.postId if (!params.content || content.length < COMMENT_MIN_LENGTH) { - throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`) + throw new UserInputError( + `Comment must be at least ${COMMENT_MIN_LENGTH} character long!` + ) } if (!postId.trim()) { throw new UserInputError(NO_POST_ERR_MESSAGE) } const session = context.driver.session() - const postQueryRes = await session.run(` + const postQueryRes = await session.run( + ` MATCH (post:Post {id: $postId}) - RETURN post`, { - postId - } + RETURN post`, + { + postId + } ) const [post] = postQueryRes.records.map(record => { return record.get('post') @@ -36,20 +40,88 @@ export default { if (!post) { throw new UserInputError(NO_POST_ERR_MESSAGE) } - const comment = await neo4jgraphql(object, params, context, resolveInfo, false) + const comment = await neo4jgraphql( + object, + params, + context, + resolveInfo, + false + ) - await session.run(` + await session.run( + ` MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}), (author:User {id: $userId}) MERGE (post)<-[:COMMENTS]-(comment)<-[:WROTE]-(author) - RETURN post`, { - userId: context.user.id, - postId, - commentId: comment.id - } + RETURN post`, + { + userId: context.user.id, + postId, + commentId: comment.id + } ) session.close() return comment + }, + UpdateComment: async (object, params, context, resolveInfo) => { + // Strip element tags and remove leading/trailing white spaces from content + const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim() + const { id } = params + console.log(id) + // Check length of content + if (!params.content || content.length < COMMENT_MIN_LENGTH) { + throw new UserInputError( + `Comment must be at least ${COMMENT_MIN_LENGTH} character long!` + ) + } + + // Check if comment exists + const session = context.driver.session() + const commentQueryRes = await session.run( + ` + MATCH (comment: COMMENT) + WHERE id(comment)=$id + RETURN comment`, + { + id + } + ) + console.log(id) + console.log(commentQueryRes) + // Destructure content from session results array + const [comment] = commentQueryRes.records.map(record => { + console.log(record.get('comment')) + return record.get('comment') + }) + + // Send error message if cannot find a matching comment. + // if (!comment) { + // throw new UserInputError(NO_COMMENT_ERR_MESSAGE) + // } + + // Update comment. + // const commentRev = await neo4jgraphql( + // object, + // params, + // context, + // resolveInfo, + // false + // ) + + // await session.run( + // ` + // MATCH (comment:Comment) + // WHERE id(comment)=$id, + // SET comment.content = $content + // `, + // { + // id, + // content + // } + // ) + session.close() + + // return commentRev } } } From 7ddbab83e98e09cfac41e3ed18ea2fb5eb468faa Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Sat, 18 May 2019 23:32:24 -0700 Subject: [PATCH 02/22] 552-update_comment --- backend/src/resolvers/comments.js | 54 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 8023fb334..72d2f96fb 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -40,6 +40,7 @@ export default { if (!post) { throw new UserInputError(NO_POST_ERR_MESSAGE) } + const comment = await neo4jgraphql( object, params, @@ -67,7 +68,6 @@ export default { // Strip element tags and remove leading/trailing white spaces from content const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim() const { id } = params - console.log(id) // Check length of content if (!params.content || content.length < COMMENT_MIN_LENGTH) { throw new UserInputError( @@ -79,49 +79,47 @@ export default { const session = context.driver.session() const commentQueryRes = await session.run( ` - MATCH (comment: COMMENT) - WHERE id(comment)=$id + MATCH (comment: Comment { id:$id}) RETURN comment`, { id } ) - console.log(id) - console.log(commentQueryRes) + // Destructure content from session results array const [comment] = commentQueryRes.records.map(record => { - console.log(record.get('comment')) + const a = record.get('comment') + console.log(a) return record.get('comment') }) // Send error message if cannot find a matching comment. - // if (!comment) { - // throw new UserInputError(NO_COMMENT_ERR_MESSAGE) - // } + if (!comment) { + throw new UserInputError(NO_COMMENT_ERR_MESSAGE) + } // Update comment. - // const commentRev = await neo4jgraphql( - // object, - // params, - // context, - // resolveInfo, - // false - // ) + const commentRev = await neo4jgraphql( + object, + params, + context, + resolveInfo, + false + ) - // await session.run( - // ` - // MATCH (comment:Comment) - // WHERE id(comment)=$id, - // SET comment.content = $content - // `, - // { - // id, - // content - // } - // ) + await session.run( + ` + MATCH (comment: Comment { id:$id}) + SET comment.content = 'bbb' + `, + { + id, + content + } + ) session.close() - // return commentRev + return commentRev } } } From 3fe8e9a2886e3f5a1872b4e3612b2ad70aa639de Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Sat, 18 May 2019 23:42:17 -0700 Subject: [PATCH 03/22] 552-update_comment --- backend/src/resolvers/comments.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 72d2f96fb..6dea8e51b 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -88,8 +88,6 @@ export default { // Destructure content from session results array const [comment] = commentQueryRes.records.map(record => { - const a = record.get('comment') - console.log(a) return record.get('comment') }) @@ -110,7 +108,7 @@ export default { await session.run( ` MATCH (comment: Comment { id:$id}) - SET comment.content = 'bbb' + SET comment.content = $content `, { id, From 8a8ed5131e010e75b156b8a80cefe1618dcd9072 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Fri, 24 May 2019 08:03:39 -0700 Subject: [PATCH 04/22] refactor backend and add UI --- backend/src/middleware/validation/index.js | 21 ++- backend/src/resolvers/comments.js | 59 --------- webapp/components/Comment.vue | 29 ++++- webapp/components/ContentMenu.vue | 2 +- .../components/comments/CommentList/index.vue | 20 +-- .../comments/EditCommentForm/index.vue | 122 ++++++++++++++++++ 6 files changed, 170 insertions(+), 83 deletions(-) create mode 100644 webapp/components/comments/EditCommentForm/index.vue diff --git a/backend/src/middleware/validation/index.js b/backend/src/middleware/validation/index.js index de9be72e9..faf95beaf 100644 --- a/backend/src/middleware/validation/index.js +++ b/backend/src/middleware/validation/index.js @@ -22,10 +22,29 @@ const validateUrl = async (resolve, root, args, context, info) => { } } +const validateComment = async (resolve, root, args, context, info) => { + const COMMENT_MIN_LENGTH = 1 + const content = args.content.replace(/<(?:.|\n)*?>/gm, '').trim() + if (!args.content || content.length < COMMENT_MIN_LENGTH) { + throw new UserInputError( + `Comment must be at least ${COMMENT_MIN_LENGTH} character long!` + ) + } + const NO_POST_ERR_MESSAGE = 'Comment cannot be created without a post!' + const { postId } = args + if (!postId) { + throw new UserInputError(NO_POST_ERR_MESSAGE) + } + + return await resolve(root, args, context, info) +} + export default { Mutation: { CreateUser: validateUsername, UpdateUser: validateUsername, - CreateSocialMedia: validateUrl + CreateSocialMedia: validateUrl, + CreateComment: validateComment, + UpdateComment: validateComment } } diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 6dea8e51b..f3cfea378 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -1,13 +1,9 @@ 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 @@ -15,15 +11,6 @@ export default { // 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!` - ) - } - if (!postId.trim()) { - throw new UserInputError(NO_POST_ERR_MESSAGE) - } - const session = context.driver.session() const postQueryRes = await session.run( ` @@ -65,38 +52,6 @@ export default { return comment }, UpdateComment: async (object, params, context, resolveInfo) => { - // Strip element tags and remove leading/trailing white spaces from content - const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim() - const { id } = params - // Check length of content - if (!params.content || content.length < COMMENT_MIN_LENGTH) { - throw new UserInputError( - `Comment must be at least ${COMMENT_MIN_LENGTH} character long!` - ) - } - - // Check if comment exists - const session = context.driver.session() - const commentQueryRes = await session.run( - ` - MATCH (comment: Comment { id:$id}) - RETURN comment`, - { - id - } - ) - - // Destructure content from session results array - const [comment] = commentQueryRes.records.map(record => { - return record.get('comment') - }) - - // Send error message if cannot find a matching comment. - if (!comment) { - throw new UserInputError(NO_COMMENT_ERR_MESSAGE) - } - - // Update comment. const commentRev = await neo4jgraphql( object, params, @@ -104,20 +59,6 @@ export default { resolveInfo, false ) - - await session.run( - ` - MATCH (comment: Comment { id:$id}) - SET comment.content = $content - `, - { - id, - content - } - ) - session.close() - - return commentRev } } } diff --git a/webapp/components/Comment.vue b/webapp/components/Comment.vue index 13edc9c0d..906575880 100644 --- a/webapp/components/Comment.vue +++ b/webapp/components/Comment.vue @@ -22,15 +22,20 @@ :resource="comment" style="float-right" :is-owner="isAuthor(author.id)" + v-on:showEditCommentMenu="editCommentMenu" /> - -
+ +
+ +
+
@@ -39,13 +44,22 @@ import { mapGetters } from 'vuex' import HcUser from '~/components/User' import ContentMenu from '~/components/ContentMenu' +import HcEditCommentForm from '~/components/comments/EditCommentForm' +import gql from 'graphql-tag' export default { components: { HcUser, - ContentMenu + ContentMenu, + HcEditCommentForm + }, + data() { + return { + openEditCommentMenu: false + } }, props: { + post: { type: Object, default: () => {} }, comment: { type: Object, default() { @@ -69,6 +83,9 @@ export default { methods: { isAuthor(id) { return this.user.id === id + }, + editCommentMenu(showMenu) { + this.openEditCommentMenu = showMenu } } } diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu.vue index 29473d6b2..5f4cd54e7 100644 --- a/webapp/components/ContentMenu.vue +++ b/webapp/components/ContentMenu.vue @@ -90,7 +90,7 @@ export default { name: this.$t(`comment.edit`), callback: () => { /* eslint-disable-next-line no-console */ - console.log('EDIT COMMENT') + this.$emit('showEditCommentMenu', true) }, icon: 'edit' }) diff --git a/webapp/components/comments/CommentList/index.vue b/webapp/components/comments/CommentList/index.vue index 57b720087..5a682bba6 100644 --- a/webapp/components/comments/CommentList/index.vue +++ b/webapp/components/comments/CommentList/index.vue @@ -12,23 +12,11 @@ >{{ comments.length }}  Comments - -
- + +
+
- +
From 8c7009097a274c04fa22631429b1c7f57c90cad4 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Fri, 24 May 2019 08:22:56 -0700 Subject: [PATCH 05/22] 552-update_comment --- webapp/components/comments/EditCommentForm/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/webapp/components/comments/EditCommentForm/index.vue b/webapp/components/comments/EditCommentForm/index.vue index 216e47604..562b80b48 100644 --- a/webapp/components/comments/EditCommentForm/index.vue +++ b/webapp/components/comments/EditCommentForm/index.vue @@ -97,7 +97,6 @@ export default { this.disabled = false this.$emit('showEditCommentMenu', false) }) - //@Todo close edit comment window .catch(err => { this.$toast.error(err.message) }) From a5f6390f97a2b9e9ec614bc43e4b023b9540e35e Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Thu, 30 May 2019 15:47:55 -0700 Subject: [PATCH 06/22] 552-update_comment --- backend/src/middleware/validation/index.js | 7 ++++--- backend/src/resolvers/comments.js | 10 +++------- webapp/package.json | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/backend/src/middleware/validation/index.js b/backend/src/middleware/validation/index.js index faf95beaf..a7238ab03 100644 --- a/backend/src/middleware/validation/index.js +++ b/backend/src/middleware/validation/index.js @@ -7,7 +7,9 @@ const validateUsername = async (resolve, root, args, context, info) => { /* eslint-disable-next-line no-return-await */ return await resolve(root, args, context, info) } else { - throw new UserInputError(`Username must be at least ${USERNAME_MIN_LENGTH} characters long!`) + throw new UserInputError( + `Username must be at least ${USERNAME_MIN_LENGTH} characters long!` + ) } } @@ -35,8 +37,7 @@ const validateComment = async (resolve, root, args, context, info) => { if (!postId) { throw new UserInputError(NO_POST_ERR_MESSAGE) } - - return await resolve(root, args, context, info) + return resolve(root, args, context, info) } export default { diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index f3cfea378..2515ba36a 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -1,6 +1,8 @@ import { neo4jgraphql } from 'neo4j-graphql-js' import { UserInputError } from 'apollo-server' +const NO_POST_ERR_MESSAGE = 'Comment cannot be created without a post!' + export default { Mutation: { CreateComment: async (object, params, context, resolveInfo) => { @@ -52,13 +54,7 @@ export default { return comment }, UpdateComment: async (object, params, context, resolveInfo) => { - const commentRev = await neo4jgraphql( - object, - params, - context, - resolveInfo, - false - ) + await neo4jgraphql(object, params, context, resolveInfo, false) } } } diff --git a/webapp/package.json b/webapp/package.json index a3e8b44b9..62007112d 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -104,4 +104,4 @@ "vue-jest": "~3.0.4", "vue-svg-loader": "~0.12.0" } -} \ No newline at end of file +} From 788979eedfd82cda726ba2d69b821c43c98fd6bf Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Wed, 5 Jun 2019 18:12:22 -0700 Subject: [PATCH 07/22] add update comment jest test --- backend/src/middleware/validation/index.js | 3 ++- backend/src/resolvers/comments.spec.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/src/middleware/validation/index.js b/backend/src/middleware/validation/index.js index a7238ab03..2da25a605 100644 --- a/backend/src/middleware/validation/index.js +++ b/backend/src/middleware/validation/index.js @@ -37,7 +37,8 @@ const validateComment = async (resolve, root, args, context, info) => { if (!postId) { throw new UserInputError(NO_POST_ERR_MESSAGE) } - return resolve(root, args, context, info) + /* eslint-disable-next-line no-return-await */ + return await resolve(root, args, context, info) } export default { diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index 87a0df270..952850759 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -175,4 +175,24 @@ describe('CreateComment', () => { expect(Comment).toEqual([{ postId: null }]) }) }) + +describe('UpdateComment', () => { + const updateCommentMutation = ` + mutation($postId: ID, $content: String!, $id: ID!) { + UpdateComment(postId: $postId, content: $content, id: $id) { + id + content + } + } + ` + updateCommentVariables = { + postId: 'p1', + content: 'Comment is updated', + id: 'c8' + } + + it('updates a comment', async () = { + + }) +}) }) From 8d4ed065c7c5984e9a764ac4ac976cf2c7030751 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Wed, 5 Jun 2019 18:42:17 -0700 Subject: [PATCH 08/22] add post.comment.updated --- webapp/components/comments/EditCommentForm/index.vue | 2 +- webapp/locales/en.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/webapp/components/comments/EditCommentForm/index.vue b/webapp/components/comments/EditCommentForm/index.vue index 562b80b48..5a28062a9 100644 --- a/webapp/components/comments/EditCommentForm/index.vue +++ b/webapp/components/comments/EditCommentForm/index.vue @@ -93,7 +93,7 @@ export default { .then(res => { this.loading = false this.$root.$emit('refetchPostComments') - this.$toast.success(this.$t('post.comment.submitted')) + this.$toast.success(this.$t('post.comment.updated')) this.disabled = false this.$emit('showEditCommentMenu', false) }) diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 186b31d41..975917c78 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -145,7 +145,8 @@ }, "comment": { "submit": "Comment", - "submitted": "Comment Submitted" + "submitted": "Comment Submitted", + "updated": "Comment Updated" } }, "quotes": { From 0401e3b92947ae8319f4b6238e2da0de0edd9359 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Thu, 6 Jun 2019 15:58:32 -0700 Subject: [PATCH 09/22] add update comment to comments.spec --- backend/src/resolvers/comments.spec.js | 59 ++++++++++++++++---------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index 952850759..7784a889f 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -20,7 +20,7 @@ afterEach(async () => { await factory.cleanDatabase() }) -describe('CreateComment', () => { +describe('Comment Functionality', () => { const createCommentMutation = ` mutation($postId: ID, $content: String!) { CreateComment(postId: $postId, content: $content) { @@ -78,7 +78,37 @@ describe('CreateComment', () => { } } - await expect(client.request(createCommentMutation, createCommentVariables)).resolves.toMatchObject(expected) + await expect( + client.request(createCommentMutation, createCommentVariables) + ).resolves.toMatchObject(expected) + }) + + it('updates a comment', async () => { + await client.request(createCommentMutation, createCommentVariables) + + const updateCommentMutation = ` + mutation($postId: ID, $content: String!, $id: ID!) { + UpdateComment(postId: $postId, content: $content, id: $id) { + id + content + } + } + ` + let updateCommentVariables = { + postId: 'p1', + content: 'Comment is updated', + id: 'c8' + } + + const expected = { + UpdateComment: { + content: 'Comment is updated' + } + } + + await expect( + client.request(updateCommentMutation, updateCommentVariables) + ).resolves.toMatchObject(expected) }) it('assigns the authenticated user as author', async () => { @@ -171,28 +201,11 @@ describe('CreateComment', () => { } await client.request(createCommentMutation, createCommentVariables) - const { Comment } = await client.request(commentQueryForPostId, commentQueryVariablesByContent) + const { Comment } = await client.request( + commentQueryForPostId, + commentQueryVariablesByContent + ) expect(Comment).toEqual([{ postId: null }]) }) }) - -describe('UpdateComment', () => { - const updateCommentMutation = ` - mutation($postId: ID, $content: String!, $id: ID!) { - UpdateComment(postId: $postId, content: $content, id: $id) { - id - content - } - } - ` - updateCommentVariables = { - postId: 'p1', - content: 'Comment is updated', - id: 'c8' - } - - it('updates a comment', async () = { - - }) -}) }) From ae9d508ada81ded368cd6adf6463b30d0ea8d410 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Sat, 8 Jun 2019 15:59:15 -0700 Subject: [PATCH 10/22] Revise "updated":"Changes Saved" --- webapp/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 50a7b497d..521f681c0 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -154,7 +154,7 @@ "comment": { "submit": "Comment", "submitted": "Comment Submitted", - "updated": "Comment Updated" + "updated": "Changes Saved" } }, "comment": { From 3cc05c0916f66fc7290fe63c62f527e5b7db6752 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Thu, 13 Jun 2019 13:00:20 -0700 Subject: [PATCH 11/22] add backend managecomments tests --- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/middleware/validation/index.js | 10 +- backend/src/schema/resolvers/comments.js | 9 + backend/src/schema/resolvers/comments.spec.js | 199 ++++++++++++------ 4 files changed, 147 insertions(+), 72 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index bc9b4c525..83f5cd29b 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -113,6 +113,7 @@ const permissions = shield({ enable: isModerator, disable: isModerator, CreateComment: isAuthenticated, + UpdateComment: isAuthor, DeleteComment: isAuthor, // CreateUser: allow, }, diff --git a/backend/src/middleware/validation/index.js b/backend/src/middleware/validation/index.js index ec69b9a3a..e296bb866 100644 --- a/backend/src/middleware/validation/index.js +++ b/backend/src/middleware/validation/index.js @@ -22,17 +22,12 @@ const validateUrl = async (resolve, root, args, context, info) => { } } -const validateComment = async (resolve, root, args, context, info) => { +const validateUpdateComment = async (resolve, root, args, context, info) => { const COMMENT_MIN_LENGTH = 1 const content = args.content.replace(/<(?:.|\n)*?>/gm, '').trim() if (!args.content || content.length < COMMENT_MIN_LENGTH) { throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`) } - const NO_POST_ERR_MESSAGE = 'Comment cannot be created without a post!' - const { postId } = args - if (!postId) { - throw new UserInputError(NO_POST_ERR_MESSAGE) - } /* eslint-disable-next-line no-return-await */ return await resolve(root, args, context, info) } @@ -42,7 +37,6 @@ export default { CreateUser: validateUsername, UpdateUser: validateUsername, CreateSocialMedia: validateUrl, - CreateComment: validateComment, - UpdateComment: validateComment, + UpdateComment: validateUpdateComment, }, } diff --git a/backend/src/schema/resolvers/comments.js b/backend/src/schema/resolvers/comments.js index f28ef2792..8bca3bb98 100644 --- a/backend/src/schema/resolvers/comments.js +++ b/backend/src/schema/resolvers/comments.js @@ -1,11 +1,13 @@ 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 @@ -13,6 +15,13 @@ export default { // 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!`) + } + if (!postId.trim()) { + throw new UserInputError(NO_POST_ERR_MESSAGE) + } + const session = context.driver.session() const postQueryRes = await session.run( ` diff --git a/backend/src/schema/resolvers/comments.spec.js b/backend/src/schema/resolvers/comments.spec.js index 55b946bb9..00d139a62 100644 --- a/backend/src/schema/resolvers/comments.spec.js +++ b/backend/src/schema/resolvers/comments.spec.js @@ -9,9 +9,10 @@ let createCommentVariables let createPostVariables let createCommentVariablesSansPostId let createCommentVariablesWithNonExistentPost +let asAuthor beforeEach(async () => { - await factory.create('User', { + asAuthor = await factory.create('User', { email: 'test@example.org', password: '1234', }) @@ -211,22 +212,9 @@ describe('CreateComment', () => { }) }) -describe('DeleteComment', () => { - const deleteCommentMutation = gql` - mutation($id: ID!) { - DeleteComment(id: $id) { - id - } - } - ` - - let deleteCommentVariables = { - id: 'c1', - } - +describe('ManageComments', () => { beforeEach(async () => { - const asAuthor = Factory() - await asAuthor.create('User', { + asAuthor = await factory.create('User', { email: 'author@example.org', password: '1234', }) @@ -245,55 +233,138 @@ describe('DeleteComment', () => { }) }) - describe('unauthenticated', () => { - it('throws authorization error', async () => { - client = new GraphQLClient(host) - await expect(client.request(deleteCommentMutation, deleteCommentVariables)).rejects.toThrow( - 'Not Authorised', - ) - }) - }) - - describe('authenticated but not the author', () => { - beforeEach(async () => { - let headers - headers = await login({ - email: 'test@example.org', - password: '1234', - }) - client = new GraphQLClient(host, { - headers, - }) - }) - - it('throws authorization error', async () => { - await expect(client.request(deleteCommentMutation, deleteCommentVariables)).rejects.toThrow( - 'Not Authorised', - ) - }) - }) - - describe('authenticated as author', () => { - beforeEach(async () => { - let headers - headers = await login({ - email: 'author@example.org', - password: '1234', - }) - client = new GraphQLClient(host, { - headers, - }) - }) - - it('deletes the comment', async () => { - const expected = { - DeleteComment: { - id: 'c1', - }, + describe('UpdateComment', () => { + const updateCommentMutation = gql` + mutation($content: String!, $id: ID!) { + UpdateComment(content: $content, id: $id) { + id + content + } } - await expect(client.request(deleteCommentMutation, deleteCommentVariables)).resolves.toEqual( - expected, - ) + ` + + let updateCommentVariables = { + id: 'c1', + content: 'The comment is updated', + } + + describe('unauthenticated', () => { + it('throws authorization error', async () => { + client = new GraphQLClient(host) + await expect(client.request(updateCommentMutation, updateCommentVariables)).rejects.toThrow( + 'Not Authorised', + ) + }) + }) + + describe('authenticated but not the author', () => { + beforeEach(async () => { + let headers + headers = await login({ + email: 'test@example.org', + password: '1234', + }) + client = new GraphQLClient(host, { + headers, + }) + }) + + it('throws authorization error', async () => { + await expect(client.request(updateCommentMutation, updateCommentVariables)).rejects.toThrow( + 'Not Authorised', + ) + }) + }) + + describe('authenticated as author', () => { + beforeEach(async () => { + let headers + headers = await login({ + email: 'author@example.org', + password: '1234', + }) + client = new GraphQLClient(host, { + headers, + }) + }) + + it('updates the comment', async () => { + const expected = { + UpdateComment: { + id: 'c1', + content: 'The comment is updated', + }, + } + await expect( + client.request(updateCommentMutation, updateCommentVariables), + ).resolves.toEqual(expected) + }) + }) + }) + + describe('DeleteComment', () => { + const deleteCommentMutation = gql` + mutation($id: ID!) { + DeleteComment(id: $id) { + id + } + } + ` + + let deleteCommentVariables = { + id: 'c1', + } + + describe('unauthenticated', () => { + it('throws authorization error', async () => { + client = new GraphQLClient(host) + await expect(client.request(deleteCommentMutation, deleteCommentVariables)).rejects.toThrow( + 'Not Authorised', + ) + }) + }) + + describe('authenticated but not the author', () => { + beforeEach(async () => { + let headers + headers = await login({ + email: 'test@example.org', + password: '1234', + }) + client = new GraphQLClient(host, { + headers, + }) + }) + + it('throws authorization error', async () => { + await expect(client.request(deleteCommentMutation, deleteCommentVariables)).rejects.toThrow( + 'Not Authorised', + ) + }) + }) + + describe('authenticated as author', () => { + beforeEach(async () => { + let headers + headers = await login({ + email: 'author@example.org', + password: '1234', + }) + client = new GraphQLClient(host, { + headers, + }) + }) + + it('deletes the comment', async () => { + const expected = { + DeleteComment: { + id: 'c1', + }, + } + await expect( + client.request(deleteCommentMutation, deleteCommentVariables), + ).resolves.toEqual(expected) + }) }) }) }) From 912b94d43c829622fb637fa0318d0675fd992fb8 Mon Sep 17 00:00:00 2001 From: ALau2088 Date: Thu, 27 Jun 2019 10:59:53 -0700 Subject: [PATCH 12/22] add EditCommentForm spec.js --- backend/src/schema/resolvers/comments.js | 3 -- webapp/components/Comment.vue | 8 +-- webapp/components/ContentMenu.vue | 4 +- .../components/comments/CommentList/index.vue | 11 ++-- .../comments/EditCommentForm/index.vue | 50 +++++++++---------- 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/backend/src/schema/resolvers/comments.js b/backend/src/schema/resolvers/comments.js index be257d912..d2e296596 100644 --- a/backend/src/schema/resolvers/comments.js +++ b/backend/src/schema/resolvers/comments.js @@ -74,9 +74,6 @@ export default { session.close() return commentReturnedWithAuthor }, - UpdateComment: async (object, params, context, resolveInfo) => { - await neo4jgraphql(object, params, context, resolveInfo, false) - }, DeleteComment: async (object, params, context, resolveInfo) => { const comment = await neo4jgraphql(object, params, context, resolveInfo, false) diff --git a/webapp/components/Comment.vue b/webapp/components/Comment.vue index a119328f1..a134787ff 100644 --- a/webapp/components/Comment.vue +++ b/webapp/components/Comment.vue @@ -1,13 +1,13 @@ diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu.vue index 8f5fe1eff..cb164678a 100644 --- a/webapp/components/ContentMenu.vue +++ b/webapp/components/ContentMenu.vue @@ -3,7 +3,7 @@ @@ -16,7 +16,7 @@ :parents="item.parents" @click.stop.prevent="openItem(item.route, toggleMenu)" > - + {{ item.route.name }} diff --git a/webapp/components/comments/CommentList/index.vue b/webapp/components/comments/CommentList/index.vue index 8f1cbc3d0..d1c91fef0 100644 --- a/webapp/components/comments/CommentList/index.vue +++ b/webapp/components/comments/CommentList/index.vue @@ -2,17 +2,20 @@

- + {{ comments.length }}  Comments + > + {{ comments.length }} + +   Comments

- +
- +
From c7dc2f6a5c3f6bf09722260853b9986b7c881339 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Mon, 15 Jul 2019 19:09:33 -0300 Subject: [PATCH 13/22] Hide CommentForm when an edit is in progress - Follow @Tirokk PR review --- webapp/components/Comment.vue | 40 ++++++++++--------- .../components/comments/CommentForm/index.vue | 8 +++- .../components/comments/CommentForm/spec.js | 1 + .../comments/EditCommentForm/index.vue | 5 +++ webapp/store/editor.js | 7 ++++ 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/webapp/components/Comment.vue b/webapp/components/Comment.vue index f0155afa8..1fdfad7cf 100644 --- a/webapp/components/Comment.vue +++ b/webapp/components/Comment.vue @@ -35,24 +35,22 @@ @showEditCommentMenu="editCommentMenu" />
-
- -
-
- - {{ $t('comment.show.less') }} - +
+
+ + @@ -61,7 +59,7 @@