From f3728af97bb8ebdd2d72e7568c206e395fb99153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Fri, 13 Dec 2019 13:54:51 +0100 Subject: [PATCH] First test driven approach to implement notification of report filing user --- .../notifications/notificationsMiddleware.js | 67 ++++++-- .../notificationsMiddleware.spec.js | 161 ++++++++++++++---- backend/src/schema/types/type/NOTIFIED.gql | 3 +- ...tionship_to_report_node_first_solution.sh} | 0 styleguide | 2 +- 5 files changed, 185 insertions(+), 48 deletions(-) rename neo4j/{change_disabled_relationship_to_report_node.sh => db_manipulation/change_disabled_relationship_to_report_node_first_solution.sh} (100%) diff --git a/backend/src/middleware/notifications/notificationsMiddleware.js b/backend/src/middleware/notifications/notificationsMiddleware.js index ac199a67d..505908f53 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.js @@ -45,10 +45,7 @@ const notifyUsers = async (label, id, idsOfUsers, reason, context) => { AND NOT (user)<-[:BLOCKED]-(author) MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user) SET notification.read = FALSE - SET ( - CASE - WHEN notification.createdAt IS NULL - THEN notification END ).createdAt = toString(datetime()) + SET ( CASE WHEN notification.createdAt IS NULL THEN notification END ).createdAt = toString(datetime()) SET notification.updatedAt = toString(datetime()) ` break @@ -62,10 +59,7 @@ const notifyUsers = async (label, id, idsOfUsers, reason, context) => { AND NOT (user)<-[:BLOCKED]-(postAuthor) MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user) SET notification.read = FALSE - SET ( - CASE - WHEN notification.createdAt IS NULL - THEN notification END ).createdAt = toString(datetime()) + SET ( CASE WHEN notification.createdAt IS NULL THEN notification END ).createdAt = toString(datetime()) SET notification.updatedAt = toString(datetime()) ` break @@ -79,10 +73,7 @@ const notifyUsers = async (label, id, idsOfUsers, reason, context) => { AND NOT (author)<-[:BLOCKED]-(user) MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user) SET notification.read = FALSE - SET ( - CASE - WHEN notification.createdAt IS NULL - THEN notification END ).createdAt = toString(datetime()) + SET ( CASE WHEN notification.createdAt IS NULL THEN notification END ).createdAt = toString(datetime()) SET notification.updatedAt = toString(datetime()) ` break @@ -154,11 +145,63 @@ const handleCreateComment = async (resolve, root, args, context, resolveInfo) => return comment } +const notifyReportFiler = async (resolve, root, args, context, resolveInfo) => { + // const comment = await handleContentDataOfComment(resolve, root, args, context, resolveInfo) + const report = await resolve(root, args, context, resolveInfo) + + if (report) { + console.log('If report !!!') + console.log('report: ', report) + console.log('args: ', args) + const { resourceId/* Wolle , reasonCategory, reasonDescription */ } = args + const { driver, user } = context + const { id: reportId } = report + console.log('resourceId: ', resourceId) + console.log('user.id: ', user.id) + console.log('reportId: ', reportId) + // Wolle await notifyUsers(report.resource.__typename, resourceId, [user.id], 'filed_report_on_resource', context) + const session = driver.session() + const notificationWriteTxResultPromise = session.writeTransaction(async transaction => { + const notificationTransactionResponse = await transaction.run( + ` + MATCH (resource {id: $resourceId})<-[:BELONGS_TO]-(:Report {id: $reportId})<-[:FILED]-(submitter:User {id: $submitterId}) + WHERE resource: User OR resource: Post OR resource: Comment + MERGE (resource)-[notification:NOTIFIED {reason: $reason, reportId: $reportId}]->(submitter) + ON CREATE SET notification.createdAt = toString(datetime()), notification.updatedAt = notification.createdAt + ON MERGE SET notification.updatedAt = toString(datetime()) + SET notification.read = FALSE + `, + { + reportId, + resourceId, + submitterId: user.id, + reason: 'filed_report_on_resource', + // Wolle reasonCategory, + // Wolle reasonDescription, + }, + ) + console.log('notificationTransactionResponse: ', notificationTransactionResponse) + log(notificationTransactionResponse) + // Wolle return notificationTransactionResponse.records.map(transformReturnType) + }) + try { + await notificationWriteTxResultPromise + // Wolle if (!createdRelationshipWithNestedAttributes) return null + // Wolle return createdRelationshipWithNestedAttributes + } finally { + session.close() + } + } + + return report +} + export default { Mutation: { CreatePost: handleContentDataOfPost, UpdatePost: handleContentDataOfPost, CreateComment: handleCreateComment, UpdateComment: handleContentDataOfComment, + fileReport: notifyReportFiler, }, } diff --git a/backend/src/middleware/notifications/notificationsMiddleware.spec.js b/backend/src/middleware/notifications/notificationsMiddleware.spec.js index 53fa80ce8..6134a7b7c 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.spec.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.spec.js @@ -38,6 +38,17 @@ const createCommentMutation = gql` } } ` +const fileReportMutation = gql ` + mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { + fileReport( + resourceId: $resourceId + reasonCategory: $reasonCategory + reasonDescription: $reasonDescription + ) { + id + } + } +` beforeAll(() => { const createServerResult = createServer({ @@ -96,46 +107,45 @@ describe('notifications', () => { } ` + let title + let postContent + let postAuthor + const createPostAction = async () => { + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createPostMutation, + variables: { + id: 'p47', + title, + postContent, + categoryIds, + }, + }) + authenticatedUser = await notifiedUser.toJson() + } + + let commentContent + let commentAuthor + const createCommentOnPostAction = async () => { + await createPostAction() + authenticatedUser = await commentAuthor.toJson() + await mutate({ + mutation: createCommentMutation, + variables: { + id: 'c47', + postId: 'p47', + commentContent, + }, + }) + authenticatedUser = await notifiedUser.toJson() + } + describe('authenticated', () => { beforeEach(async () => { authenticatedUser = await notifiedUser.toJson() }) describe('given another user', () => { - let title - let postContent - let postAuthor - - const createPostAction = async () => { - authenticatedUser = await postAuthor.toJson() - await mutate({ - mutation: createPostMutation, - variables: { - id: 'p47', - title, - postContent, - categoryIds, - }, - }) - authenticatedUser = await notifiedUser.toJson() - } - - let commentContent - let commentAuthor - const createCommentOnPostAction = async () => { - await createPostAction() - authenticatedUser = await commentAuthor.toJson() - await mutate({ - mutation: createCommentMutation, - variables: { - id: 'c47', - postId: 'p47', - commentContent, - }, - }) - authenticatedUser = await notifiedUser.toJson() - } - describe('comments on my post', () => { beforeEach(async () => { title = 'My post' @@ -545,5 +555,88 @@ describe('notifications', () => { }) }) }) + + describe('given me filing a report of a', () => { + let resourceId + let reasonCategory + let reasonDescription + let reportFiler + const fileReportAction = async () => { + authenticatedUser = await reportFiler.toJson() + await mutate({ + mutation: fileReportMutation, + variables: { + resourceId, + reasonCategory, + reasonDescription, + }, + }) + authenticatedUser = await notifiedUser.toJson() + } + + describe('user', () => { + }) + + describe('post', () => { + }) + + describe('comment', () => { + beforeEach(async () => { + title = 'My post' + postContent = 'My post content.' + postAuthor = await neode.create('User', { + id: 'postAuthor', + name: 'Mrs Post', + slug: 'mrs-post', + email: 'post-author@example.org', + password: '1234', + }) + + commentContent = 'Commenters comment.' + commentAuthor = await neode.create('User', { + id: 'commentAuthor', + name: 'Mrs Comment', + slug: 'mrs-comment', + email: 'commentauthor@example.org', + password: '1234', + }) + }) + + it.only('sends me a notification', async () => { + await createCommentOnPostAction() + resourceId = 'c47' + reasonCategory = 'discrimination_etc' + reasonDescription = 'I am free to be gay !!!' + reportFiler = notifiedUser + await fileReportAction() + + const expected = expect.objectContaining({ + data: { + notifications: [ + { + read: false, + createdAt: expect.any(String), + reason: 'filed_report_on_resource', + from: { + __typename: 'Comment', + id: 'c47', + content: commentContent, + }, + }, + ], + }, + }) + const { query } = createTestClient(server) + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toEqual(expected) + }) + }) + }) }) }) diff --git a/backend/src/schema/types/type/NOTIFIED.gql b/backend/src/schema/types/type/NOTIFIED.gql index af91460f7..9926d39cc 100644 --- a/backend/src/schema/types/type/NOTIFIED.gql +++ b/backend/src/schema/types/type/NOTIFIED.gql @@ -18,9 +18,10 @@ enum NotificationOrdering { } enum NotificationReason { + commented_on_post + filed_report_on_resource mentioned_in_post mentioned_in_comment - commented_on_post } type Query { diff --git a/neo4j/change_disabled_relationship_to_report_node.sh b/neo4j/db_manipulation/change_disabled_relationship_to_report_node_first_solution.sh similarity index 100% rename from neo4j/change_disabled_relationship_to_report_node.sh rename to neo4j/db_manipulation/change_disabled_relationship_to_report_node_first_solution.sh diff --git a/styleguide b/styleguide index 7ef834050..808b3c5a9 160000 --- a/styleguide +++ b/styleguide @@ -1 +1 @@ -Subproject commit 7ef83405006b016fe45b476ed6e34ec189d7d283 +Subproject commit 808b3c5a9523505cb80b20b50348d29ba9932845