mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
fix(backend): fix notification emails with different name (#8419)
* fix diffent name notifications We had emails sent with incorrect names. This PR combines the query for the email with the user the notification is sent to since the notification in database was correct. The underlying problem is the unstable order in which the database can return values. The results of the two queries were matched by id since it was assumed that they always return the same order of elements. lint fixes fix typo fix factory fix tests * fix tests accoridng to review also test for the right amount of emails in every test
This commit is contained in:
parent
5883818b91
commit
649491f7cb
@ -16,20 +16,21 @@ import createServer from '@src/server'
|
|||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('../helpers/email/sendMail', () => ({
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
sendMail: () => sendMailMock(),
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let server, query, mutate, authenticatedUser
|
let server, query, mutate, authenticatedUser, emaillessMember
|
||||||
|
|
||||||
let postAuthor, groupMember
|
let postAuthor, groupMember
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
|
|
||||||
const mentionString =
|
const mentionString = `
|
||||||
'<a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member">@group-member</a>'
|
<a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member">@group-member</a>
|
||||||
|
<a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member">@email-less-member</a>`
|
||||||
|
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
mutation ($id: ID, $title: String!, $content: String!, $groupId: ID) {
|
mutation ($id: ID, $title: String!, $content: String!, $groupId: ID) {
|
||||||
@ -148,6 +149,11 @@ describe('emails sent for notifications', () => {
|
|||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
emaillessMember = await neode.create('User', {
|
||||||
|
id: 'email-less-member',
|
||||||
|
name: 'Email-less Member',
|
||||||
|
slug: 'email-less-member',
|
||||||
|
})
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
@ -171,6 +177,18 @@ describe('emails sent for notifications', () => {
|
|||||||
mutation: followUserMutation,
|
mutation: followUserMutation,
|
||||||
variables: { id: 'post-author' },
|
variables: { id: 'post-author' },
|
||||||
})
|
})
|
||||||
|
authenticatedUser = await emaillessMember.toJson()
|
||||||
|
await mutate({
|
||||||
|
mutation: joinGroupMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'public-group',
|
||||||
|
userId: 'group-member',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: followUserMutation,
|
||||||
|
variables: { id: 'post-author' },
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -188,7 +206,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -213,7 +231,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -225,7 +243,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'followed_user_posted',
|
reason: 'followed_user_posted',
|
||||||
@ -237,7 +255,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
@ -260,7 +278,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -285,7 +303,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -297,7 +315,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'followed_user_posted',
|
reason: 'followed_user_posted',
|
||||||
@ -309,7 +327,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
@ -333,7 +351,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -358,7 +376,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -370,7 +388,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'followed_user_posted',
|
reason: 'followed_user_posted',
|
||||||
@ -382,7 +400,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
@ -407,7 +425,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -432,7 +450,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -444,7 +462,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'followed_user_posted',
|
reason: 'followed_user_posted',
|
||||||
@ -456,7 +474,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'post',
|
id: 'post',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my trusty follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
@ -481,7 +499,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -501,7 +519,7 @@ describe('emails sent for notifications', () => {
|
|||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content: `Hello, ${mentionString}, my beloved follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
postId: 'post',
|
postId: 'post',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -529,7 +547,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my beloved follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'commented_on_post',
|
reason: 'commented_on_post',
|
||||||
@ -541,7 +559,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my beloved follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_comment',
|
reason: 'mentioned_in_comment',
|
||||||
@ -563,7 +581,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -583,7 +601,7 @@ describe('emails sent for notifications', () => {
|
|||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content: `Hello, ${mentionString}, my beloved follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
postId: 'post',
|
postId: 'post',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -611,7 +629,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my beloved follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'commented_on_post',
|
reason: 'commented_on_post',
|
||||||
@ -623,7 +641,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my beloved follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_comment',
|
reason: 'mentioned_in_comment',
|
||||||
@ -646,7 +664,7 @@ describe('emails sent for notifications', () => {
|
|||||||
variables: {
|
variables: {
|
||||||
id: 'post',
|
id: 'post',
|
||||||
title: 'This is the post',
|
title: 'This is the post',
|
||||||
content: `Hello, ${mentionString}, my trusty follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
groupId: 'public-group',
|
groupId: 'public-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -666,7 +684,7 @@ describe('emails sent for notifications', () => {
|
|||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content: `Hello, ${mentionString}, my beloved follower.`,
|
content: `Hello, ${mentionString}, my trusty followers.`,
|
||||||
postId: 'post',
|
postId: 'post',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -694,7 +712,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my beloved follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'commented_on_post',
|
reason: 'commented_on_post',
|
||||||
@ -706,7 +724,7 @@ describe('emails sent for notifications', () => {
|
|||||||
__typename: 'Comment',
|
__typename: 'Comment',
|
||||||
id: 'comment-2',
|
id: 'comment-2',
|
||||||
content:
|
content:
|
||||||
'Hello, <a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>, my beloved follower.',
|
'Hello, <br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a><br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>, my trusty followers.',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_comment',
|
reason: 'mentioned_in_comment',
|
||||||
|
|||||||
@ -14,14 +14,14 @@ import createServer from '@src/server'
|
|||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('../helpers/email/sendMail', () => ({
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
sendMail: () => sendMailMock(),
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let server, query, mutate, authenticatedUser
|
let server, query, mutate, authenticatedUser
|
||||||
|
|
||||||
let postAuthor, firstFollower, secondFollower
|
let postAuthor, firstFollower, secondFollower, thirdFollower, emaillessFollower
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
@ -107,7 +107,7 @@ describe('following users notifications', () => {
|
|||||||
slug: 'post-author',
|
slug: 'post-author',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'test@example.org',
|
email: 'post-author@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -119,7 +119,7 @@ describe('following users notifications', () => {
|
|||||||
slug: 'first-follower',
|
slug: 'first-follower',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'test2@example.org',
|
email: 'first-follower@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -131,10 +131,27 @@ describe('following users notifications', () => {
|
|||||||
slug: 'second-follower',
|
slug: 'second-follower',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'test3@example.org',
|
email: 'second-follower@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
thirdFollower = await Factory.build(
|
||||||
|
'user',
|
||||||
|
{
|
||||||
|
id: 'third-follower',
|
||||||
|
name: 'Third Follower',
|
||||||
|
slug: 'third-follower',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email: 'third-follower@example.org',
|
||||||
|
password: '1234',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
emaillessFollower = await neode.create('User', {
|
||||||
|
id: 'email-less-follower',
|
||||||
|
name: 'Email-less Follower',
|
||||||
|
slug: 'email-less-follower',
|
||||||
|
})
|
||||||
await secondFollower.update({ emailNotificationsFollowingUsers: false })
|
await secondFollower.update({ emailNotificationsFollowingUsers: false })
|
||||||
authenticatedUser = await firstFollower.toJson()
|
authenticatedUser = await firstFollower.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
@ -146,6 +163,16 @@ describe('following users notifications', () => {
|
|||||||
mutation: followUserMutation,
|
mutation: followUserMutation,
|
||||||
variables: { id: 'post-author' },
|
variables: { id: 'post-author' },
|
||||||
})
|
})
|
||||||
|
authenticatedUser = await thirdFollower.toJson()
|
||||||
|
await mutate({
|
||||||
|
mutation: followUserMutation,
|
||||||
|
variables: { id: 'post-author' },
|
||||||
|
})
|
||||||
|
authenticatedUser = await emaillessFollower.toJson()
|
||||||
|
await mutate({
|
||||||
|
mutation: followUserMutation,
|
||||||
|
variables: { id: 'post-author' },
|
||||||
|
})
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -221,8 +248,43 @@ describe('following users notifications', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends only one email, as second follower has emails disabled', () => {
|
it('sends notification to the email-less follower', async () => {
|
||||||
expect(sendMailMock).toHaveBeenCalledTimes(1)
|
authenticatedUser = await emaillessFollower.toJson()
|
||||||
|
await expect(
|
||||||
|
query({
|
||||||
|
query: notificationQuery,
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
data: {
|
||||||
|
notifications: [
|
||||||
|
{
|
||||||
|
from: {
|
||||||
|
__typename: 'Post',
|
||||||
|
id: 'post',
|
||||||
|
},
|
||||||
|
read: false,
|
||||||
|
reason: 'followed_user_posted',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sends only two emails, as second follower has emails disabled and email-less follower has no email', () => {
|
||||||
|
expect(sendMailMock).toHaveBeenCalledTimes(2)
|
||||||
|
expect(sendMailMock).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
html: expect.stringContaining('Hello First Follower'),
|
||||||
|
to: 'first-follower@example.org',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
expect(sendMailMock).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
html: expect.stringContaining('Hello Third Follower'),
|
||||||
|
to: 'third-follower@example.org',
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -17,22 +17,23 @@ import createServer from '@src/server'
|
|||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('../helpers/email/sendMail', () => ({
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
sendMail: () => sendMailMock(),
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let server, query, mutate, authenticatedUser
|
let server, query, mutate, authenticatedUser
|
||||||
|
|
||||||
let postAuthor, groupMember, pendingMember, noMember
|
let postAuthor, groupMember, pendingMember, noMember, emaillessMember
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
|
|
||||||
const mentionString = `
|
const mentionString = `
|
||||||
<a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member">@no-meber</a>
|
<a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member">@no-member</a>
|
||||||
<a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member">@pending-member</a>
|
<a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member">@pending-member</a>
|
||||||
<a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member">@group-member</a>.
|
<a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member">@group-member</a>.
|
||||||
|
<a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member">@email-less-member</a>.
|
||||||
`
|
`
|
||||||
|
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
@ -168,6 +169,12 @@ describe('mentions in groups', () => {
|
|||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
emaillessMember = await neode.create('User', {
|
||||||
|
id: 'email-less-member',
|
||||||
|
name: 'Email-less Member',
|
||||||
|
slug: 'email-less-member',
|
||||||
|
})
|
||||||
|
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
@ -243,6 +250,28 @@ describe('mentions in groups', () => {
|
|||||||
userId: 'pending-member',
|
userId: 'pending-member',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
authenticatedUser = await emaillessMember.toJson()
|
||||||
|
await mutate({
|
||||||
|
mutation: joinGroupMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'public-group',
|
||||||
|
userId: 'group-member',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: joinGroupMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'closed-group',
|
||||||
|
userId: 'group-member',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: joinGroupMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'hidden-group',
|
||||||
|
userId: 'group-member',
|
||||||
|
},
|
||||||
|
})
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
@ -260,8 +289,26 @@ describe('mentions in groups', () => {
|
|||||||
roleInGroup: 'usual',
|
roleInGroup: 'usual',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'closed-group',
|
||||||
|
userId: 'email-less-member',
|
||||||
|
roleInGroup: 'usual',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'hidden-group',
|
||||||
|
userId: 'email-less-member',
|
||||||
|
roleInGroup: 'usual',
|
||||||
|
},
|
||||||
|
})
|
||||||
authenticatedUser = await groupMember.toJson()
|
authenticatedUser = await groupMember.toJson()
|
||||||
await markAllAsRead()
|
await markAllAsRead()
|
||||||
|
authenticatedUser = await emaillessMember.toJson()
|
||||||
|
await markAllAsRead()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -327,7 +374,7 @@ describe('mentions in groups', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'public-post',
|
id: 'public-post',
|
||||||
content:
|
content:
|
||||||
'Hey <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-meber</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br>! Please read this',
|
'Hey <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-member</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>.<br>! Please read this',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -339,7 +386,7 @@ describe('mentions in groups', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'public-post',
|
id: 'public-post',
|
||||||
content:
|
content:
|
||||||
'Hey <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-meber</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br>! Please read this',
|
'Hey <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-member</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>.<br>! Please read this',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
@ -351,7 +398,7 @@ describe('mentions in groups', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends 3 emails, one for each user', () => {
|
it('sends only 3 emails, one for each user with an email', () => {
|
||||||
expect(sendMailMock).toHaveBeenCalledTimes(3)
|
expect(sendMailMock).toHaveBeenCalledTimes(3)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -423,7 +470,7 @@ describe('mentions in groups', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'closed-post',
|
id: 'closed-post',
|
||||||
content:
|
content:
|
||||||
'Hey members <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-meber</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br>! Please read this',
|
'Hey members <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-member</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>.<br>! Please read this',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -435,7 +482,7 @@ describe('mentions in groups', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'closed-post',
|
id: 'closed-post',
|
||||||
content:
|
content:
|
||||||
'Hey members <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-meber</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br>! Please read this',
|
'Hey members <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-member</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>.<br>! Please read this',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
@ -519,7 +566,7 @@ describe('mentions in groups', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'hidden-post',
|
id: 'hidden-post',
|
||||||
content:
|
content:
|
||||||
'Hey hiders <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-meber</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br>! Please read this',
|
'Hey hiders <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-member</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>.<br>! Please read this',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'post_in_group',
|
reason: 'post_in_group',
|
||||||
@ -531,7 +578,7 @@ describe('mentions in groups', () => {
|
|||||||
__typename: 'Post',
|
__typename: 'Post',
|
||||||
id: 'hidden-post',
|
id: 'hidden-post',
|
||||||
content:
|
content:
|
||||||
'Hey hiders <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-meber</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br>! Please read this',
|
'Hey hiders <br><a class="mention" data-mention-id="no-member" href="/profile/no-member/no-member" target="_blank">@no-member</a><br><a class="mention" data-mention-id="pending-member" href="/profile/pending-member/pending-member" target="_blank">@pending-member</a><br><a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member" target="_blank">@group-member</a>.<br><a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member" target="_blank">@email-less-member</a>.<br>! Please read this',
|
||||||
},
|
},
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
|
|||||||
@ -6,15 +6,20 @@ import { createTestClient } from 'apollo-server-testing'
|
|||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import CONFIG from '@config/index'
|
||||||
import { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
import { getNeode, getDriver } from '@db/neo4j'
|
||||||
import createServer from '@src/server'
|
import createServer from '@src/server'
|
||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
|
}))
|
||||||
|
|
||||||
let server, query, mutate, authenticatedUser
|
let server, query, mutate, authenticatedUser
|
||||||
|
|
||||||
let postAuthor, firstCommenter, secondCommenter
|
let postAuthor, firstCommenter, secondCommenter, emaillessObserver
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
@ -102,42 +107,47 @@ afterAll(async () => {
|
|||||||
|
|
||||||
describe('notifications for users that observe a post', () => {
|
describe('notifications for users that observe a post', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
postAuthor = await neode.create(
|
postAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'post-author',
|
id: 'post-author',
|
||||||
name: 'Post Author',
|
name: 'Post Author',
|
||||||
slug: 'post-author',
|
slug: 'post-author',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'test@example.org',
|
email: 'post-author@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
firstCommenter = await neode.create(
|
firstCommenter = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'first-commenter',
|
id: 'first-commenter',
|
||||||
name: 'First Commenter',
|
name: 'First Commenter',
|
||||||
slug: 'first-commenter',
|
slug: 'first-commenter',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'test2@example.org',
|
email: 'first-commenter@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
secondCommenter = await neode.create(
|
secondCommenter = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'second-commenter',
|
id: 'second-commenter',
|
||||||
name: 'Second Commenter',
|
name: 'Second Commenter',
|
||||||
slug: 'second-commenter',
|
slug: 'second-commenter',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'test3@example.org',
|
email: 'second-commenter@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
emaillessObserver = await neode.create('User', {
|
||||||
|
id: 'email-less-observer',
|
||||||
|
name: 'Email-less Observer',
|
||||||
|
slug: 'email-less-observer',
|
||||||
|
})
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createPostMutation,
|
mutation: createPostMutation,
|
||||||
@ -147,6 +157,14 @@ describe('notifications for users that observe a post', () => {
|
|||||||
content: 'This is the content of the post',
|
content: 'This is the content of the post',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
authenticatedUser = await emaillessObserver.toJson()
|
||||||
|
await mutate({
|
||||||
|
mutation: toggleObservePostMutation,
|
||||||
|
variables: {
|
||||||
|
id: 'post',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('first comment on the post', () => {
|
describe('first comment on the post', () => {
|
||||||
@ -198,8 +216,18 @@ describe('notifications for users that observe a post', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('sends one email', () => {
|
||||||
|
expect(sendMailMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(sendMailMock).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
to: 'post-author@example.org',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
describe('second comment on post', () => {
|
describe('second comment on post', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
authenticatedUser = await secondCommenter.toJson()
|
authenticatedUser = await secondCommenter.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
@ -277,10 +305,25 @@ describe('notifications for users that observe a post', () => {
|
|||||||
errors: undefined,
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('sends two emails', () => {
|
||||||
|
expect(sendMailMock).toHaveBeenCalledTimes(2)
|
||||||
|
expect(sendMailMock).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
to: 'post-author@example.org',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
expect(sendMailMock).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
to: 'first-commenter@example.org',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('first commenter unfollows the post and post author comments post', () => {
|
describe('first commenter unfollows the post and post author comments post', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
authenticatedUser = await firstCommenter.toJson()
|
authenticatedUser = await firstCommenter.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: toggleObservePostMutation,
|
mutation: toggleObservePostMutation,
|
||||||
@ -376,6 +419,15 @@ describe('notifications for users that observe a post', () => {
|
|||||||
errors: undefined,
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('sends one email', () => {
|
||||||
|
expect(sendMailMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(sendMailMock).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
to: 'second-commenter@example.org',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import createServer from '@src/server'
|
|||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('../helpers/email/sendMail', () => ({
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
sendMail: () => sendMailMock(),
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let isUserOnlineMock = jest.fn().mockReturnValue(false)
|
let isUserOnlineMock = jest.fn().mockReturnValue(false)
|
||||||
|
|||||||
@ -17,14 +17,14 @@ import createServer from '@src/server'
|
|||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('../helpers/email/sendMail', () => ({
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
sendMail: () => sendMailMock(),
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let server, query, mutate, authenticatedUser
|
let server, query, mutate, authenticatedUser
|
||||||
|
|
||||||
let postAuthor, groupMember, pendingMember
|
let postAuthor, groupMember, pendingMember, emaillessMember
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
@ -159,6 +159,12 @@ describe('notify group members of new posts in group', () => {
|
|||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
emaillessMember = await neode.create('User', {
|
||||||
|
id: 'email-less-member',
|
||||||
|
name: 'Email-less Member',
|
||||||
|
slug: 'email-less-member',
|
||||||
|
})
|
||||||
|
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
@ -186,6 +192,14 @@ describe('notify group members of new posts in group', () => {
|
|||||||
userId: 'pending-member',
|
userId: 'pending-member',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
authenticatedUser = await emaillessMember.toJson()
|
||||||
|
await mutate({
|
||||||
|
mutation: joinGroupMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'g-1',
|
||||||
|
userId: 'group-member',
|
||||||
|
},
|
||||||
|
})
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
@ -195,6 +209,14 @@ describe('notify group members of new posts in group', () => {
|
|||||||
roleInGroup: 'usual',
|
roleInGroup: 'usual',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'g-1',
|
||||||
|
userId: 'email-less-member',
|
||||||
|
roleInGroup: 'usual',
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
|
|||||||
@ -18,9 +18,9 @@ import { leaveGroupMutation } from '@graphql/queries/leaveGroupMutation'
|
|||||||
import { removeUserFromGroupMutation } from '@graphql/queries/removeUserFromGroupMutation'
|
import { removeUserFromGroupMutation } from '@graphql/queries/removeUserFromGroupMutation'
|
||||||
import createServer, { pubsub } from '@src/server'
|
import createServer, { pubsub } from '@src/server'
|
||||||
|
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('../helpers/email/sendMail', () => ({
|
jest.mock('@middleware/helpers/email/sendMail', () => ({
|
||||||
sendMail: () => sendMailMock(),
|
sendMail: (notification) => sendMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const chatMessageTemplateMock = jest.fn()
|
const chatMessageTemplateMock = jest.fn()
|
||||||
@ -195,8 +195,8 @@ describe('notifications', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
commentContent = 'Commenters comment.'
|
commentContent = 'Commenters comment.'
|
||||||
commentAuthor = await neode.create(
|
commentAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'commentAuthor',
|
id: 'commentAuthor',
|
||||||
name: 'Mrs Comment',
|
name: 'Mrs Comment',
|
||||||
@ -345,8 +345,8 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
postAuthor = await neode.create(
|
postAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'postAuthor',
|
id: 'postAuthor',
|
||||||
name: 'Mrs Post',
|
name: 'Mrs Post',
|
||||||
@ -658,8 +658,8 @@ describe('notifications', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
commentContent =
|
commentContent =
|
||||||
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
||||||
commentAuthor = await neode.create(
|
commentAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'commentAuthor',
|
id: 'commentAuthor',
|
||||||
name: 'Mrs Comment',
|
name: 'Mrs Comment',
|
||||||
@ -673,15 +673,15 @@ describe('notifications', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('sends only one notification with reason mentioned_in_comment', async () => {
|
it('sends only one notification with reason mentioned_in_comment', async () => {
|
||||||
postAuthor = await neode.create(
|
postAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'MrPostAuthor',
|
id: 'MrPostAuthor',
|
||||||
name: 'Mr Author',
|
name: 'Mr Author',
|
||||||
slug: 'mr-author',
|
slug: 'mr-author',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'post-author@example.org',
|
email: 'post-author2@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -756,8 +756,8 @@ describe('notifications', () => {
|
|||||||
await postAuthor.relateTo(notifiedUser, 'blocked')
|
await postAuthor.relateTo(notifiedUser, 'blocked')
|
||||||
commentContent =
|
commentContent =
|
||||||
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
||||||
commentAuthor = await neode.create(
|
commentAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'commentAuthor',
|
id: 'commentAuthor',
|
||||||
name: 'Mrs Comment',
|
name: 'Mrs Comment',
|
||||||
@ -807,8 +807,8 @@ describe('notifications', () => {
|
|||||||
await postAuthor.relateTo(notifiedUser, 'muted')
|
await postAuthor.relateTo(notifiedUser, 'muted')
|
||||||
commentContent =
|
commentContent =
|
||||||
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
||||||
commentAuthor = await neode.create(
|
commentAuthor = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'commentAuthor',
|
id: 'commentAuthor',
|
||||||
name: 'Mrs Comment',
|
name: 'Mrs Comment',
|
||||||
@ -879,8 +879,8 @@ describe('notifications', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|
||||||
chatSender = await neode.create(
|
chatSender = await Factory.build(
|
||||||
'User',
|
'user',
|
||||||
{
|
{
|
||||||
id: 'chatSender',
|
id: 'chatSender',
|
||||||
name: 'chatSender',
|
name: 'chatSender',
|
||||||
@ -931,7 +931,7 @@ describe('notifications', () => {
|
|||||||
content: 'Some nice message to chatReceiver',
|
content: 'Some nice message to chatReceiver',
|
||||||
senderId: 'chatSender',
|
senderId: 'chatSender',
|
||||||
username: 'chatSender',
|
username: 'chatSender',
|
||||||
avatar: null,
|
avatar: expect.any(String),
|
||||||
date: expect.any(String),
|
date: expect.any(String),
|
||||||
saved: true,
|
saved: true,
|
||||||
distributed: false,
|
distributed: false,
|
||||||
@ -967,7 +967,7 @@ describe('notifications', () => {
|
|||||||
content: 'Some nice message to chatReceiver',
|
content: 'Some nice message to chatReceiver',
|
||||||
senderId: 'chatSender',
|
senderId: 'chatSender',
|
||||||
username: 'chatSender',
|
username: 'chatSender',
|
||||||
avatar: null,
|
avatar: expect.any(String),
|
||||||
date: expect.any(String),
|
date: expect.any(String),
|
||||||
saved: true,
|
saved: true,
|
||||||
distributed: false,
|
distributed: false,
|
||||||
@ -1046,7 +1046,7 @@ describe('notifications', () => {
|
|||||||
content: 'Some nice message to chatReceiver',
|
content: 'Some nice message to chatReceiver',
|
||||||
senderId: 'chatSender',
|
senderId: 'chatSender',
|
||||||
username: 'chatSender',
|
username: 'chatSender',
|
||||||
avatar: null,
|
avatar: expect.any(String),
|
||||||
date: expect.any(String),
|
date: expect.any(String),
|
||||||
saved: true,
|
saved: true,
|
||||||
distributed: false,
|
distributed: false,
|
||||||
|
|||||||
@ -18,59 +18,28 @@ import { pubsub, NOTIFICATION_ADDED, ROOM_COUNT_UPDATED, CHAT_MESSAGE_ADDED } fr
|
|||||||
|
|
||||||
import extractMentionedUsers from './mentions/extractMentionedUsers'
|
import extractMentionedUsers from './mentions/extractMentionedUsers'
|
||||||
|
|
||||||
const queryNotificationEmails = async (context, notificationUserIds) => {
|
|
||||||
if (!notificationUserIds?.length) return []
|
|
||||||
const userEmailCypher = `
|
|
||||||
MATCH (user: User)
|
|
||||||
// blocked users are filtered out from notifications already
|
|
||||||
WHERE user.id in $notificationUserIds
|
|
||||||
WITH user
|
|
||||||
MATCH (user)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
|
||||||
RETURN emailAddress {.email}
|
|
||||||
`
|
|
||||||
const session = context.driver.session()
|
|
||||||
const writeTxResultPromise = session.readTransaction(async (transaction) => {
|
|
||||||
const emailAddressTransactionResponse = await transaction.run(userEmailCypher, {
|
|
||||||
notificationUserIds,
|
|
||||||
})
|
|
||||||
return emailAddressTransactionResponse.records.map((record) => record.get('emailAddress'))
|
|
||||||
})
|
|
||||||
try {
|
|
||||||
const emailAddresses = await writeTxResultPromise
|
|
||||||
return emailAddresses
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(error)
|
|
||||||
} finally {
|
|
||||||
session.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const publishNotifications = async (
|
const publishNotifications = async (
|
||||||
context,
|
context,
|
||||||
promises,
|
notificationsPromise,
|
||||||
emailNotificationSetting: string,
|
emailNotificationSetting: string,
|
||||||
emailsSent: string[] = [],
|
emailsSent: string[] = [],
|
||||||
): Promise<string[]> => {
|
): Promise<string[]> => {
|
||||||
let notifications = await Promise.all(promises)
|
const notifications = await notificationsPromise
|
||||||
notifications = notifications.flat()
|
notifications.forEach((notificationAdded) => {
|
||||||
const notificationsEmailAddresses = await queryNotificationEmails(
|
|
||||||
context,
|
|
||||||
notifications.map((notification) => notification.to.id),
|
|
||||||
)
|
|
||||||
notifications.forEach((notificationAdded, index) => {
|
|
||||||
pubsub.publish(NOTIFICATION_ADDED, { notificationAdded })
|
pubsub.publish(NOTIFICATION_ADDED, { notificationAdded })
|
||||||
if (
|
if (
|
||||||
|
notificationAdded.email && // no primary email was found
|
||||||
(notificationAdded.to[emailNotificationSetting] ?? true) &&
|
(notificationAdded.to[emailNotificationSetting] ?? true) &&
|
||||||
!isUserOnline(notificationAdded.to) &&
|
!isUserOnline(notificationAdded.to) &&
|
||||||
!emailsSent.includes(notificationsEmailAddresses[index].email)
|
!emailsSent.includes(notificationAdded.email)
|
||||||
) {
|
) {
|
||||||
sendMail(
|
sendMail(
|
||||||
notificationTemplate({
|
notificationTemplate({
|
||||||
email: notificationsEmailAddresses[index].email,
|
email: notificationAdded.email,
|
||||||
variables: { notification: notificationAdded },
|
variables: { notification: notificationAdded },
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
emailsSent.push(notificationsEmailAddresses[index].email)
|
emailsSent.push(notificationAdded.email)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return emailsSent
|
return emailsSent
|
||||||
@ -82,7 +51,7 @@ const handleJoinGroup = async (resolve, root, args, context, resolveInfo) => {
|
|||||||
if (user) {
|
if (user) {
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context)],
|
notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context),
|
||||||
'emailNotificationsGroupMemberJoined',
|
'emailNotificationsGroupMemberJoined',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -95,7 +64,7 @@ const handleLeaveGroup = async (resolve, root, args, context, resolveInfo) => {
|
|||||||
if (user) {
|
if (user) {
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyOwnersOfGroup(groupId, userId, 'user_left_group', context)],
|
notifyOwnersOfGroup(groupId, userId, 'user_left_group', context),
|
||||||
'emailNotificationsGroupMemberLeft',
|
'emailNotificationsGroupMemberLeft',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -108,7 +77,7 @@ const handleChangeGroupMemberRole = async (resolve, root, args, context, resolve
|
|||||||
if (user) {
|
if (user) {
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context)],
|
notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context),
|
||||||
'emailNotificationsGroupMemberRoleChanged',
|
'emailNotificationsGroupMemberRoleChanged',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -121,7 +90,7 @@ const handleRemoveUserFromGroup = async (resolve, root, args, context, resolveIn
|
|||||||
if (user) {
|
if (user) {
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context)],
|
notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context),
|
||||||
'emailNotificationsGroupMemberRemoved',
|
'emailNotificationsGroupMemberRemoved',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -135,20 +104,20 @@ const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo
|
|||||||
if (post) {
|
if (post) {
|
||||||
const sentEmails: string[] = await publishNotifications(
|
const sentEmails: string[] = await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context)],
|
notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context),
|
||||||
'emailNotificationsMention',
|
'emailNotificationsMention',
|
||||||
)
|
)
|
||||||
sentEmails.concat(
|
sentEmails.concat(
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyFollowingUsers(post.id, groupId, context)],
|
notifyFollowingUsers(post.id, groupId, context),
|
||||||
'emailNotificationsFollowingUsers',
|
'emailNotificationsFollowingUsers',
|
||||||
sentEmails,
|
sentEmails,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyGroupMembersOfNewPost(post.id, groupId, context)],
|
notifyGroupMembersOfNewPost(post.id, groupId, context),
|
||||||
'emailNotificationsPostInGroup',
|
'emailNotificationsPostInGroup',
|
||||||
sentEmails,
|
sentEmails,
|
||||||
)
|
)
|
||||||
@ -164,20 +133,18 @@ const handleContentDataOfComment = async (resolve, root, args, context, resolveI
|
|||||||
idsOfMentionedUsers = idsOfMentionedUsers.filter((id) => id !== postAuthor.id)
|
idsOfMentionedUsers = idsOfMentionedUsers.filter((id) => id !== postAuthor.id)
|
||||||
const sentEmails: string[] = await publishNotifications(
|
const sentEmails: string[] = await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[
|
notifyUsersOfMention(
|
||||||
notifyUsersOfMention(
|
'Comment',
|
||||||
'Comment',
|
comment.id,
|
||||||
comment.id,
|
idsOfMentionedUsers,
|
||||||
idsOfMentionedUsers,
|
'mentioned_in_comment',
|
||||||
'mentioned_in_comment',
|
context,
|
||||||
context,
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
'emailNotificationsMention',
|
'emailNotificationsMention',
|
||||||
)
|
)
|
||||||
await publishNotifications(
|
await publishNotifications(
|
||||||
context,
|
context,
|
||||||
[notifyUsersOfComment('Comment', comment.id, 'commented_on_post', context)],
|
notifyUsersOfComment('Comment', comment.id, 'commented_on_post', context),
|
||||||
'emailNotificationsCommentOnObservedPost',
|
'emailNotificationsCommentOnObservedPost',
|
||||||
sentEmails,
|
sentEmails,
|
||||||
)
|
)
|
||||||
@ -208,17 +175,20 @@ const notifyFollowingUsers = async (postId, groupId, context) => {
|
|||||||
const cypher = `
|
const cypher = `
|
||||||
MATCH (post:Post { id: $postId })<-[:WROTE]-(author:User { id: $userId })<-[:FOLLOWS]-(user:User)
|
MATCH (post:Post { id: $postId })<-[:WROTE]-(author:User { id: $userId })<-[:FOLLOWS]-(user:User)
|
||||||
OPTIONAL MATCH (post)-[:IN]->(group:Group { id: $groupId })
|
OPTIONAL MATCH (post)-[:IN]->(group:Group { id: $groupId })
|
||||||
WITH post, author, user, group WHERE group IS NULL OR group.groupType = 'public'
|
OPTIONAL MATCH (user)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
|
WITH post, author, user, emailAddress, group
|
||||||
|
WHERE group IS NULL OR group.groupType = 'public'
|
||||||
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
|
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||||
SET notification.read = FALSE
|
SET notification.read = FALSE
|
||||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||||
SET notification.updatedAt = toString(datetime())
|
SET notification.updatedAt = toString(datetime())
|
||||||
WITH notification, author, user,
|
WITH notification, author, user, emailAddress.email as email,
|
||||||
post {.*, author: properties(author) } AS finalResource
|
post {.*, author: properties(author) } AS finalResource
|
||||||
RETURN notification {
|
RETURN notification {
|
||||||
.*,
|
.*,
|
||||||
from: finalResource,
|
from: finalResource,
|
||||||
to: properties(user),
|
to: properties(user),
|
||||||
|
email: email,
|
||||||
relatedUser: properties(author)
|
relatedUser: properties(author)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -233,8 +203,7 @@ const notifyFollowingUsers = async (postId, groupId, context) => {
|
|||||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const notifications = await writeTxResultPromise
|
return await writeTxResultPromise
|
||||||
return notifications
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
@ -247,23 +216,25 @@ const notifyGroupMembersOfNewPost = async (postId, groupId, context) => {
|
|||||||
const reason = 'post_in_group'
|
const reason = 'post_in_group'
|
||||||
const cypher = `
|
const cypher = `
|
||||||
MATCH (post:Post { id: $postId })<-[:WROTE]-(author:User { id: $userId })
|
MATCH (post:Post { id: $postId })<-[:WROTE]-(author:User { id: $userId })
|
||||||
|
OPTIONAL MATCH (user)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
MATCH (post)-[:IN]->(group:Group { id: $groupId })<-[membership:MEMBER_OF]-(user:User)
|
MATCH (post)-[:IN]->(group:Group { id: $groupId })<-[membership:MEMBER_OF]-(user:User)
|
||||||
WHERE NOT membership.role = 'pending'
|
WHERE NOT membership.role = 'pending'
|
||||||
AND NOT (user)-[:MUTED]->(group)
|
AND NOT (user)-[:MUTED]->(group)
|
||||||
AND NOT (user)-[:MUTED]->(author)
|
AND NOT (user)-[:MUTED]->(author)
|
||||||
AND NOT (user)-[:BLOCKED]-(author)
|
AND NOT (user)-[:BLOCKED]-(author)
|
||||||
AND NOT user.id = $userId
|
AND NOT user.id = $userId
|
||||||
WITH post, author, user
|
WITH post, author, user, emailAddress
|
||||||
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
|
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||||
SET notification.read = FALSE
|
SET notification.read = FALSE
|
||||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||||
SET notification.updatedAt = toString(datetime())
|
SET notification.updatedAt = toString(datetime())
|
||||||
WITH notification, author, user,
|
WITH notification, author, user, emailAddress.email as email,
|
||||||
post {.*, author: properties(author) } AS finalResource
|
post {.*, author: properties(author) } AS finalResource
|
||||||
RETURN notification {
|
RETURN notification {
|
||||||
.*,
|
.*,
|
||||||
from: finalResource,
|
from: finalResource,
|
||||||
to: properties(user),
|
to: properties(user),
|
||||||
|
email: email,
|
||||||
relatedUser: properties(author)
|
relatedUser: properties(author)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -278,8 +249,7 @@ const notifyGroupMembersOfNewPost = async (postId, groupId, context) => {
|
|||||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const notifications = await writeTxResultPromise
|
return await writeTxResultPromise
|
||||||
return notifications
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
@ -295,12 +265,13 @@ const notifyOwnersOfGroup = async (groupId, userId, reason, context) => {
|
|||||||
WITH owner, group, user, membership
|
WITH owner, group, user, membership
|
||||||
MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(owner)
|
MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(owner)
|
||||||
WITH group, owner, notification, user, membership
|
WITH group, owner, notification, user, membership
|
||||||
|
OPTIONAL MATCH (owner)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
SET notification.read = FALSE
|
SET notification.read = FALSE
|
||||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||||
SET notification.updatedAt = toString(datetime())
|
SET notification.updatedAt = toString(datetime())
|
||||||
SET notification.relatedUserId = $userId
|
SET notification.relatedUserId = $userId
|
||||||
WITH owner, group { __typename: 'Group', .*, myRole: membership.roleInGroup } AS finalGroup, user, notification
|
WITH owner, emailAddress.email as email, group { __typename: 'Group', .*, myRole: membership.roleInGroup } AS finalGroup, user, notification
|
||||||
RETURN notification {.*, from: finalGroup, to: properties(owner), relatedUser: properties(user) }
|
RETURN notification {.*, from: finalGroup, to: properties(owner), email: email, relatedUser: properties(user) }
|
||||||
`
|
`
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
@ -312,8 +283,7 @@ const notifyOwnersOfGroup = async (groupId, userId, reason, context) => {
|
|||||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const notifications = await writeTxResultPromise
|
return await writeTxResultPromise
|
||||||
return notifications
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
@ -327,17 +297,18 @@ const notifyMemberOfGroup = async (groupId, userId, reason, context) => {
|
|||||||
MATCH (owner:User { id: $ownerId })
|
MATCH (owner:User { id: $ownerId })
|
||||||
MATCH (user:User { id: $userId })
|
MATCH (user:User { id: $userId })
|
||||||
MATCH (group:Group { id: $groupId })
|
MATCH (group:Group { id: $groupId })
|
||||||
|
OPTIONAL MATCH (user)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
OPTIONAL MATCH (user)-[membership:MEMBER_OF]->(group)
|
OPTIONAL MATCH (user)-[membership:MEMBER_OF]->(group)
|
||||||
WITH user, group, owner, membership
|
WITH user, group, owner, membership, emailAddress
|
||||||
MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(user)
|
MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||||
WITH group, user, notification, owner, membership
|
WITH group, user, notification, owner, membership, emailAddress
|
||||||
SET notification.read = FALSE
|
SET notification.read = FALSE
|
||||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||||
SET notification.updatedAt = toString(datetime())
|
SET notification.updatedAt = toString(datetime())
|
||||||
SET notification.relatedUserId = $ownerId
|
SET notification.relatedUserId = $ownerId
|
||||||
WITH group { __typename: 'Group', .*, myRole: membership.roleInGroup } AS finalGroup,
|
WITH group { __typename: 'Group', .*, myRole: membership.roleInGroup } AS finalGroup,
|
||||||
notification, user, owner
|
notification, user, emailAddress.email as email, owner
|
||||||
RETURN notification {.*, from: finalGroup, to: properties(user), relatedUser: properties(owner) }
|
RETURN notification {.*, from: finalGroup, to: properties(user), email: email, relatedUser: properties(owner) }
|
||||||
`
|
`
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
@ -350,8 +321,7 @@ const notifyMemberOfGroup = async (groupId, userId, reason, context) => {
|
|||||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const notifications = await writeTxResultPromise
|
return await writeTxResultPromise
|
||||||
return notifications
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
@ -371,11 +341,13 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
|||||||
WHERE user.id in $idsOfUsers
|
WHERE user.id in $idsOfUsers
|
||||||
AND NOT (user)-[:BLOCKED]-(author)
|
AND NOT (user)-[:BLOCKED]-(author)
|
||||||
AND NOT (user)-[:MUTED]->(author)
|
AND NOT (user)-[:MUTED]->(author)
|
||||||
|
OPTIONAL MATCH (user)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
OPTIONAL MATCH (post)-[:IN]->(group:Group)
|
OPTIONAL MATCH (post)-[:IN]->(group:Group)
|
||||||
OPTIONAL MATCH (group)<-[membership:MEMBER_OF]-(user)
|
OPTIONAL MATCH (group)<-[membership:MEMBER_OF]-(user)
|
||||||
WITH post, author, user, group WHERE group IS NULL OR group.groupType = 'public' OR membership.role IN ['usual', 'admin', 'owner']
|
WITH post, author, user, group, emailAddress
|
||||||
|
WHERE group IS NULL OR group.groupType = 'public' OR membership.role IN ['usual', 'admin', 'owner']
|
||||||
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
|
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||||
WITH post AS resource, notification, user
|
WITH post AS resource, notification, user, emailAddress
|
||||||
`
|
`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -388,25 +360,27 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
|||||||
AND NOT (user)-[:BLOCKED]-(postAuthor)
|
AND NOT (user)-[:BLOCKED]-(postAuthor)
|
||||||
AND NOT (user)-[:MUTED]->(commenter)
|
AND NOT (user)-[:MUTED]->(commenter)
|
||||||
AND NOT (user)-[:MUTED]->(postAuthor)
|
AND NOT (user)-[:MUTED]->(postAuthor)
|
||||||
|
OPTIONAL MATCH (user)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
OPTIONAL MATCH (post)-[:IN]->(group:Group)
|
OPTIONAL MATCH (post)-[:IN]->(group:Group)
|
||||||
OPTIONAL MATCH (group)<-[membership:MEMBER_OF]-(user)
|
OPTIONAL MATCH (group)<-[membership:MEMBER_OF]-(user)
|
||||||
WITH comment, user, group WHERE group IS NULL OR group.groupType = 'public' OR membership.role IN ['usual', 'admin', 'owner']
|
WITH comment, user, group, emailAddress
|
||||||
|
WHERE group IS NULL OR group.groupType = 'public' OR membership.role IN ['usual', 'admin', 'owner']
|
||||||
MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user)
|
MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||||
WITH comment AS resource, notification, user
|
WITH comment AS resource, notification, user, emailAddress
|
||||||
`
|
`
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mentionedCypher += `
|
mentionedCypher += `
|
||||||
WITH notification, user, resource,
|
WITH notification, user, resource, emailAddress,
|
||||||
[(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
[(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
|
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
|
||||||
WITH resource, user, notification, authors, posts,
|
WITH resource, user, emailAddress.email as email, notification, authors, posts,
|
||||||
resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'Group']][0], author: authors[0], post: posts[0]} AS finalResource
|
resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'Group']][0], author: authors[0], post: posts[0]} AS finalResource
|
||||||
SET notification.read = FALSE
|
SET notification.read = FALSE
|
||||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||||
SET notification.updatedAt = toString(datetime())
|
SET notification.updatedAt = toString(datetime())
|
||||||
RETURN notification {.*, from: finalResource, to: properties(user), relatedUser: properties(user) }
|
RETURN notification {.*, from: finalResource, to: properties(user), email: email, relatedUser: properties(user) }
|
||||||
`
|
`
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
@ -418,8 +392,7 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
|||||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const notifications = await writeTxResultPromise
|
return await writeTxResultPromise
|
||||||
return notifications
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
@ -437,18 +410,20 @@ const notifyUsersOfComment = async (label, commentId, reason, context) => {
|
|||||||
WHERE NOT (observingUser)-[:BLOCKED]-(commenter)
|
WHERE NOT (observingUser)-[:BLOCKED]-(commenter)
|
||||||
AND NOT (observingUser)-[:MUTED]->(commenter)
|
AND NOT (observingUser)-[:MUTED]->(commenter)
|
||||||
AND NOT observingUser.id = $userId
|
AND NOT observingUser.id = $userId
|
||||||
WITH observingUser, post, comment, commenter
|
OPTIONAL MATCH (observingUser)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress)
|
||||||
|
WITH observingUser, emailAddress, post, comment, commenter
|
||||||
MATCH (postAuthor:User)-[:WROTE]->(post)
|
MATCH (postAuthor:User)-[:WROTE]->(post)
|
||||||
MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(observingUser)
|
MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(observingUser)
|
||||||
SET notification.read = FALSE
|
SET notification.read = FALSE
|
||||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||||
SET notification.updatedAt = toString(datetime())
|
SET notification.updatedAt = toString(datetime())
|
||||||
WITH notification, observingUser, post, commenter, postAuthor,
|
WITH notification, observingUser, emailAddress.email as email, post, commenter, postAuthor,
|
||||||
comment {.*, __typename: labels(comment)[0], author: properties(commenter), post: post {.*, author: properties(postAuthor) } } AS finalResource
|
comment {.*, __typename: labels(comment)[0], author: properties(commenter), post: post {.*, author: properties(postAuthor) } } AS finalResource
|
||||||
RETURN notification {
|
RETURN notification {
|
||||||
.*,
|
.*,
|
||||||
from: finalResource,
|
from: finalResource,
|
||||||
to: properties(observingUser),
|
to: properties(observingUser),
|
||||||
|
email: email,
|
||||||
relatedUser: properties(commenter)
|
relatedUser: properties(commenter)
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -461,8 +436,7 @@ const notifyUsersOfComment = async (label, commentId, reason, context) => {
|
|||||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const notifications = await writeTxResultPromise
|
return await writeTxResultPromise
|
||||||
return notifications
|
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user