mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2026-01-20 20:01:22 +00:00
return user from follow/unfollow mutation
This commit is contained in:
parent
eeee5f8e9b
commit
7d048b029d
@ -1,51 +1,44 @@
|
||||
import { neode as getNeode } from '../../bootstrap/neo4j'
|
||||
|
||||
const neode = getNeode()
|
||||
|
||||
export default {
|
||||
Mutation: {
|
||||
follow: async (_object, params, context, _resolveInfo) => {
|
||||
const { id, type } = params
|
||||
const { id: followedId, type } = params
|
||||
const { user: currentUser } = context
|
||||
|
||||
const session = context.driver.session()
|
||||
const transactionRes = await session.run(
|
||||
`MATCH (node {id: $id}), (user:User {id: $userId})
|
||||
WHERE $type IN labels(node) AND NOT $id = $userId
|
||||
MERGE (user)-[relation:FOLLOWS]->(node)
|
||||
RETURN COUNT(relation) > 0 as isFollowed`,
|
||||
{
|
||||
id,
|
||||
type,
|
||||
userId: context.user.id,
|
||||
},
|
||||
)
|
||||
if (type === 'User' && currentUser.id === followedId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const [isFollowed] = transactionRes.records.map(record => {
|
||||
return record.get('isFollowed')
|
||||
})
|
||||
|
||||
session.close()
|
||||
|
||||
return isFollowed
|
||||
const [user, followedNode] = await Promise.all([
|
||||
neode.find('User', currentUser.id),
|
||||
neode.find(type, followedId),
|
||||
])
|
||||
await user.relateTo(followedNode, 'following')
|
||||
return followedNode.toJson()
|
||||
},
|
||||
|
||||
unfollow: async (_object, params, context, _resolveInfo) => {
|
||||
const { id, type } = params
|
||||
const session = context.driver.session()
|
||||
const { id: followedId, type } = params
|
||||
const { user: currentUser } = context
|
||||
|
||||
const transactionRes = await session.run(
|
||||
`MATCH (user:User {id: $userId})-[relation:FOLLOWS]->(node {id: $id})
|
||||
/*
|
||||
* Note: Neode doesn't provide an easy method for retrieving or removing relationships.
|
||||
* It's suggested to use query builder feature (https://github.com/adam-cowley/neode/issues/67)
|
||||
* However, pure cypher query looks cleaner IMO
|
||||
*/
|
||||
await neode.cypher(
|
||||
`MATCH (user:User {id: $currentUser.id})-[relation:FOLLOWS]->(node {id: $followedId})
|
||||
WHERE $type IN labels(node)
|
||||
DELETE relation
|
||||
RETURN COUNT(relation) > 0 as isFollowed`,
|
||||
{
|
||||
id,
|
||||
type,
|
||||
userId: context.user.id,
|
||||
},
|
||||
{ followedId, type, currentUser },
|
||||
)
|
||||
const [isFollowed] = transactionRes.records.map(record => {
|
||||
return record.get('isFollowed')
|
||||
})
|
||||
session.close()
|
||||
|
||||
return isFollowed
|
||||
const followedNode = await neode.find(type, followedId)
|
||||
return followedNode.toJson()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -17,13 +17,27 @@ let variables
|
||||
|
||||
const mutationFollowUser = gql`
|
||||
mutation($id: ID!, $type: FollowTypeEnum) {
|
||||
follow(id: $id, type: $type)
|
||||
follow(id: $id, type: $type) {
|
||||
name
|
||||
followedBy {
|
||||
id
|
||||
name
|
||||
}
|
||||
followedByCurrentUser
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const mutationUnfollowUser = gql`
|
||||
mutation($id: ID!, $type: FollowTypeEnum) {
|
||||
unfollow(id: $id, type: $type)
|
||||
unfollow(id: $id, type: $type) {
|
||||
name
|
||||
followedBy {
|
||||
id
|
||||
name
|
||||
}
|
||||
followedByCurrentUser
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@ -58,6 +72,7 @@ beforeEach(async () => {
|
||||
user1 = await factory
|
||||
.create('User', {
|
||||
id: 'u1',
|
||||
name: 'user1',
|
||||
email: 'test@example.org',
|
||||
password: '1234',
|
||||
})
|
||||
@ -65,6 +80,7 @@ beforeEach(async () => {
|
||||
user2 = await factory
|
||||
.create('User', {
|
||||
id: 'u2',
|
||||
name: 'user2',
|
||||
email: 'test2@example.org',
|
||||
password: '1234',
|
||||
})
|
||||
@ -81,39 +97,34 @@ afterEach(async () => {
|
||||
describe('follow', () => {
|
||||
describe('follow user', () => {
|
||||
describe('unauthenticated follow', () => {
|
||||
it('throws authorization error', async () => {
|
||||
test('throws authorization error', async () => {
|
||||
authenticatedUser = null
|
||||
const { errors } = await mutate({
|
||||
const { errors, data } = await mutate({
|
||||
mutation: mutationFollowUser,
|
||||
variables,
|
||||
})
|
||||
expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||
expect(data).toMatchObject({ follow: null })
|
||||
})
|
||||
})
|
||||
|
||||
it('I can follow another user', async () => {
|
||||
test('I can follow another user', async () => {
|
||||
const { data: result } = await mutate({
|
||||
mutation: mutationFollowUser,
|
||||
variables,
|
||||
})
|
||||
const expectedResult = { follow: true }
|
||||
expect(result).toMatchObject(expectedResult)
|
||||
|
||||
const { data } = await query({
|
||||
query: userQuery,
|
||||
variables: { id: user2.id },
|
||||
})
|
||||
const expectedUser = {
|
||||
followedBy: [{ id: user1.id }],
|
||||
name: user2.name,
|
||||
followedBy: [{ id: user1.id, name: user1.name }],
|
||||
followedByCurrentUser: true,
|
||||
}
|
||||
expect(data).toMatchObject({ User: [expectedUser] })
|
||||
expect(result).toMatchObject({ follow: expectedUser })
|
||||
})
|
||||
|
||||
it('I can`t follow myself', async () => {
|
||||
test('I can`t follow myself', async () => {
|
||||
variables.id = user1.id
|
||||
const { data: result } = await mutate({ mutation: mutationFollowUser, variables })
|
||||
const expectedResult = { follow: false }
|
||||
const expectedResult = { follow: null }
|
||||
expect(result).toMatchObject(expectedResult)
|
||||
|
||||
const { data } = await query({
|
||||
@ -137,27 +148,22 @@ describe('follow', () => {
|
||||
})
|
||||
|
||||
describe('unauthenticated follow', () => {
|
||||
it('throws authorization error', async () => {
|
||||
test('throws authorization error', async () => {
|
||||
authenticatedUser = null
|
||||
const { errors } = await mutate({ mutation: mutationUnfollowUser, variables })
|
||||
const { errors, data } = await mutate({ mutation: mutationUnfollowUser, variables })
|
||||
expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||
expect(data).toMatchObject({ unfollow: null })
|
||||
})
|
||||
})
|
||||
|
||||
it('I can unfollow a user', async () => {
|
||||
const { data: result } = await mutate({ mutation: mutationUnfollowUser, variables })
|
||||
const expectedResult = { unfollow: true }
|
||||
expect(result).toMatchObject(expectedResult)
|
||||
|
||||
const { data } = await query({
|
||||
query: userQuery,
|
||||
variables: { id: user2.id },
|
||||
})
|
||||
const expectedUser = {
|
||||
name: user2.name,
|
||||
followedBy: [],
|
||||
followedByCurrentUser: false,
|
||||
}
|
||||
expect(data).toMatchObject({ User: [expectedUser] })
|
||||
expect(result).toMatchObject({ unfollow: expectedUser })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -32,9 +32,9 @@ type Mutation {
|
||||
# Unshout the given Type and ID
|
||||
unshout(id: ID!, type: ShoutTypeEnum): Boolean!
|
||||
# Follow the given Type and ID
|
||||
follow(id: ID!, type: FollowTypeEnum): Boolean!
|
||||
follow(id: ID!, type: FollowTypeEnum): User
|
||||
# Unfollow the given Type and ID
|
||||
unfollow(id: ID!, type: FollowTypeEnum): Boolean!
|
||||
unfollow(id: ID!, type: FollowTypeEnum): User
|
||||
}
|
||||
|
||||
type Report {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user