mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
parent
44d503c53c
commit
f32bfc7e36
@ -2,11 +2,21 @@ import extractMentionedUsers from './mentions/extractMentionedUsers'
|
|||||||
import { validateNotifyUsers } from '../validation/validationMiddleware'
|
import { validateNotifyUsers } from '../validation/validationMiddleware'
|
||||||
import { pubsub, NOTIFICATION_ADDED } from '../../server'
|
import { pubsub, NOTIFICATION_ADDED } from '../../server'
|
||||||
|
|
||||||
|
const publishNotifications = async (...promises) => {
|
||||||
|
const notifications = await Promise.all(promises)
|
||||||
|
notifications
|
||||||
|
.flat()
|
||||||
|
.forEach(notificationAdded => pubsub.publish(NOTIFICATION_ADDED, { notificationAdded }))
|
||||||
|
}
|
||||||
|
|
||||||
const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => {
|
const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => {
|
||||||
const idsOfUsers = extractMentionedUsers(args.content)
|
const idsOfUsers = extractMentionedUsers(args.content)
|
||||||
const post = await resolve(root, args, context, resolveInfo)
|
const post = await resolve(root, args, context, resolveInfo)
|
||||||
if (post && idsOfUsers && idsOfUsers.length)
|
if (post) {
|
||||||
await notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context)
|
await publishNotifications(
|
||||||
|
notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context),
|
||||||
|
)
|
||||||
|
}
|
||||||
return post
|
return post
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,10 +26,10 @@ const handleContentDataOfComment = async (resolve, root, args, context, resolveI
|
|||||||
const comment = await resolve(root, args, context, resolveInfo)
|
const comment = await resolve(root, args, context, resolveInfo)
|
||||||
const [postAuthor] = await postAuthorOfComment(comment.id, { context })
|
const [postAuthor] = await postAuthorOfComment(comment.id, { context })
|
||||||
idsOfUsers = idsOfUsers.filter(id => id !== postAuthor.id)
|
idsOfUsers = idsOfUsers.filter(id => id !== postAuthor.id)
|
||||||
if (idsOfUsers && idsOfUsers.length)
|
await publishNotifications(
|
||||||
await notifyUsersOfMention('Comment', comment.id, idsOfUsers, 'mentioned_in_comment', context)
|
notifyUsersOfMention('Comment', comment.id, idsOfUsers, 'mentioned_in_comment', context),
|
||||||
if (context.user.id !== postAuthor.id)
|
notifyUsersOfComment('Comment', comment.id, postAuthor.id, 'commented_on_post', context),
|
||||||
await notifyUsersOfComment('Comment', comment.id, postAuthor.id, 'commented_on_post', context)
|
)
|
||||||
return comment
|
return comment
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +39,7 @@ const postAuthorOfComment = async (commentId, { context }) => {
|
|||||||
try {
|
try {
|
||||||
postAuthorId = await session.readTransaction(transaction => {
|
postAuthorId = await session.readTransaction(transaction => {
|
||||||
return transaction.run(
|
return transaction.run(
|
||||||
`
|
`
|
||||||
MATCH (author:User)-[:WROTE]->(:Post)<-[:COMMENTS]-(:Comment { id: $commentId })
|
MATCH (author:User)-[:WROTE]->(:Post)<-[:COMMENTS]-(:Comment { id: $commentId })
|
||||||
RETURN author { .id } as authorId
|
RETURN author { .id } as authorId
|
||||||
`,
|
`,
|
||||||
@ -43,6 +53,7 @@ const postAuthorOfComment = async (commentId, { context }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
||||||
|
if (!(idsOfUsers && idsOfUsers.length)) return []
|
||||||
await validateNotifyUsers(label, reason)
|
await validateNotifyUsers(label, reason)
|
||||||
let mentionedCypher
|
let mentionedCypher
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
@ -91,8 +102,8 @@ 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 [notification] = await writeTxResultPromise
|
const notifications = await writeTxResultPromise
|
||||||
return pubsub.publish(NOTIFICATION_ADDED, { notificationAdded: notification })
|
return notifications
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
@ -101,6 +112,7 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, context) => {
|
const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, context) => {
|
||||||
|
if (!(context.user.id !== postAuthorId)) return []
|
||||||
await validateNotifyUsers(label, reason)
|
await validateNotifyUsers(label, reason)
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = await session.writeTransaction(async transaction => {
|
const writeTxResultPromise = await session.writeTransaction(async transaction => {
|
||||||
@ -121,8 +133,8 @@ const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, cont
|
|||||||
return notificationTransactionResponse.records.map(record => record.get('notification'))
|
return notificationTransactionResponse.records.map(record => record.get('notification'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const [notification] = await writeTxResultPromise
|
const notifications = await writeTxResultPromise
|
||||||
return pubsub.publish(NOTIFICATION_ADDED, { notificationAdded: notification })
|
return notifications
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,10 @@ import { gql } from '../../helpers/jest'
|
|||||||
import { cleanDatabase } from '../../db/factories'
|
import { cleanDatabase } from '../../db/factories'
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
import { createTestClient } from 'apollo-server-testing'
|
||||||
import { getNeode, getDriver } from '../../db/neo4j'
|
import { getNeode, getDriver } from '../../db/neo4j'
|
||||||
import createServer from '../../server'
|
import createServer, { pubsub } from '../../server'
|
||||||
|
|
||||||
let server, query, mutate, notifiedUser, authenticatedUser
|
let server, query, mutate, notifiedUser, authenticatedUser
|
||||||
|
let publishSpy
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
const categoryIds = ['cat9']
|
const categoryIds = ['cat9']
|
||||||
@ -36,6 +37,7 @@ const createCommentMutation = gql`
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
publishSpy = jest.spyOn(pubsub, 'publish')
|
||||||
const createServerResult = createServer({
|
const createServerResult = createServer({
|
||||||
context: () => {
|
context: () => {
|
||||||
return {
|
return {
|
||||||
@ -52,6 +54,7 @@ beforeAll(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
publishSpy.mockClear()
|
||||||
notifiedUser = await neode.create(
|
notifiedUser = await neode.create(
|
||||||
'User',
|
'User',
|
||||||
{
|
{
|
||||||
@ -259,7 +262,15 @@ describe('notifications', () => {
|
|||||||
await createPostAction()
|
await createPostAction()
|
||||||
const expectedContent =
|
const expectedContent =
|
||||||
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone" target="_blank">@al-capone</a> how do you do?'
|
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone" target="_blank">@al-capone</a> how do you do?'
|
||||||
const expected = expect.objectContaining({
|
await expect(
|
||||||
|
query({
|
||||||
|
query: notificationQuery,
|
||||||
|
variables: {
|
||||||
|
read: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: undefined,
|
||||||
data: {
|
data: {
|
||||||
notifications: [
|
notifications: [
|
||||||
{
|
{
|
||||||
@ -275,15 +286,22 @@ describe('notifications', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
await expect(
|
it('publishes `NOTIFICATION_ADDED` to me', async () => {
|
||||||
query({
|
await createPostAction()
|
||||||
query: notificationQuery,
|
expect(publishSpy).toHaveBeenCalledWith(
|
||||||
variables: {
|
'NOTIFICATION_ADDED',
|
||||||
read: false,
|
expect.objectContaining({
|
||||||
},
|
notificationAdded: expect.objectContaining({
|
||||||
|
reason: 'mentioned_in_post',
|
||||||
|
to: expect.objectContaining({
|
||||||
|
id: 'you',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
).resolves.toEqual(expected)
|
)
|
||||||
|
expect(publishSpy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('updates the post and mentions me again', () => {
|
describe('updates the post and mentions me again', () => {
|
||||||
@ -429,6 +447,11 @@ describe('notifications', () => {
|
|||||||
}),
|
}),
|
||||||
).resolves.toEqual(expected)
|
).resolves.toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not publish `NOTIFICATION_ADDED`', async () => {
|
||||||
|
await createPostAction()
|
||||||
|
expect(publishSpy).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -554,10 +577,6 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
it('sends no notification', async () => {
|
it('sends no notification', async () => {
|
||||||
await createCommentOnPostAction()
|
await createCommentOnPostAction()
|
||||||
const expected = expect.objectContaining({
|
|
||||||
data: { notifications: [] },
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -565,7 +584,26 @@ describe('notifications', () => {
|
|||||||
read: false,
|
read: false,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toEqual(expected)
|
).resolves.toMatchObject({
|
||||||
|
data: { notifications: [] },
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not publish `NOTIFICATION_ADDED` to authenticated user', async () => {
|
||||||
|
await createCommentOnPostAction()
|
||||||
|
expect(publishSpy).toHaveBeenCalledWith(
|
||||||
|
'NOTIFICATION_ADDED',
|
||||||
|
expect.objectContaining({
|
||||||
|
notificationAdded: expect.objectContaining({
|
||||||
|
reason: 'commented_on_post',
|
||||||
|
to: expect.objectContaining({
|
||||||
|
id: 'postAuthor', // that's expected, it's not me but the post author
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
expect(publishSpy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user