From 3a058443562c657aa8954be046898e740e523500 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Wed, 27 Nov 2019 17:31:51 +0100 Subject: [PATCH] Refactor tests/resolvers - Favor union as it's cleaner and less code - refactor tests to new implementation - add reviewedByModerator resolver --- backend/src/schema/resolvers/reports.js | 110 +++++++-------- backend/src/schema/resolvers/reports.spec.js | 133 +++++++------------ backend/src/schema/types/type/Report.gql | 9 +- 3 files changed, 100 insertions(+), 152 deletions(-) diff --git a/backend/src/schema/resolvers/reports.js b/backend/src/schema/resolvers/reports.js index a79ab65ae..9269c9751 100644 --- a/backend/src/schema/resolvers/reports.js +++ b/backend/src/schema/resolvers/reports.js @@ -1,3 +1,13 @@ +const transformReturnType = record => { + return { + ...record.get('report').properties, + to: { + __typename: record.get('type'), + ...record.get('resource').properties, + }, + } +} + export default { Mutation: { fileReport: async (_parent, params, context, _resolveInfo) => { @@ -5,21 +15,18 @@ export default { const { resourceId, reasonCategory, reasonDescription } = params const { driver, user } = context const session = driver.session() - const writeTxResultPromise = session.writeTransaction(async txc => { - const reportRelationshipTransactionResponse = await txc.run( + const reportWriteTxResultPromise = session.writeTransaction(async txc => { + const reportTransactionResponse = await txc.run( ` MATCH (submitter:User {id: $submitterId}) MATCH (resource {id: $resourceId}) WHERE resource:User OR resource:Post OR resource:Comment - // no open report, create one MERGE (resource)<-[:BELONGS_TO]-(report:Report {closed: false}) ON CREATE SET report.id = randomUUID(), report.createdAt = $createdAt, report.updatedAt = report.createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = resource.disabled, report.closed = false - // ON MATCH: do not update report.updatedAt !!! that is only for reviews! - // Create report to report WITH submitter, resource, report CREATE (report)<-[filed:FILED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter) - RETURN submitter, report, resource, labels(resource)[0] AS type + RETURN report, resource, labels(resource)[0] AS type `, { resourceId, @@ -29,36 +36,12 @@ export default { reasonDescription, }, ) - return reportRelationshipTransactionResponse.records.map(record => ({ - submitter: record.get('submitter').properties, - report: record.get('report').properties, - resource: record.get('resource').properties, - type: record.get('type'), - })) + return reportTransactionResponse.records.map(transformReturnType) }) try { - const txResult = await writeTxResultPromise + const txResult = await reportWriteTxResultPromise if (!txResult[0]) return null - const { submitter, report, resource, type } = txResult[0] - createdRelationshipWithNestedAttributes = { - ...report, - post: null, - comment: null, - user: null, - submitter, - type, - } - switch (type) { - case 'Post': - createdRelationshipWithNestedAttributes.post = resource - break - case 'Comment': - createdRelationshipWithNestedAttributes.comment = resource - break - case 'User': - createdRelationshipWithNestedAttributes.user = resource - break - } + createdRelationshipWithNestedAttributes = txResult[0] } finally { session.close() } @@ -85,44 +68,17 @@ export default { ` MATCH (submitter:User)-[filed:FILED]->(report:Report)-[:BELONGS_TO]->(resource) WHERE resource:User OR resource:Post OR resource:Comment - RETURN submitter, report, resource, labels(resource)[0] as type + RETURN DISTINCT report, resource, labels(resource)[0] as type ${orderByClause} `, {}, ) - return allReportsTransactionResponse.records.map(record => ({ - submitter: record.get('submitter').properties, - report: record.get('report').properties, - resource: record.get('resource').properties, - type: record.get('type'), - })) + return allReportsTransactionResponse.records.map(transformReturnType) }) try { const txResult = await readTxPromise if (!txResult[0]) return null - reports = txResult.map(reportedRecord => { - const { report, submitter, resource, type } = reportedRecord - const relationshipWithNestedAttributes = { - ...report, - post: null, - comment: null, - user: null, - submitter, - type, - } - switch (type) { - case 'Post': - relationshipWithNestedAttributes.post = resource - break - case 'Comment': - relationshipWithNestedAttributes.comment = resource - break - case 'User': - relationshipWithNestedAttributes.user = resource - break - } - return relationshipWithNestedAttributes - }) + reports = txResult } finally { session.close() } @@ -164,5 +120,33 @@ export default { } return reportsFiled }, + reviewedByModerator: async (parent, _params, context, _resolveInfo) => { + if (typeof parent.reviewedByModerator !== 'undefined') return parent.reviewedByModerator + const session = context.driver.session() + const { id } = parent + let reviewedByModerator + const readTxPromise = session.readTransaction(async tx => { + const allReportsTransactionResponse = await tx.run( + ` + MATCH (resource)<-[:BELONGS_TO]-(report:Report {id: $id})<-[review:REVIEWED]-(moderator:User) + RETURN moderator + ORDER BY report.updatedAt DESC, review.updatedAt DESC + LIMIT 1 + `, + { id }, + ) + return allReportsTransactionResponse.records.map( + record => record.get('moderator').properties, + ) + }) + try { + const txResult = await readTxPromise + if (!txResult[0]) return null + reviewedByModerator = txResult[0] + } finally { + session.close() + } + return reviewedByModerator + }, }, } diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 9f66bb690..e5552497d 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -23,15 +23,17 @@ describe('file a report on a resource', () => { updatedAt disable closed - type - user { - name - } - post { - title - } - comment { - content + to { + __typename + ... on User { + name + } + ... on Post { + title + } + ... on Comment { + content + } } reportsFiled { submitter { @@ -130,14 +132,6 @@ describe('file a report on a resource', () => { data: { fileReport: { id: expect.any(String), - createdAt: expect.any(String), - updatedAt: expect.any(String), - disable: false, - closed: false, - user: { - name: 'abusive-user', - }, - type: 'User', }, }, errors: undefined, @@ -157,11 +151,11 @@ describe('file a report on a resource', () => { expect(firstReport.data.fileReport.id).toEqual(secondReport.data.fileReport.id) }) - it.todo('creates multiple reports') + it.todo('creates multiple filed reports') }) describe('reported resource is a user', () => { - it('returns type "User"', async () => { + it('returns __typename "User"', async () => { await expect( mutate({ mutation: reportMutation, @@ -170,29 +164,16 @@ describe('file a report on a resource', () => { ).resolves.toMatchObject({ data: { fileReport: { - id: expect.any(String), - createdAt: expect.any(String), - updatedAt: expect.any(String), - disable: false, - closed: false, - type: 'User', - reportsFiled: [ - { - submitter: { - id: 'current-user-id', - }, - createdAt: expect.any(String), - reasonCategory: 'other', - reasonDescription: 'Violates code of conduct !!!', - }, - ], + to: { + __typename: 'User', + }, }, }, errors: undefined, }) }) - it('returns resource in user attribute', async () => { + it('returns user attribute info', async () => { await expect( mutate({ mutation: reportMutation, @@ -201,7 +182,8 @@ describe('file a report on a resource', () => { ).resolves.toMatchObject({ data: { fileReport: { - user: { + to: { + __typename: 'User', name: 'abusive-user', }, }, @@ -364,7 +346,9 @@ describe('file a report on a resource', () => { ).resolves.toMatchObject({ data: { fileReport: { - type: 'Post', + to: { + __typename: 'Post', + }, }, }, errors: undefined, @@ -383,7 +367,8 @@ describe('file a report on a resource', () => { ).resolves.toMatchObject({ data: { fileReport: { - post: { + to: { + __typename: 'Post', title: 'This is a post that is going to be reported', }, }, @@ -391,25 +376,6 @@ describe('file a report on a resource', () => { errors: undefined, }) }) - - it('returns null in user attribute', async () => { - await expect( - mutate({ - mutation: reportMutation, - variables: { - ...variables, - resourceId: 'post-to-report-id', - }, - }), - ).resolves.toMatchObject({ - data: { - fileReport: { - user: null, - }, - }, - errors: undefined, - }) - }) }) describe('reported resource is a comment', () => { @@ -442,7 +408,9 @@ describe('file a report on a resource', () => { ).resolves.toMatchObject({ data: { fileReport: { - type: 'Comment', + to: { + __typename: 'Comment', + }, }, }, errors: undefined, @@ -461,7 +429,8 @@ describe('file a report on a resource', () => { ).resolves.toMatchObject({ data: { fileReport: { - comment: { + to: { + __typename: 'Comment', content: 'Post comment to be reported.', }, }, @@ -506,15 +475,17 @@ describe('file a report on a resource', () => { updatedAt disable closed - type - user { - id - } - post { - id - } - comment { - id + to { + __typename + ... on User { + id + } + ... on Post { + id + } + ... on Comment { + id + } } reportsFiled { submitter { @@ -639,12 +610,10 @@ describe('file a report on a resource', () => { updatedAt: expect.any(String), disable: false, closed: false, - type: 'User', - user: expect.objectContaining({ + to: { + __typename: 'User', id: 'abusive-user-1', - }), - post: null, - comment: null, + }, reportsFiled: expect.arrayContaining([ expect.objectContaining({ submitter: expect.objectContaining({ @@ -662,12 +631,10 @@ describe('file a report on a resource', () => { updatedAt: expect.any(String), disable: false, closed: false, - type: 'Post', - user: null, - post: expect.objectContaining({ + to: { + __typename: 'Post', id: 'abusive-post-1', - }), - comment: null, + }, reportsFiled: expect.arrayContaining([ expect.objectContaining({ submitter: expect.objectContaining({ @@ -685,12 +652,10 @@ describe('file a report on a resource', () => { updatedAt: expect.any(String), disable: false, closed: false, - type: 'Comment', - user: null, - post: null, - comment: expect.objectContaining({ + to: { + __typename: 'Comment', id: 'abusive-comment-1', - }), + }, reportsFiled: expect.arrayContaining([ expect.objectContaining({ submitter: expect.objectContaining({ diff --git a/backend/src/schema/types/type/Report.gql b/backend/src/schema/types/type/Report.gql index ce4e511f8..6dee7f282 100644 --- a/backend/src/schema/types/type/Report.gql +++ b/backend/src/schema/types/type/Report.gql @@ -6,13 +6,12 @@ type Report { disable: Boolean! closed: Boolean! reportsFiled: [FILED] - user: User - post: Post - comment: Comment + to: ReportedResource type: String + reviewedByModerator: User } -# not yet supported -# union ReportResource = User | Post | Comment + +union ReportedResource = User | Post | Comment enum ReportRule { latestReviewUpdatedAtRules