mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-01-15 09:24:34 +00:00
Fix backend tests
This commit is contained in:
parent
ee60bf7e15
commit
32d5482597
@ -1,3 +1,4 @@
|
||||
import log from '../../schema/resolvers/helpers/databaseLogger'
|
||||
import extractMentionedUsers from './mentions/extractMentionedUsers'
|
||||
import { validateNotifyUsers } from '../validation/validationMiddleware'
|
||||
import { pubsub, NOTIFICATION_ADDED } from '../../server'
|
||||
@ -80,6 +81,7 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
||||
AND NOT (user)-[:BLOCKED]-(author)
|
||||
AND NOT (user)-[:BLOCKED]-(postAuthor)
|
||||
MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||
WITH comment AS resource, notification, user
|
||||
`
|
||||
break
|
||||
}
|
||||
@ -91,19 +93,19 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
||||
WITH resource, user, notification, authors, posts,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource
|
||||
SET notification.read = FALSE
|
||||
// Wolle SET ( CASE WHEN notification.createdAt IS NULL THEN notification END ).createdAt = toString(datetime())
|
||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||
SET notification.updatedAt = toString(datetime())
|
||||
RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
`
|
||||
const session = context.driver.session()
|
||||
const writeTxResultPromise = session.writeTransaction(async transaction => {
|
||||
const notificationTransactionResponse = await transaction.run(mentionedCypher, {
|
||||
const notificationsTransactionResponse = await transaction.run(mentionedCypher, {
|
||||
id,
|
||||
idsOfUsers,
|
||||
reason,
|
||||
})
|
||||
return notificationTransactionResponse.records.map(record => record.get('notification'))
|
||||
log(notificationsTransactionResponse)
|
||||
return notificationsTransactionResponse.records.map(record => record.get('notification'))
|
||||
})
|
||||
try {
|
||||
const notifications = await writeTxResultPromise
|
||||
@ -120,7 +122,7 @@ const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, cont
|
||||
await validateNotifyUsers(label, reason)
|
||||
const session = context.driver.session()
|
||||
const writeTxResultPromise = await session.writeTransaction(async transaction => {
|
||||
const notificationTransactionResponse = await transaction.run(
|
||||
const notificationsTransactionResponse = await transaction.run(
|
||||
`
|
||||
MATCH (postAuthor:User {id: $postAuthorId})-[:WROTE]->(post:Post)<-[:COMMENTS]-(comment:Comment { id: $commentId })<-[:WROTE]-(commenter:User)
|
||||
WHERE NOT (postAuthor)-[:BLOCKED]-(commenter)
|
||||
@ -134,7 +136,8 @@ const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, cont
|
||||
`,
|
||||
{ commentId, postAuthorId, reason },
|
||||
)
|
||||
return notificationTransactionResponse.records.map(record => record.get('notification'))
|
||||
log(notificationsTransactionResponse)
|
||||
return notificationsTransactionResponse.records.map(record => record.get('notification'))
|
||||
})
|
||||
try {
|
||||
const notifications = await writeTxResultPromise
|
||||
@ -146,41 +149,53 @@ const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, cont
|
||||
}
|
||||
}
|
||||
|
||||
const notifyReportFiler = async (resolve, root, args, context, resolveInfo) => {
|
||||
const report = await resolve(root, args, context, resolveInfo)
|
||||
const handleFileReport = async (resolve, root, args, context, resolveInfo) => {
|
||||
const filedReport = await resolve(root, args, context, resolveInfo)
|
||||
|
||||
if (report) {
|
||||
if (filedReport) {
|
||||
const { reportId } = filedReport
|
||||
const { resourceId } = args
|
||||
const { driver, user } = context
|
||||
const { id: reportId } = report
|
||||
const session = driver.session()
|
||||
try {
|
||||
await session.writeTransaction(async transaction => {
|
||||
await transaction.run(
|
||||
`
|
||||
MATCH (resource {id: $resourceId})<-[:BELONGS_TO]-(report:Report {id: $reportId})<-[:FILED]-(submitter:User {id: $submitterId})
|
||||
WHERE resource: User OR resource: Post OR resource: Comment
|
||||
MERGE (report)-[notification:NOTIFIED {reason: $reason}]->(submitter)
|
||||
ON CREATE SET notification.createdAt = toString(datetime()), notification.updatedAt = notification.createdAt
|
||||
ON MATCH SET notification.updatedAt = toString(datetime())
|
||||
SET notification.read = FALSE
|
||||
`,
|
||||
{
|
||||
reportId,
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
reason: 'filed_report_on_resource',
|
||||
},
|
||||
)
|
||||
})
|
||||
} catch (error) {
|
||||
debug(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
await publishNotifications(notifyReportFiler(reportId, resourceId, context))
|
||||
}
|
||||
|
||||
return report
|
||||
return filedReport
|
||||
}
|
||||
|
||||
const notifyReportFiler = async (reportId, resourceId, context) => {
|
||||
const { driver, user } = context
|
||||
const session = driver.session()
|
||||
const writeTxResultPromise = await session.writeTransaction(async transaction => {
|
||||
const notificationsTransactionResponse = await transaction.run(
|
||||
`
|
||||
MATCH (resource {id: $resourceId})<-[:BELONGS_TO]-(report:Report {id: $reportId})<-[filed:FILED]-(submitter:User {id: $submitterId})
|
||||
WHERE resource: User OR resource: Post OR resource: Comment
|
||||
MERGE (report)-[notification:NOTIFIED {reason: $reason}]->(submitter)
|
||||
ON CREATE SET notification.createdAt = toString(datetime()), notification.updatedAt = notification.createdAt
|
||||
ON MATCH SET notification.updatedAt = toString(datetime())
|
||||
SET notification.read = FALSE
|
||||
WITH notification, submitter,
|
||||
{__typename: "FiledReport", reportId: report.id, createdAt: filed.createdAt, reasonCategory: filed.reasonCategory, reasonDescription: filed.reasonDescription, resource: apoc.map.merge(properties(resource), {__typename: labels(resource)[0]})} AS finalResource
|
||||
RETURN notification {.*, from: finalResource, to: properties(submitter)}
|
||||
`,
|
||||
{
|
||||
reportId,
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
reason: 'filed_report_on_resource',
|
||||
},
|
||||
)
|
||||
log(notificationsTransactionResponse)
|
||||
return notificationsTransactionResponse.records.map(record => record.get('notification'))
|
||||
})
|
||||
try {
|
||||
const [notification] = await writeTxResultPromise
|
||||
if (notification) return [notification]
|
||||
else throw new Error(`Notification for filing a report could not be send!`)
|
||||
} catch (error) {
|
||||
debug(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
@ -189,6 +204,6 @@ export default {
|
||||
UpdatePost: handleContentDataOfPost,
|
||||
CreateComment: handleContentDataOfComment,
|
||||
UpdateComment: handleContentDataOfComment,
|
||||
fileReport: notifyReportFiler,
|
||||
fileReport: handleFileReport,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { gql } from '../../helpers/jest'
|
||||
import Factory, { cleanDatabase } from '../../factories'
|
||||
import Factory, { cleanDatabase } from '../../db/factories'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import { getDriver } from '../../db/neo4j'
|
||||
import createServer, { pubsub } from '../../server'
|
||||
@ -40,7 +40,7 @@ const fileReportMutation = gql`
|
||||
reasonCategory: $reasonCategory
|
||||
reasonDescription: $reasonDescription
|
||||
) {
|
||||
id
|
||||
reportId
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -64,6 +64,12 @@ beforeAll(async () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
publishSpy.mockClear()
|
||||
await Factory.build('category', {
|
||||
id: 'cat9',
|
||||
name: 'Democracy & Politics',
|
||||
slug: 'democracy-politics',
|
||||
icon: 'university',
|
||||
})
|
||||
notifiedUser = await Factory.build(
|
||||
'user',
|
||||
{
|
||||
@ -76,12 +82,7 @@ beforeEach(async () => {
|
||||
password: '1234',
|
||||
},
|
||||
)
|
||||
await Factory.build('category', {
|
||||
id: 'cat9',
|
||||
name: 'Democracy & Politics',
|
||||
slug: 'democracy-politics',
|
||||
icon: 'university',
|
||||
})
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
@ -89,7 +90,7 @@ afterEach(async () => {
|
||||
})
|
||||
|
||||
describe('notifications', () => {
|
||||
const notificationQuery = gql`
|
||||
const notificationsQuery = gql`
|
||||
query($read: Boolean) {
|
||||
notifications(read: $read, orderBy: updatedAt_desc) {
|
||||
createdAt
|
||||
@ -105,25 +106,23 @@ describe('notifications', () => {
|
||||
id
|
||||
content
|
||||
}
|
||||
... on Report {
|
||||
id
|
||||
filed {
|
||||
reasonCategory
|
||||
reasonDescription
|
||||
reportedResource {
|
||||
__typename
|
||||
... on User {
|
||||
id
|
||||
name
|
||||
}
|
||||
... on Post {
|
||||
id
|
||||
content
|
||||
}
|
||||
... on Comment {
|
||||
id
|
||||
content
|
||||
}
|
||||
... on FiledReport {
|
||||
reportId
|
||||
reasonCategory
|
||||
reasonDescription
|
||||
resource {
|
||||
__typename
|
||||
... on User {
|
||||
id
|
||||
name
|
||||
}
|
||||
... on Post {
|
||||
id
|
||||
content
|
||||
}
|
||||
... on Comment {
|
||||
id
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,7 +214,7 @@ describe('notifications', () => {
|
||||
})
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -232,7 +231,7 @@ describe('notifications', () => {
|
||||
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -256,7 +255,7 @@ describe('notifications', () => {
|
||||
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -275,7 +274,7 @@ describe('notifications', () => {
|
||||
slug: 'mrs-post',
|
||||
},
|
||||
{
|
||||
email: 'post-author@example.org',
|
||||
email: 'mrs-post-author@example.org',
|
||||
password: '1234',
|
||||
},
|
||||
)
|
||||
@ -295,7 +294,7 @@ describe('notifications', () => {
|
||||
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone" target="_blank">@al-capone</a> how do you do?'
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -387,7 +386,7 @@ describe('notifications', () => {
|
||||
})
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -416,7 +415,7 @@ describe('notifications', () => {
|
||||
notifications: [{ read: readBefore }],
|
||||
},
|
||||
} = await query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
})
|
||||
await updatePostAction()
|
||||
const {
|
||||
@ -424,7 +423,7 @@ describe('notifications', () => {
|
||||
notifications: [{ read: readAfter }],
|
||||
},
|
||||
} = await query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
})
|
||||
expect(readBefore).toEqual(true)
|
||||
expect(readAfter).toEqual(false)
|
||||
@ -438,7 +437,7 @@ describe('notifications', () => {
|
||||
notifications: [{ createdAt: createdAtBefore }],
|
||||
},
|
||||
} = await query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
})
|
||||
await updatePostAction()
|
||||
const {
|
||||
@ -446,7 +445,7 @@ describe('notifications', () => {
|
||||
notifications: [{ createdAt: createdAtAfter }],
|
||||
},
|
||||
} = await query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
})
|
||||
expect(createdAtBefore).toBeTruthy()
|
||||
expect(Date.parse(createdAtBefore)).toEqual(expect.any(Number))
|
||||
@ -471,7 +470,7 @@ describe('notifications', () => {
|
||||
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -519,7 +518,7 @@ describe('notifications', () => {
|
||||
slug: 'mr-author',
|
||||
},
|
||||
{
|
||||
email: 'post-author@example.org',
|
||||
email: 'mr-post-author@example.org',
|
||||
password: '1234',
|
||||
},
|
||||
)
|
||||
@ -544,7 +543,7 @@ describe('notifications', () => {
|
||||
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -557,6 +556,7 @@ describe('notifications', () => {
|
||||
postContent = 'Content of post where I get mentioned in a comment.'
|
||||
postAuthor = notifiedUser
|
||||
})
|
||||
|
||||
it('sends only one notification with reason commented_on_post, no notification with reason mentioned_in_comment', async () => {
|
||||
await createCommentOnPostAction()
|
||||
const expected = {
|
||||
@ -578,7 +578,7 @@ describe('notifications', () => {
|
||||
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -610,7 +610,7 @@ describe('notifications', () => {
|
||||
await createCommentOnPostAction()
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -641,11 +641,9 @@ describe('notifications', () => {
|
||||
})
|
||||
|
||||
describe('given I file a report on a', () => {
|
||||
let resourceId
|
||||
let resourceId, reportFiler, reportedUserOrAuthorData, expectedMeAsNotifiedForFilingReport
|
||||
const reasonCategory = 'discrimination_etc'
|
||||
const reasonDescription = 'I am free to be gay !!!'
|
||||
let reportFiler
|
||||
let reportedUserOrAuthorData
|
||||
const fileReportAction = async () => {
|
||||
authenticatedUser = await reportFiler.toJson()
|
||||
await mutate({
|
||||
@ -658,7 +656,7 @@ describe('notifications', () => {
|
||||
})
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
}
|
||||
const setExpectedNotificationOfReportedResource = reportedResource => {
|
||||
const setExpectedNotificationOfReportedResource = resource => {
|
||||
return expect.objectContaining({
|
||||
data: {
|
||||
notifications: [
|
||||
@ -667,15 +665,11 @@ describe('notifications', () => {
|
||||
read: false,
|
||||
reason: 'filed_report_on_resource',
|
||||
from: {
|
||||
__typename: 'Report',
|
||||
id: expect.any(String),
|
||||
filed: [
|
||||
{
|
||||
reasonCategory: 'discrimination_etc',
|
||||
reasonDescription: 'I am free to be gay !!!',
|
||||
reportedResource,
|
||||
},
|
||||
],
|
||||
__typename: 'FiledReport',
|
||||
reportId: expect.any(String),
|
||||
reasonCategory: 'discrimination_etc',
|
||||
reasonDescription: 'I am free to be gay !!!',
|
||||
resource,
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -686,20 +680,38 @@ describe('notifications', () => {
|
||||
beforeEach(async () => {
|
||||
reportFiler = notifiedUser
|
||||
reportedUserOrAuthorData = {
|
||||
id: 'reportedUser',
|
||||
name: 'Mrs Badman',
|
||||
slug: 'mrs-badman',
|
||||
email: 'reported-user@example.org',
|
||||
password: '1234',
|
||||
userProperties: {
|
||||
id: 'reportedUser',
|
||||
name: 'Mrs Badman',
|
||||
slug: 'mrs-badman',
|
||||
},
|
||||
emailProperties: {
|
||||
email: 'reported-user@example.org',
|
||||
password: '1234',
|
||||
},
|
||||
}
|
||||
expectedMeAsNotifiedForFilingReport = expect.objectContaining({
|
||||
notificationAdded: expect.objectContaining({
|
||||
reason: 'filed_report_on_resource',
|
||||
to: expect.objectContaining({
|
||||
id: 'you',
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
describe('user', () => {
|
||||
it('sends me a notification for filing a report on a user', async () => {
|
||||
await Factory.create('User', reportedUserOrAuthorData)
|
||||
resourceId = 'reportedUser'
|
||||
beforeEach(async () => {
|
||||
await Factory.build(
|
||||
'user',
|
||||
reportedUserOrAuthorData.userProperties,
|
||||
reportedUserOrAuthorData.emailProperties,
|
||||
)
|
||||
resourceId = reportedUserOrAuthorData.userProperties.id
|
||||
await fileReportAction()
|
||||
})
|
||||
|
||||
it('sends me a notification for filing a report on a user', async () => {
|
||||
const expected = setExpectedNotificationOfReportedResource({
|
||||
__typename: 'User',
|
||||
id: 'reportedUser',
|
||||
@ -708,28 +720,41 @@ describe('notifications', () => {
|
||||
const { query } = createTestClient(server)
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(expected)
|
||||
})
|
||||
|
||||
it('does publish `NOTIFICATION_ADDED` to authenticated user', async () => {
|
||||
expect(publishSpy).toHaveBeenCalledWith(
|
||||
'NOTIFICATION_ADDED',
|
||||
expectedMeAsNotifiedForFilingReport,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('post or comment', () => {
|
||||
beforeEach(async () => {
|
||||
title = 'My post'
|
||||
postContent = 'My post content.'
|
||||
postAuthor = await Factory.create('User', reportedUserOrAuthorData)
|
||||
postAuthor = await Factory.build(
|
||||
'user',
|
||||
reportedUserOrAuthorData.userProperties,
|
||||
reportedUserOrAuthorData.emailProperties,
|
||||
)
|
||||
})
|
||||
|
||||
describe('post', () => {
|
||||
it('sends me a notification for filing a report on a post', async () => {
|
||||
beforeEach(async () => {
|
||||
await createPostAction()
|
||||
resourceId = 'p47'
|
||||
await fileReportAction()
|
||||
})
|
||||
|
||||
it('sends me a notification for filing a report on a post', async () => {
|
||||
const expected = setExpectedNotificationOfReportedResource({
|
||||
__typename: 'Post',
|
||||
id: 'p47',
|
||||
@ -738,32 +763,43 @@ describe('notifications', () => {
|
||||
const { query } = createTestClient(server)
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(expected)
|
||||
})
|
||||
|
||||
it('does publish `NOTIFICATION_ADDED` to authenticated user', async () => {
|
||||
expect(publishSpy).toHaveBeenCalledWith(
|
||||
'NOTIFICATION_ADDED',
|
||||
expectedMeAsNotifiedForFilingReport,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('comment', () => {
|
||||
beforeEach(async () => {
|
||||
commentContent = "Commenter's comment."
|
||||
commentAuthor = await Factory.create('User', {
|
||||
id: 'commentAuthor',
|
||||
name: 'Mrs Comment',
|
||||
slug: 'mrs-comment',
|
||||
email: 'commentauthor@example.org',
|
||||
password: '1234',
|
||||
})
|
||||
})
|
||||
|
||||
it('sends me a notification for filing a report on a comment', async () => {
|
||||
commentAuthor = await Factory.build(
|
||||
'user',
|
||||
{
|
||||
id: 'commentAuthor',
|
||||
name: 'Mrs Comment',
|
||||
slug: 'mrs-comment',
|
||||
},
|
||||
{
|
||||
email: 'commentauthor@example.org',
|
||||
password: '1234',
|
||||
},
|
||||
)
|
||||
await createCommentOnPostAction()
|
||||
resourceId = 'c47'
|
||||
await fileReportAction()
|
||||
})
|
||||
|
||||
it('sends me a notification for filing a report on a comment', async () => {
|
||||
const expected = setExpectedNotificationOfReportedResource({
|
||||
__typename: 'Comment',
|
||||
id: 'c47',
|
||||
@ -772,7 +808,7 @@ describe('notifications', () => {
|
||||
const { query } = createTestClient(server)
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
query: notificationsQuery,
|
||||
variables: {
|
||||
read: false,
|
||||
},
|
||||
@ -780,20 +816,11 @@ describe('notifications', () => {
|
||||
).resolves.toEqual(expected)
|
||||
})
|
||||
|
||||
it('does not publish `NOTIFICATION_ADDED` to authenticated user', async () => {
|
||||
await createCommentOnPostAction()
|
||||
it('does publish `NOTIFICATION_ADDED` to authenticated user', async () => {
|
||||
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
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
expectedMeAsNotifiedForFilingReport,
|
||||
)
|
||||
expect(publishSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,6 +2,27 @@ import log from './helpers/databaseLogger'
|
||||
import { withFilter } from 'graphql-subscriptions'
|
||||
import { pubsub, NOTIFICATION_ADDED } from '../../server'
|
||||
|
||||
const cypherReturnNotificationsWithCollectedResourceData = `
|
||||
CALL apoc.case(
|
||||
[
|
||||
labels(resource)[0] = "Post", '
|
||||
MATCH (resource)<-[:WROTE]-(author:User)
|
||||
RETURN resource {.*, __typename: labels(resource)[0], author: author} AS finalResource',
|
||||
labels(resource)[0] = "Comment", '
|
||||
MATCH (author:User)-[:WROTE]->(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User)
|
||||
RETURN resource {.*, __typename: labels(resource)[0], author: author, post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})} AS finalResource',
|
||||
labels(resource)[0] = "Report", '
|
||||
MATCH (reportedResource)<-[:BELONGS_TO]-(resource)<-[filed:FILED]-(user)
|
||||
RETURN {__typename: "FiledReport", reportId: resource.id, createdAt: filed.createdAt, reasonCategory: filed.reasonCategory, reasonDescription: filed.reasonDescription, resource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} AS finalResource'
|
||||
],
|
||||
'',
|
||||
{
|
||||
resource: resource,
|
||||
user: user
|
||||
}) YIELD value
|
||||
RETURN notification {.*, from: value.finalResource, to: properties(user)}
|
||||
`
|
||||
|
||||
export default {
|
||||
Subscription: {
|
||||
notificationAdded: {
|
||||
@ -42,97 +63,87 @@ export default {
|
||||
const offset = args.offset && typeof args.offset === 'number' ? `SKIP ${args.offset}` : ''
|
||||
const limit = args.first && typeof args.first === 'number' ? `LIMIT ${args.first}` : ''
|
||||
|
||||
const cypher = `
|
||||
// Wolle MATCH (resource)-[notification:NOTIFIED]->(user:User {id:$id})
|
||||
// WHERE
|
||||
// ((labels(resource)[0] in ["Post", "Comment"] AND NOT resource.deleted AND NOT resource.disabled)
|
||||
// OR labels(resource)[0] in ["Report"])
|
||||
// $ {whereClause}
|
||||
// WITH user, notification, resource,
|
||||
// [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||
// [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author)} ] AS posts,
|
||||
// [(reportedResource)<-[:BELONGS_TO]-(resource)<-[file:FILED]-(user) | file {.*, reportedResource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} ] AS files
|
||||
// WITH resource, user, notification, authors, posts, files,
|
||||
// resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], filed: files, resource: files[0].reportedResource} AS finalResource
|
||||
// RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
// $ {orderByClause}
|
||||
// $ {offset} $ {limit}
|
||||
|
||||
MATCH (resource)-[notification:NOTIFIED]->(user:User {id:$id})
|
||||
WHERE
|
||||
((labels(resource)[0] in ["Post", "Comment"] AND NOT resource.deleted AND NOT resource.disabled)
|
||||
OR labels(resource)[0] in ["Report"])
|
||||
${whereClause}
|
||||
${cypherReturnNotificationsWithCollectedResourceData}
|
||||
// Wolle WITH resource, notification, user
|
||||
// MATCH (author:User)-[:WROTE]->(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User)
|
||||
// WITH resource, notification, user, author, post, postAuthor
|
||||
// resource {.*, __typename: labels(resource)[0], author: author, post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})} AS finalResource',
|
||||
// RETURN notification {.*, from: value.finalResource, to: properties(user)}
|
||||
${orderByClause}
|
||||
${offset} ${limit}
|
||||
|
||||
// Wolle
|
||||
// the UNION ALL with ORDER BY and SKIP, LIMIT is possible since Neo4j 4.0. See https://neo4j.com/docs/cypher-manual/4.0/clauses/call-subquery/#subquery-post-union
|
||||
// refactor the following to the new CALL {} subquery
|
||||
|
||||
// MATCH (author:User)-[:WROTE]->(post:Post)-[notification:NOTIFIED]->(user:User {id: $id})
|
||||
// WHERE NOT post.deleted AND NOT post.disabled
|
||||
// $ {whereClause}
|
||||
// WITH user, notification, post {.*, __typename: labels(post)[0], author: properties(author)}
|
||||
// RETURN notification {.*, from: post, to: properties(user)}
|
||||
|
||||
// UNION ALL
|
||||
// MATCH (author:User)-[:WROTE]->(comment:Comment)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User),
|
||||
// (comment)-[notification:NOTIFIED]->(user:User {id: $id})
|
||||
// WHERE NOT comment.deleted AND NOT comment.disabled
|
||||
// $ {whereClause}
|
||||
// WITH user, notification, comment {.*, __typename: labels(comment)[0], author: properties(author), post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})}
|
||||
// RETURN notification {.*, from: comment, to: properties(user)}
|
||||
|
||||
// UNION ALL
|
||||
// MATCH (reportedResource)<-[:BELONGS_TO]-(report)<-[file:FILED]-(user:User {id:$id}),
|
||||
// (report:Report)-[notification:NOTIFIED]->(user)
|
||||
// WHERE (reportedResource:User) OR (reportedResource:Post) OR (reportedResource:Comment)
|
||||
// $ {whereClause}
|
||||
// // Wolle - Here the three different case are not distinguished and therefore Post is not added to Comment and the authors are not added etc.
|
||||
// WITH
|
||||
// user,
|
||||
// notification,
|
||||
// {
|
||||
// __typename: "FiledReport",
|
||||
// createdAt: file.createdAt,
|
||||
// reasonCategory: file.reasonCategory,
|
||||
// reasonDescription: file.reasonDescription,
|
||||
// reportId: report.id,
|
||||
// resource: apoc.map.merge(properties(reportedResource), {
|
||||
// __typename: labels(reportedResource)[0]
|
||||
// })
|
||||
// } AS filedReport
|
||||
// RETURN notification {.*, from: filedReport, to: properties(user)}
|
||||
// $ {orderByClause}
|
||||
// $ {offset} $ {limit}
|
||||
`
|
||||
|
||||
const readTxResultPromise = session.readTransaction(async transaction => {
|
||||
const notificationsTransactionResponse = await transaction.run(
|
||||
`
|
||||
// Wolle MATCH (resource)-[notification:NOTIFIED]->(user:User {id:$id})
|
||||
// WHERE
|
||||
// ((labels(resource)[0] in ["Post", "Comment"] AND NOT resource.deleted AND NOT resource.disabled)
|
||||
// OR labels(resource)[0] in ["Report"])
|
||||
// ${whereClause}
|
||||
// WITH user, notification, resource,
|
||||
// [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||
// [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author)} ] AS posts,
|
||||
// [(reportedResource)<-[:BELONGS_TO]-(resource)<-[file:FILED]-(user) | file {.*, reportedResource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} ] AS files
|
||||
// WITH resource, user, notification, authors, posts, files,
|
||||
// resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], filed: files, resource: files[0].reportedResource} AS finalResource
|
||||
// RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
// ${orderByClause}
|
||||
// ${offset} ${limit}
|
||||
|
||||
MATCH (resource)-[notification:NOTIFIED]->(user:User {id:$id})
|
||||
WHERE
|
||||
((labels(resource)[0] in ["Post", "Comment"] AND NOT resource.deleted AND NOT resource.disabled)
|
||||
OR labels(resource)[0] in ["Report"])
|
||||
${whereClause}
|
||||
CALL apoc.case(
|
||||
[
|
||||
labels(resource)[0] = "Post", '
|
||||
MATCH (resource)<-[:WROTE]-(author:User)
|
||||
RETURN resource {.*, __typename: labels(resource)[0], author: author} AS finalResource',
|
||||
labels(resource)[0] = "Comment", '
|
||||
MATCH (author:User)-[:WROTE]->(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User)
|
||||
RETURN resource {.*, __typename: labels(resource)[0], author: author, post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})} AS finalResource',
|
||||
labels(resource)[0] = "Report", '
|
||||
MATCH (reportedResource)<-[:BELONGS_TO]-(resource)<-[filed:FILED]-(user)
|
||||
RETURN {__typename: "FiledReport", reportId: resource.id, createdAt: filed.createdAt, reasonCategory: filed.reasonCategory, reasonDescription: filed.reasonDescription, resource: apoc.map.merge(properties(reportedResource), {__typename: labels(reportedResource)[0]})} AS finalResource'
|
||||
],
|
||||
'',
|
||||
{
|
||||
resource: resource,
|
||||
user: user
|
||||
}) YIELD value
|
||||
RETURN notification {.*, from: value.finalResource, to: properties(user)}
|
||||
${orderByClause}
|
||||
${offset} ${limit}
|
||||
|
||||
// Wolle
|
||||
// the UNION ALL with ORDER BY and SKIP, LIMIT is possible since Neo4j 4.0. See https://neo4j.com/docs/cypher-manual/4.0/clauses/call-subquery/#subquery-post-union
|
||||
// refactor the following to the new CALL {} subquery
|
||||
// MATCH (author:User)-[:WROTE]->(post:Post)-[notification:NOTIFIED]->(user:User {id: $id})
|
||||
// WHERE NOT post.deleted AND NOT post.disabled
|
||||
// ${whereClause}
|
||||
// WITH user, notification, post {.*, __typename: labels(post)[0], author: properties(author)}
|
||||
// RETURN notification {.*, from: post, to: properties(user)}
|
||||
|
||||
// UNION ALL
|
||||
// MATCH (author:User)-[:WROTE]->(comment:Comment)-[:COMMENTS]->(post:Post)<-[:WROTE]-(postAuthor:User),
|
||||
// (comment)-[notification:NOTIFIED]->(user:User {id: $id})
|
||||
// WHERE NOT comment.deleted AND NOT comment.disabled
|
||||
// ${whereClause}
|
||||
// WITH user, notification, comment {.*, __typename: labels(comment)[0], author: properties(author), post: apoc.map.merge(properties(post), {__typename: labels(post)[0], author: properties(postAuthor)})}
|
||||
// RETURN notification {.*, from: comment, to: properties(user)}
|
||||
|
||||
// UNION ALL
|
||||
// MATCH (reportedResource)<-[:BELONGS_TO]-(report)<-[file:FILED]-(user:User {id:$id}),
|
||||
// (report:Report)-[notification:NOTIFIED]->(user)
|
||||
// WHERE (reportedResource:User) OR (reportedResource:Post) OR (reportedResource:Comment)
|
||||
// ${whereClause}
|
||||
// // Wolle - Here the three different case are not distinguished and therefore Post is not added to Comment and the authors are not added etc.
|
||||
// WITH
|
||||
// user,
|
||||
// notification,
|
||||
// {
|
||||
// __typename: "FiledReport",
|
||||
// createdAt: file.createdAt,
|
||||
// reasonCategory: file.reasonCategory,
|
||||
// reasonDescription: file.reasonDescription,
|
||||
// reportId: report.id,
|
||||
// resource: apoc.map.merge(properties(reportedResource), {
|
||||
// __typename: labels(reportedResource)[0]
|
||||
// })
|
||||
// } AS filedReport
|
||||
// RETURN notification {.*, from: filedReport, to: properties(user)}
|
||||
// ${orderByClause}
|
||||
// ${offset} ${limit}
|
||||
`,
|
||||
{ id: currentUser.id },
|
||||
)
|
||||
const notificationsTransactionResponse = await transaction.run(cypher, {
|
||||
id: currentUser.id,
|
||||
})
|
||||
log(notificationsTransactionResponse)
|
||||
// Wolle return notificationsTransactionResponse.records.map(record => record.get('notification'))
|
||||
const notification = notificationsTransactionResponse.records.map(record => record.get('notification'))
|
||||
// Wolle console.log('notification: ', notification)
|
||||
return notification
|
||||
const notifications = notificationsTransactionResponse.records.map(record =>
|
||||
record.get('notification'),
|
||||
)
|
||||
return notifications
|
||||
})
|
||||
try {
|
||||
const notifications = await readTxResultPromise
|
||||
@ -144,7 +155,7 @@ export default {
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
markAsRead: async (parent, args, context, resolveInfo) => {
|
||||
markAsRead: async (_parent, args, context, _resolveInfo) => {
|
||||
const { user: currentUser } = context
|
||||
const session = context.driver.session()
|
||||
const writeTxResultPromise = session.writeTransaction(async transaction => {
|
||||
@ -152,12 +163,8 @@ export default {
|
||||
`
|
||||
MATCH (resource {id: $resourceId})-[notification:NOTIFIED {read: FALSE}]->(user:User {id: $id})
|
||||
SET notification.read = TRUE
|
||||
WITH user, notification, resource,
|
||||
[(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
|
||||
WITH resource, user, notification, authors, posts,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource
|
||||
RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
WITH resource, notification, user
|
||||
${cypherReturnNotificationsWithCollectedResourceData}
|
||||
`,
|
||||
{
|
||||
resourceId: args.id,
|
||||
@ -170,8 +177,8 @@ export default {
|
||||
)
|
||||
})
|
||||
try {
|
||||
const [notifications] = await writeTxResultPromise
|
||||
return notifications
|
||||
const [notification] = await writeTxResultPromise
|
||||
return notification
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
|
||||
@ -344,8 +344,7 @@ describe('given some notifications', () => {
|
||||
resource: {
|
||||
__typename: 'Comment',
|
||||
id: 'c4',
|
||||
content:
|
||||
'I am harassing content in a harassing comment to a bad post !!!',
|
||||
content: 'I am harassing content in a harassing comment to a bad post !!!',
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -431,8 +430,7 @@ describe('given some notifications', () => {
|
||||
resource: {
|
||||
__typename: 'Comment',
|
||||
id: 'c4',
|
||||
content:
|
||||
'I am harassing content in a harassing comment to a bad post !!!',
|
||||
content: 'I am harassing content in a harassing comment to a bad post !!!',
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -533,8 +531,8 @@ describe('given some notifications', () => {
|
||||
... on Comment {
|
||||
content
|
||||
}
|
||||
... on Report {
|
||||
id
|
||||
... on FiledReport {
|
||||
reportId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ export const markAsReadMutation = i18n => {
|
||||
}
|
||||
}
|
||||
}
|
||||
... on Report {
|
||||
... on FiledReport {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user