diff --git a/backend/src/middleware/handleNotifications/handleNotifications.js b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js similarity index 80% rename from backend/src/middleware/handleNotifications/handleNotifications.js rename to backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js index cbb305fe5..d04eeeece 100644 --- a/backend/src/middleware/handleNotifications/handleNotifications.js +++ b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js @@ -1,6 +1,4 @@ -import { - UserInputError -} from 'apollo-server' +import { UserInputError } from 'apollo-server' import extractMentionedUsers from './notifications/extractMentionedUsers' import extractHashtags from './hashtags/extractHashtags' @@ -9,8 +7,8 @@ const notifyUsers = async (label, id, idsOfUsers, reason, context) => { // Done here, because Neode validation is not working. const reasonsAllowed = ['mentioned_in_post', 'mentioned_in_comment', 'comment_on_your_post'] - if (!(reasonsAllowed.includes(reason))) { - throw new UserInputError("Notification reason is not allowed!") + if (!reasonsAllowed.includes(reason)) { + throw new UserInputError('Notification reason is not allowed!') } const session = context.driver.session() @@ -81,8 +79,10 @@ const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo const post = await resolve(root, args, context, resolveInfo) - await notifyUsers('Post', post.id, idsOfUsers, 'mentioned_in_post', context) - await updateHashtagsOfPost(post.id, hashtags, context) + if (post) { + await notifyUsers('Post', post.id, idsOfUsers, 'mentioned_in_post', context) + await updateHashtagsOfPost(post.id, hashtags, context) + } return post } @@ -91,7 +91,9 @@ const handleContentDataOfComment = async (resolve, root, args, context, resolveI const idsOfUsers = extractMentionedUsers(args.content) const comment = await resolve(root, args, context, resolveInfo) - await notifyUsers('Comment', comment.id, idsOfUsers, 'mentioned_in_comment', context) + if (comment) { + await notifyUsers('Comment', comment.id, idsOfUsers, 'mentioned_in_comment', context) + } return comment } @@ -100,20 +102,22 @@ const handleCreateComment = async (resolve, root, args, context, resolveInfo) => // removes classes from the content const comment = await handleContentDataOfComment(resolve, root, args, context, resolveInfo) - const session = context.driver.session() - const cypherFindUser = ` + if (comment) { + const session = context.driver.session() + const cypherFindUser = ` MATCH (user: User)-[:WROTE]->(:Post)<-[:COMMENTS]-(:Comment { id: $commentId }) RETURN user { .id } ` - const result = await session.run(cypherFindUser, { - commentId: comment.id, - }) - session.close() - const [userWrotePost] = await result.records.map(record => { - return record.get('user') - }) - if (context.user.id !== userWrotePost.id) { - await notifyUsers('Comment', comment.id, [userWrotePost.id], 'comment_on_your_post', context) + const result = await session.run(cypherFindUser, { + commentId: comment.id, + }) + session.close() + const [postAuthor] = await result.records.map(record => { + return record.get('user') + }) + if (context.user.id !== postAuthor.id) { + await notifyUsers('Comment', comment.id, [postAuthor.id], 'comment_on_your_post', context) + } } return comment @@ -126,4 +130,4 @@ export default { CreateComment: handleCreateComment, UpdateComment: handleContentDataOfComment, }, -} \ No newline at end of file +} diff --git a/backend/src/middleware/handleNotifications/handleNotifications.spec.js b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js similarity index 79% rename from backend/src/middleware/handleNotifications/handleNotifications.spec.js rename to backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js index 205c1ecb0..cb6aa9844 100644 --- a/backend/src/middleware/handleNotifications/handleNotifications.spec.js +++ b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js @@ -1,14 +1,7 @@ -import { - gql -} from '../../jest/helpers' +import { gql } from '../../jest/helpers' import Factory from '../../seed/factories' -import { - createTestClient -} from 'apollo-server-testing' -import { - neode, - getDriver -} from '../../bootstrap/neo4j' +import { createTestClient } from 'apollo-server-testing' +import { neode, getDriver } from '../../bootstrap/neo4j' import createServer from '../../server' const factory = Factory() @@ -51,7 +44,7 @@ afterEach(async () => { }) describe('notifications', () => { - const notificationQuery = gql ` + const notificationQuery = gql` query($read: Boolean) { currentUser { notifications(read: $read, orderBy: createdAt_desc) { @@ -74,6 +67,30 @@ describe('notifications', () => { }) describe('given another user', () => { + let title + let content + const createPostAction = async () => { + const createPostMutation = gql` + mutation($id: ID, $title: String!, $content: String!) { + CreatePost(id: $id, title: $title, content: $content) { + id + title + content + } + } + ` + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createPostMutation, + variables: { + id: 'p47', + title, + content, + }, + }) + authenticatedUser = await user.toJson() + } + let postAuthor beforeEach(async () => { postAuthor = await instance.create('User', { @@ -83,54 +100,42 @@ describe('notifications', () => { }) }) - describe('who mentions me in a post', () => { - const title = 'Mentioning Al Capone' - const content = + describe('comments on my post', () => { + title = 'My post' + content = 'My content' + + // it('sends me a notification', async () => { + // await createPostAction() + // XXX + // }) + }) + + describe('mentions me in a post', () => { + title = 'Mentioning Al Capone' + content = 'Hey @al-capone how do you do?' - const createPostAction = async () => { - const createPostMutation = gql ` - mutation($id: ID, $title: String!, $content: String!) { - CreatePost(id: $id, title: $title, content: $content) { - id - title - content - } - } - ` - authenticatedUser = await postAuthor.toJson() - await mutate({ - mutation: createPostMutation, - variables: { - id: 'p47', - title, - content, - }, - }) - authenticatedUser = await user.toJson() - } - - it.only('sends you a notification', async () => { + it('sends you a notification', async () => { await createPostAction() const expectedContent = 'Hey @al-capone how do you do?' const expected = expect.objectContaining({ data: { currentUser: { - notifications: [{ - read: false, - reason: 'mentioned_in_post', - post: { - content: expectedContent, + notifications: [ + { + read: false, + reason: 'mentioned_in_post', + post: { + content: expectedContent, + }, + comment: null, }, - comment: null, - }, ], + ], }, }, }) - const { - query - } = createTestClient(server) + const { query } = createTestClient(server) await expect( query({ query: notificationQuery, @@ -157,7 +162,7 @@ describe('notifications', () => { @al-capone ` - const updatePostMutation = gql ` + const updatePostMutation = gql` mutation($id: ID!, $title: String!, $content: String!) { UpdatePost(id: $id, content: $content, title: $title) { title @@ -185,7 +190,8 @@ describe('notifications', () => { const expected = expect.objectContaining({ data: { currentUser: { - notifications: [{ + notifications: [ + { read: false, reason: 'mentioned_in_post', post: { @@ -230,9 +236,7 @@ describe('notifications', () => { }, }, }) - const { - query - } = createTestClient(server) + const { query } = createTestClient(server) await expect( query({ query: notificationQuery, @@ -247,7 +251,7 @@ describe('notifications', () => { describe('but the author of the post blocked me and a mentioner mentions me in a comment', () => { const createCommentOnPostAction = async () => { await createPostAction() - const createCommentMutation = gql ` + const createCommentMutation = gql` mutation($id: ID, $postId: ID!, $commentContent: String!) { CreateComment(id: $id, postId: $postId, content: $commentContent) { id @@ -261,7 +265,8 @@ describe('notifications', () => { variables: { id: 'c47', postId: 'p47', - commentContent: 'One mention of me with .', + commentContent: + 'One mention of me with .', }, }) authenticatedUser = await user.toJson() @@ -288,9 +293,7 @@ describe('notifications', () => { }, }, }) - const { - query - } = createTestClient(server) + const { query } = createTestClient(server) await expect( query({ query: notificationQuery, @@ -311,7 +314,7 @@ describe('Hashtags', () => { const postTitle = 'Two Hashtags' const postContent = '

Hey Dude, #Democracy should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone.

' - const postWithHastagsQuery = gql ` + const postWithHastagsQuery = gql` query($id: ID) { Post(id: $id) { tags { @@ -323,7 +326,7 @@ describe('Hashtags', () => { const postWithHastagsVariables = { id: postId, } - const createPostMutation = gql ` + const createPostMutation = gql` mutation($postId: ID, $postTitle: String!, $postContent: String!) { CreatePost(id: $postId, title: $postTitle, content: $postContent) { id @@ -351,11 +354,14 @@ describe('Hashtags', () => { }) it('both Hashtags are created with the "id" set to their "name"', async () => { - const expected = [{ - id: 'Democracy' - }, { - id: 'Liberty' - }] + const expected = [ + { + id: 'Democracy', + }, + { + id: 'Liberty', + }, + ] await expect( query({ query: postWithHastagsQuery, @@ -364,9 +370,11 @@ describe('Hashtags', () => { ).resolves.toEqual( expect.objectContaining({ data: { - Post: [{ - tags: expect.arrayContaining(expected), - }, ], + Post: [ + { + tags: expect.arrayContaining(expected), + }, + ], }, }), ) @@ -376,7 +384,7 @@ describe('Hashtags', () => { // The already existing Hashtag has no class at this point. const updatedPostContent = '

Hey Dude, #Elections should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone.

' - const updatePostMutation = gql ` + const updatePostMutation = gql` mutation($postId: ID!, $postTitle: String!, $updatedPostContent: String!) { UpdatePost(id: $postId, title: $postTitle, content: $updatedPostContent) { id @@ -396,11 +404,14 @@ describe('Hashtags', () => { }, }) - const expected = [{ - id: 'Elections' - }, { - id: 'Liberty' - }] + const expected = [ + { + id: 'Elections', + }, + { + id: 'Liberty', + }, + ] await expect( query({ query: postWithHastagsQuery, @@ -409,9 +420,11 @@ describe('Hashtags', () => { ).resolves.toEqual( expect.objectContaining({ data: { - Post: [{ - tags: expect.arrayContaining(expected), - }, ], + Post: [ + { + tags: expect.arrayContaining(expected), + }, + ], }, }), ) @@ -419,4 +432,4 @@ describe('Hashtags', () => { }) }) }) -}) \ No newline at end of file +}) diff --git a/backend/src/middleware/index.js b/backend/src/middleware/index.js index f155f5648..9d9ce7e35 100644 --- a/backend/src/middleware/index.js +++ b/backend/src/middleware/index.js @@ -12,7 +12,7 @@ import user from './userMiddleware' import includedFields from './includedFieldsMiddleware' import orderBy from './orderByMiddleware' import validation from './validation/validationMiddleware' -import handleNotifications from './handleNotifications/handleNotifications' +import handleNotifications from './handleNotifications/handleNotificationsMiddleware' import email from './email/emailMiddleware' export default schema => { diff --git a/backend/src/models/Notification.js b/backend/src/models/Notification.js index 89de27aec..93c4cd6cb 100644 --- a/backend/src/models/Notification.js +++ b/backend/src/models/Notification.js @@ -32,4 +32,4 @@ module.exports = { target: 'Post', direction: 'in', }, -} \ No newline at end of file +} diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.js index 313376a25..99dc2fcd3 100644 --- a/backend/src/schema/resolvers/notifications.spec.js +++ b/backend/src/schema/resolvers/notifications.spec.js @@ -1,12 +1,6 @@ -import { - GraphQLClient -} from 'graphql-request' +import { GraphQLClient } from 'graphql-request' import Factory from '../../seed/factories' -import { - host, - login, - gql -} from '../../jest/helpers' +import { host, login, gql } from '../../jest/helpers' const factory = Factory() let client @@ -25,7 +19,7 @@ afterEach(async () => { }) describe('query for notification', () => { - const notificationQuery = gql ` + const notificationQuery = gql` { Notification { id @@ -161,7 +155,7 @@ describe('currentUser notifications', () => { }) describe('filter for read: false', () => { - const queryCurrentUserNotificationsFilterRead = gql ` + const queryCurrentUserNotificationsFilterRead = gql` query($read: Boolean) { currentUser { notifications(read: $read, orderBy: createdAt_desc) { @@ -182,7 +176,8 @@ describe('currentUser notifications', () => { it('returns only unread notifications of current user', async () => { const expected = { currentUser: { - notifications: expect.arrayContaining([{ + notifications: expect.arrayContaining([ + { id: 'post-mention-unseen', post: { id: 'p1', @@ -206,7 +201,7 @@ describe('currentUser notifications', () => { }) describe('no filters', () => { - const queryCurrentUserNotifications = gql ` + const queryCurrentUserNotifications = gql` { currentUser { notifications(orderBy: createdAt_desc) { @@ -224,7 +219,8 @@ describe('currentUser notifications', () => { it('returns all notifications of current user', async () => { const expected = { currentUser: { - notifications: expect.arrayContaining([{ + notifications: expect.arrayContaining([ + { id: 'post-mention-unseen', post: { id: 'p1', @@ -265,7 +261,7 @@ describe('currentUser notifications', () => { }) describe('UpdateNotification', () => { - const mutationUpdateNotification = gql ` + const mutationUpdateNotification = gql` mutation($id: ID!, $read: Boolean) { UpdateNotification(id: $id, read: $read) { id @@ -402,4 +398,4 @@ describe('UpdateNotification', () => { }) }) }) -}) \ No newline at end of file +})