Refactor tests/resolvers

- Favor union as it's cleaner and less code
- refactor tests to new implementation
- add reviewedByModerator resolver
This commit is contained in:
mattwr18 2019-11-27 17:31:51 +01:00
parent d03d669056
commit 3a05844356
3 changed files with 100 additions and 152 deletions

View File

@ -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
},
},
}

View File

@ -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({

View File

@ -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