diff --git a/backend/src/middleware/notifications/notificationsMiddleware.js b/backend/src/middleware/notifications/notificationsMiddleware.js index a494783cf..718f0b1e4 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.js @@ -1,5 +1,21 @@ import extractMentionedUsers from './mentions/extractMentionedUsers' +const postAuthorOfComment = async (comment, { context }) => { + 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 [postAuthor] = await result.records.map(record => { + return record.get('user') + }) + return postAuthor +} + const notifyUsers = async (label, id, idsOfUsers, reason, context) => { if (!idsOfUsers.length) return @@ -90,11 +106,13 @@ const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo } const handleContentDataOfComment = async (resolve, root, args, context, resolveInfo) => { - const idsOfUsers = extractMentionedUsers(args.content) - + let idsOfUsers = extractMentionedUsers(args.content) const comment = await resolve(root, args, context, resolveInfo) if (comment) { + const postAuthor = await postAuthorOfComment(comment, { context }) + idsOfUsers = idsOfUsers.filter(id => id !== postAuthor.id) + await notifyUsers('Comment', comment.id, idsOfUsers, 'mentioned_in_comment', context) } diff --git a/backend/src/middleware/notifications/notificationsMiddleware.spec.js b/backend/src/middleware/notifications/notificationsMiddleware.spec.js index 88f91d688..18ee998db 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.spec.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.spec.js @@ -105,6 +105,7 @@ describe('notifications', () => { let title let postContent let postAuthor + const createPostAction = async () => { authenticatedUser = await postAuthor.toJson() await mutate({ @@ -239,6 +240,7 @@ describe('notifications', () => { describe('mentions me in a post', () => { beforeEach(async () => { title = 'Mentioning Al Capone' + postContent = 'Hey @al-capone how do you do?' }) @@ -439,7 +441,15 @@ describe('notifications', () => { }) }) - it('sends a notification', async () => { + it('sends only one notification with reason mentioned_in_comment', async () => { + postAuthor = await instance.create('User', { + id: 'MrPostAuthor', + name: 'Mr Author', + slug: 'mr-author', + email: 'post-author@example.org', + password: '1234', + }) + await createCommentOnPostAction() const expected = expect.objectContaining({ data: { @@ -467,6 +477,40 @@ describe('notifications', () => { }), ).resolves.toEqual(expected) }) + + beforeEach(async () => { + title = "Post where I'm the author and I get mentioned in a comment" + postContent = 'Content of post where I get mentioned in a comment.' + postAuthor = notifiedUser + }) + it('sends only one notification with reason commented_on_post, no notification with reason mentioned_in_comment', async () => { + await createCommentOnPostAction() + const expected = expect.objectContaining({ + data: { + notifications: [ + { + read: false, + createdAt: expect.any(String), + reason: 'commented_on_post', + from: { + __typename: 'Comment', + id: 'c47', + content: commentContent, + }, + }, + ], + }, + }) + const { query } = createTestClient(server) + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toEqual(expected) + }) }) describe('but the author of the post blocked me', () => {