mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
parent
fa033e69bd
commit
39a94a8aac
@ -27,12 +27,6 @@ const onlyYourself = rule({
|
|||||||
return context.user.id === args.id
|
return context.user.id === args.id
|
||||||
})
|
})
|
||||||
|
|
||||||
const isMyEmotion = rule({
|
|
||||||
cache: 'no_cache',
|
|
||||||
})(async (parent, args, context, info) => {
|
|
||||||
return context.user.id === args.from.id
|
|
||||||
})
|
|
||||||
|
|
||||||
const isMyOwn = rule({
|
const isMyOwn = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (parent, args, context, info) => {
|
})(async (parent, args, context, info) => {
|
||||||
@ -163,8 +157,8 @@ const permissions = shield(
|
|||||||
User: or(noEmailFilter, isAdmin),
|
User: or(noEmailFilter, isAdmin),
|
||||||
isLoggedIn: allow,
|
isLoggedIn: allow,
|
||||||
Badge: allow,
|
Badge: allow,
|
||||||
postsEmotionsCountByEmotion: allow,
|
PostsEmotionsCountByEmotion: allow,
|
||||||
postsEmotionsCountByCurrentUser: allow,
|
PostsEmotionsByCurrentUser: allow,
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
'*': deny,
|
'*': deny,
|
||||||
@ -200,7 +194,7 @@ const permissions = shield(
|
|||||||
requestPasswordReset: allow,
|
requestPasswordReset: allow,
|
||||||
resetPassword: allow,
|
resetPassword: allow,
|
||||||
AddPostEmotions: isAuthenticated,
|
AddPostEmotions: isAuthenticated,
|
||||||
RemovePostEmotions: isMyEmotion,
|
RemovePostEmotions: isAuthenticated,
|
||||||
},
|
},
|
||||||
User: {
|
User: {
|
||||||
email: isMyOwn,
|
email: isMyOwn,
|
||||||
|
|||||||
34
backend/src/models/Post.js
Normal file
34
backend/src/models/Post.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import uuid from 'uuid/v4'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
id: { type: 'string', primary: true, default: uuid },
|
||||||
|
activityId: { type: 'string', allow: [null] },
|
||||||
|
objectId: { type: 'string', allow: [null] },
|
||||||
|
author: {
|
||||||
|
type: 'relationship',
|
||||||
|
relationship: 'WROTE',
|
||||||
|
target: 'User',
|
||||||
|
direction: 'in',
|
||||||
|
},
|
||||||
|
title: { type: 'string', disallow: [null], min: 3 },
|
||||||
|
slug: { type: 'string', allow: [null] },
|
||||||
|
content: { type: 'string', disallow: [null], min: 3 },
|
||||||
|
contentExcerpt: { type: 'string', allow: [null] },
|
||||||
|
image: { type: 'string', allow: [null] },
|
||||||
|
deleted: { type: 'boolean', default: false },
|
||||||
|
disabled: { type: 'boolean', default: false },
|
||||||
|
disabledBy: {
|
||||||
|
type: 'relationship',
|
||||||
|
relationship: 'DISABLED',
|
||||||
|
target: 'User',
|
||||||
|
direction: 'in',
|
||||||
|
},
|
||||||
|
createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
|
||||||
|
updatedAt: {
|
||||||
|
type: 'string',
|
||||||
|
isoDate: true,
|
||||||
|
required: true,
|
||||||
|
default: () => new Date().toISOString(),
|
||||||
|
},
|
||||||
|
language: { type: 'string', allow: [null] },
|
||||||
|
}
|
||||||
@ -56,4 +56,19 @@ module.exports = {
|
|||||||
required: true,
|
required: true,
|
||||||
default: () => new Date().toISOString(),
|
default: () => new Date().toISOString(),
|
||||||
},
|
},
|
||||||
|
emoted: {
|
||||||
|
type: 'relationships',
|
||||||
|
relationship: 'EMOTED',
|
||||||
|
target: 'Post',
|
||||||
|
direction: 'out',
|
||||||
|
properties: {
|
||||||
|
emotion: {
|
||||||
|
type: 'string',
|
||||||
|
valid: ['happy', 'cry', 'surprised', 'angry', 'funny'],
|
||||||
|
invalid: [null],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
eager: true,
|
||||||
|
cascade: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,4 +6,5 @@ export default {
|
|||||||
InvitationCode: require('./InvitationCode.js'),
|
InvitationCode: require('./InvitationCode.js'),
|
||||||
EmailAddress: require('./EmailAddress.js'),
|
EmailAddress: require('./EmailAddress.js'),
|
||||||
SocialMedia: require('./SocialMedia.js'),
|
SocialMedia: require('./SocialMedia.js'),
|
||||||
|
Post: require('./Post.js'),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -92,23 +92,25 @@ export default {
|
|||||||
},
|
},
|
||||||
RemovePostEmotions: async (object, params, context, resolveInfo) => {
|
RemovePostEmotions: async (object, params, context, resolveInfo) => {
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const { from, to, data } = params
|
const { to, data } = params
|
||||||
|
const { id: from } = context.user
|
||||||
const transactionRes = await session.run(
|
const transactionRes = await session.run(
|
||||||
`MATCH (userFrom:User {id: $from.id})-[emotedRelation:EMOTED {emotion: $data.emotion}]->(postTo:Post {id: $to.id})
|
`MATCH (userFrom:User {id: $from})-[emotedRelation:EMOTED {emotion: $data.emotion}]->(postTo:Post {id: $to.id})
|
||||||
DELETE emotedRelation
|
DELETE emotedRelation
|
||||||
|
RETURN userFrom
|
||||||
`,
|
`,
|
||||||
{ from, to, data },
|
{ from, to, data },
|
||||||
)
|
)
|
||||||
session.close()
|
session.close()
|
||||||
const [emoted] = transactionRes.records.map(record => {
|
const [userFrom] = transactionRes.records.map(record => {
|
||||||
return record.get('emotedRelation').properties.emotion
|
return record.get('userFrom')
|
||||||
})
|
})
|
||||||
|
if (!userFrom) throw new Error('Not Authorised!')
|
||||||
return !emoted
|
return Boolean(userFrom)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Query: {
|
Query: {
|
||||||
postsEmotionsCountByEmotion: async (object, params, context, resolveInfo) => {
|
PostsEmotionsCountByEmotion: async (object, params, context, resolveInfo) => {
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const { postId, data } = params
|
const { postId, data } = params
|
||||||
const transactionRes = await session.run(
|
const transactionRes = await session.run(
|
||||||
@ -125,22 +127,21 @@ export default {
|
|||||||
|
|
||||||
return emotionsCount
|
return emotionsCount
|
||||||
},
|
},
|
||||||
postsEmotionsCountByCurrentUser: async (object, params, context, resolveInfo) => {
|
PostsEmotionsByCurrentUser: async (object, params, context, resolveInfo) => {
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const { postId } = params
|
const { postId } = params
|
||||||
const transactionRes = await session.run(
|
const transactionRes = await session.run(
|
||||||
`MATCH (user:User {id: $userId})-[emoted:EMOTED]->(post:Post {id: $postId})
|
`MATCH (user:User {id: $userId})-[emoted:EMOTED]->(post:Post {id: $postId})
|
||||||
RETURN emoted.emotion as emotion`,
|
RETURN collect(emoted.emotion) as emotion`,
|
||||||
{ userId: context.user.id, postId },
|
{ userId: context.user.id, postId },
|
||||||
)
|
)
|
||||||
|
|
||||||
session.close()
|
session.close()
|
||||||
const emotionsArray = []
|
|
||||||
transactionRes.records.map(record => {
|
|
||||||
emotionsArray.push(record.get('emotion'))
|
|
||||||
})
|
|
||||||
|
|
||||||
return emotionsArray
|
const [emotions] = transactionRes.records.map(record => {
|
||||||
|
return record.get('emotion')
|
||||||
|
})
|
||||||
|
return emotions
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -406,15 +406,17 @@ describe('emotions', () => {
|
|||||||
owner,
|
owner,
|
||||||
postMutationAction,
|
postMutationAction,
|
||||||
user,
|
user,
|
||||||
postQueryAction
|
postQueryAction,
|
||||||
const postEmotionsCountQuery = `
|
postToEmote,
|
||||||
|
postToEmoteNode
|
||||||
|
const PostsEmotionsCountQuery = `
|
||||||
query($id: ID!) {
|
query($id: ID!) {
|
||||||
Post(id: $id) {
|
Post(id: $id) {
|
||||||
emotionsCount
|
emotionsCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const postEmotionsQuery = `
|
const PostsEmotionsQuery = `
|
||||||
query($id: ID!) {
|
query($id: ID!) {
|
||||||
Post(id: $id) {
|
Post(id: $id) {
|
||||||
emotions {
|
emotions {
|
||||||
@ -425,14 +427,27 @@ describe('emotions', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
`
|
||||||
|
const addPostEmotionsMutation = `
|
||||||
|
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
||||||
|
AddPostEmotions(from: $from, to: $to, data: $data) {
|
||||||
|
from { id }
|
||||||
|
to { id }
|
||||||
|
emotion
|
||||||
|
}
|
||||||
|
}
|
||||||
`
|
`
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
userParams.id = 'u1987'
|
userParams.id = 'u1987'
|
||||||
authorParams.id = 'u257'
|
authorParams.id = 'u257'
|
||||||
|
createPostVariables.id = 'p1376'
|
||||||
const someUserNode = await instance.create('User', userParams)
|
const someUserNode = await instance.create('User', userParams)
|
||||||
someUser = await someUserNode.toJson()
|
someUser = await someUserNode.toJson()
|
||||||
ownerNode = await instance.create('User', authorParams)
|
ownerNode = await instance.create('User', authorParams)
|
||||||
owner = await ownerNode.toJson()
|
owner = await ownerNode.toJson()
|
||||||
|
postToEmoteNode = await instance.create('Post', createPostVariables)
|
||||||
|
postToEmote = await postToEmoteNode.toJson()
|
||||||
|
await postToEmoteNode.relateTo(ownerNode, 'author')
|
||||||
|
|
||||||
postMutationAction = async (user, mutation, variables) => {
|
postMutationAction = async (user, mutation, variables) => {
|
||||||
const { server } = createServer({
|
const { server } = createServer({
|
||||||
@ -462,42 +477,29 @@ describe('emotions', () => {
|
|||||||
const { query } = createTestClient(server)
|
const { query } = createTestClient(server)
|
||||||
return query({ query: postQuery, variables })
|
return query({ query: postQuery, variables })
|
||||||
}
|
}
|
||||||
|
addPostEmotionsVariables = {
|
||||||
|
from: { id: authorParams.id },
|
||||||
|
to: { id: postToEmote.id },
|
||||||
|
data: { emotion: 'happy' },
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('AddPostEmotions', () => {
|
describe('AddPostEmotions', () => {
|
||||||
let postEmotionsQueryVariables
|
let postsEmotionsQueryVariables
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = owner
|
postsEmotionsQueryVariables = { id: postToEmote.id }
|
||||||
const {
|
|
||||||
data: { CreatePost },
|
|
||||||
} = await postMutationAction(user, createPostMutation, createPostVariables)
|
|
||||||
addPostEmotionsVariables = {
|
|
||||||
from: { id: authorParams.id },
|
|
||||||
to: { id: CreatePost.id },
|
|
||||||
data: { emotion: 'happy' },
|
|
||||||
}
|
|
||||||
postEmotionsQueryVariables = { id: CreatePost.id }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const addPostEmotionsMutation = `
|
|
||||||
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
|
||||||
AddPostEmotions(from: $from, to: $to, data: $data) {
|
|
||||||
from { id }
|
|
||||||
to { id }
|
|
||||||
emotion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
user = null
|
user = null
|
||||||
const result = await postMutationAction(
|
const addPostEmotions = await postMutationAction(
|
||||||
user,
|
user,
|
||||||
addPostEmotionsMutation,
|
addPostEmotionsMutation,
|
||||||
addPostEmotionsVariables,
|
addPostEmotionsVariables,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!')
|
expect(addPostEmotions.errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -535,7 +537,7 @@ describe('emotions', () => {
|
|||||||
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
||||||
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
||||||
await expect(
|
await expect(
|
||||||
postQueryAction(postEmotionsCountQuery, postEmotionsQueryVariables),
|
postQueryAction(PostsEmotionsCountQuery, postsEmotionsQueryVariables),
|
||||||
).resolves.toEqual(expect.objectContaining(expected))
|
).resolves.toEqual(expect.objectContaining(expected))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -551,7 +553,7 @@ describe('emotions', () => {
|
|||||||
addPostEmotionsVariables.data.emotion = 'surprised'
|
addPostEmotionsVariables.data.emotion = 'surprised'
|
||||||
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
||||||
await expect(
|
await expect(
|
||||||
postQueryAction(postEmotionsQuery, postEmotionsQueryVariables),
|
postQueryAction(PostsEmotionsQuery, postsEmotionsQueryVariables),
|
||||||
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -579,16 +581,19 @@ describe('emotions', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('RemovePostEmotions', () => {
|
describe('RemovePostEmotions', () => {
|
||||||
let removePostEmotionsVariables, postEmotionsQueryVariables
|
let removePostEmotionsVariables, postsEmotionsQueryVariables
|
||||||
const removePostEmotionsMutation = `
|
const removePostEmotionsMutation = `
|
||||||
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
mutation($to: _PostInput!, $data: _EMOTEDInput!) {
|
||||||
RemovePostEmotions(from: $from, to: $to, data: $data)
|
RemovePostEmotions(to: $to, data: $data)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
|
await ownerNode.relateTo(postToEmoteNode, 'emoted', { emotion: 'cry' })
|
||||||
|
await postMutationAction(user, addPostEmotionsMutation, addPostEmotionsVariables)
|
||||||
|
|
||||||
|
postsEmotionsQueryVariables = { id: postToEmote.id }
|
||||||
removePostEmotionsVariables = {
|
removePostEmotionsVariables = {
|
||||||
from: { id: authorParams.id },
|
to: { id: postToEmote.id },
|
||||||
to: { id: 'p1376' },
|
|
||||||
data: { emotion: 'cry' },
|
data: { emotion: 'cry' },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -596,45 +601,25 @@ describe('emotions', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
user = null
|
user = null
|
||||||
const result = await postMutationAction(
|
const removePostEmotions = await postMutationAction(
|
||||||
user,
|
user,
|
||||||
removePostEmotionsMutation,
|
removePostEmotionsMutation,
|
||||||
removePostEmotionsVariables,
|
removePostEmotionsVariables,
|
||||||
)
|
)
|
||||||
|
expect(removePostEmotions.errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||||
expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
user = owner
|
|
||||||
const {
|
|
||||||
data: { CreatePost },
|
|
||||||
} = await postMutationAction(user, createPostMutation, createPostVariables)
|
|
||||||
await factory.emote({
|
|
||||||
from: authorParams.id,
|
|
||||||
to: CreatePost.id,
|
|
||||||
data: 'cry',
|
|
||||||
})
|
|
||||||
await factory.emote({
|
|
||||||
from: authorParams.id,
|
|
||||||
to: CreatePost.id,
|
|
||||||
data: 'happy',
|
|
||||||
})
|
|
||||||
postEmotionsQueryVariables = { id: CreatePost.id }
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('but not the emoter', () => {
|
describe('but not the emoter', () => {
|
||||||
it('throws an authorization error', async () => {
|
it('throws an authorization error', async () => {
|
||||||
user = someUser
|
user = someUser
|
||||||
const result = await postMutationAction(
|
const removePostEmotions = await postMutationAction(
|
||||||
user,
|
user,
|
||||||
removePostEmotionsMutation,
|
removePostEmotionsMutation,
|
||||||
removePostEmotionsVariables,
|
removePostEmotionsVariables,
|
||||||
)
|
)
|
||||||
|
expect(removePostEmotions.errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||||
expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -654,7 +639,7 @@ describe('emotions', () => {
|
|||||||
}
|
}
|
||||||
await postMutationAction(user, removePostEmotionsMutation, removePostEmotionsVariables)
|
await postMutationAction(user, removePostEmotionsMutation, removePostEmotionsVariables)
|
||||||
await expect(
|
await expect(
|
||||||
postQueryAction(postEmotionsQuery, postEmotionsQueryVariables),
|
postQueryAction(PostsEmotionsQuery, postsEmotionsQueryVariables),
|
||||||
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -662,54 +647,44 @@ describe('emotions', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('posts emotions count', () => {
|
describe('posts emotions count', () => {
|
||||||
let postsEmotionsCountByEmotionVariables
|
let PostsEmotionsCountByEmotionVariables
|
||||||
let postsEmotionsCountByCurrentUserVariables
|
let PostsEmotionsByCurrentUserVariables
|
||||||
|
|
||||||
const postsEmotionsCountByEmotionQuery = `
|
const PostsEmotionsCountByEmotionQuery = `
|
||||||
query($postId: ID!, $data: _EMOTEDInput!) {
|
query($postId: ID!, $data: _EMOTEDInput!) {
|
||||||
postsEmotionsCountByEmotion(postId: $postId, data: $data)
|
PostsEmotionsCountByEmotion(postId: $postId, data: $data)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const postsEmotionsCountByCurrentUserQuery = `
|
const PostsEmotionsByCurrentUserQuery = `
|
||||||
query($postId: ID!) {
|
query($postId: ID!) {
|
||||||
postsEmotionsCountByCurrentUser(postId: $postId)
|
PostsEmotionsByCurrentUser(postId: $postId)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = owner
|
await ownerNode.relateTo(postToEmoteNode, 'emoted', { emotion: 'cry' })
|
||||||
const {
|
|
||||||
data: { CreatePost },
|
PostsEmotionsCountByEmotionVariables = {
|
||||||
} = await postMutationAction(user, createPostMutation, createPostVariables)
|
postId: postToEmote.id,
|
||||||
await factory.emote({
|
|
||||||
from: authorParams.id,
|
|
||||||
to: CreatePost.id,
|
|
||||||
data: 'cry',
|
|
||||||
})
|
|
||||||
postsEmotionsCountByEmotionVariables = {
|
|
||||||
postId: CreatePost.id,
|
|
||||||
data: { emotion: 'cry' },
|
data: { emotion: 'cry' },
|
||||||
}
|
}
|
||||||
postsEmotionsCountByCurrentUserVariables = { postId: CreatePost.id }
|
PostsEmotionsByCurrentUserVariables = { postId: postToEmote.id }
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('postsEmotionsCountByEmotion', () => {
|
describe('PostsEmotionsCountByEmotion', () => {
|
||||||
it("returns a post's emotions count", async () => {
|
it("returns a post's emotions count", async () => {
|
||||||
const expectedResponse = { data: { postsEmotionsCountByEmotion: 1 } }
|
const expectedResponse = { data: { PostsEmotionsCountByEmotion: 1 } }
|
||||||
await expect(
|
await expect(
|
||||||
postQueryAction(postsEmotionsCountByEmotionQuery, postsEmotionsCountByEmotionVariables),
|
postQueryAction(PostsEmotionsCountByEmotionQuery, PostsEmotionsCountByEmotionVariables),
|
||||||
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('postsEmotionsCountByEmotion', () => {
|
describe('PostsEmotionsCountByEmotion', () => {
|
||||||
it("returns a currentUser's emotions on a post", async () => {
|
it("returns a currentUser's emotions on a post", async () => {
|
||||||
const expectedResponse = { data: { postsEmotionsCountByCurrentUser: ['cry'] } }
|
const expectedResponse = { data: { PostsEmotionsByCurrentUser: ['cry'] } }
|
||||||
await expect(
|
await expect(
|
||||||
postQueryAction(
|
postQueryAction(PostsEmotionsByCurrentUserQuery, PostsEmotionsByCurrentUserVariables),
|
||||||
postsEmotionsCountByCurrentUserQuery,
|
|
||||||
postsEmotionsCountByCurrentUserVariables,
|
|
||||||
),
|
|
||||||
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
).resolves.toEqual(expect.objectContaining(expectedResponse))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -91,10 +91,11 @@ type Mutation {
|
|||||||
language: String
|
language: String
|
||||||
categoryIds: [ID]
|
categoryIds: [ID]
|
||||||
): Post
|
): Post
|
||||||
RemovePostEmotions(from: _UserInput!, to: _PostInput!, data: _EMOTEDInput!): Boolean!
|
AddPostEmotions(from: _UserInput!, to: _PostInput!, data: _EMOTEDInput!): EMOTED
|
||||||
|
RemovePostEmotions(to: _PostInput!, data: _EMOTEDInput!): Boolean!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
postsEmotionsCountByEmotion(postId: ID!, data: _EMOTEDInput!): Int!
|
PostsEmotionsCountByEmotion(postId: ID!, data: _EMOTEDInput!): Int!
|
||||||
postsEmotionsCountByCurrentUser(postId: ID!): [String]
|
PostsEmotionsByCurrentUser(postId: ID!): [String]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { mount, createLocalVue } from '@vue/test-utils'
|
import { mount, createLocalVue } from '@vue/test-utils'
|
||||||
import EmotionsButtons from './EmotionsButtons.vue'
|
import Emotions from './Emotions.vue'
|
||||||
import Styleguide from '@human-connection/styleguide'
|
import Styleguide from '@human-connection/styleguide'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import PostMutations from '~/graphql/PostMutations.js'
|
import PostMutations from '~/graphql/PostMutations.js'
|
||||||
@ -9,7 +9,7 @@ const localVue = createLocalVue()
|
|||||||
localVue.use(Styleguide)
|
localVue.use(Styleguide)
|
||||||
localVue.use(Vuex)
|
localVue.use(Vuex)
|
||||||
|
|
||||||
describe('EmotionsButtons.vue', () => {
|
describe('Emotions.vue', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
let mocks
|
let mocks
|
||||||
let propsData
|
let propsData
|
||||||
@ -39,7 +39,7 @@ describe('EmotionsButtons.vue', () => {
|
|||||||
}),
|
}),
|
||||||
query: jest.fn().mockResolvedValue({
|
query: jest.fn().mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
postsEmotionsCountByEmotion: 1,
|
PostsEmotionsCountByEmotion: 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@ -59,7 +59,7 @@ describe('EmotionsButtons.vue', () => {
|
|||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
getters,
|
getters,
|
||||||
})
|
})
|
||||||
return mount(EmotionsButtons, { mocks, propsData, store, localVue })
|
return mount(Emotions, { mocks, propsData, store, localVue })
|
||||||
}
|
}
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
@ -72,7 +72,7 @@ describe('EmotionsButtons.vue', () => {
|
|||||||
describe('adding emotions', () => {
|
describe('adding emotions', () => {
|
||||||
let expectedParams
|
let expectedParams
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper.vm.postsEmotionsCountByEmotion.funny = 0
|
wrapper.vm.PostsEmotionsCountByEmotion.funny = 0
|
||||||
funnyButton = wrapper.findAll('button').at(0)
|
funnyButton = wrapper.findAll('button').at(0)
|
||||||
funnyButton.trigger('click')
|
funnyButton.trigger('click')
|
||||||
})
|
})
|
||||||
@ -82,16 +82,16 @@ describe('EmotionsButtons.vue', () => {
|
|||||||
expect(funnyImage.attributes().src).toEqual(funnyImageSrc)
|
expect(funnyImage.attributes().src).toEqual(funnyImageSrc)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends the addPostEmotionsMutation for an emotion when clicked', () => {
|
it('sends the AddPostEmotionsMutation for an emotion when clicked', () => {
|
||||||
expectedParams = {
|
expectedParams = {
|
||||||
mutation: PostMutations().addPostEmotionsMutation,
|
mutation: PostMutations().AddPostEmotionsMutation,
|
||||||
variables: { from: { id: 'u176' }, to: { id: 'p143' }, data: { emotion: 'funny' } },
|
variables: { from: { id: 'u176' }, to: { id: 'p143' }, data: { emotion: 'funny' } },
|
||||||
}
|
}
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('increases the postEmotionsCountByEmotion for the emotion clicked', () => {
|
it('increases the PostsEmotionsCountByEmotion for the emotion clicked', () => {
|
||||||
expect(wrapper.vm.postsEmotionsCountByEmotion.funny).toEqual(1)
|
expect(wrapper.vm.PostsEmotionsCountByEmotion.funny).toEqual(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('adds an emotion to selectedEmotions to show the colored image when the button is active', () => {
|
it('adds an emotion to selectedEmotions to show the colored image when the button is active', () => {
|
||||||
@ -103,16 +103,16 @@ describe('EmotionsButtons.vue', () => {
|
|||||||
funnyButton.trigger('click')
|
funnyButton.trigger('click')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends the removePostEmotionsMutation when a user clicks on an active emotion', () => {
|
it('sends the RemovePostEmotionsMutation when a user clicks on an active emotion', () => {
|
||||||
expectedParams = {
|
expectedParams = {
|
||||||
mutation: PostMutations().removePostEmotionsMutation,
|
mutation: PostMutations().RemovePostEmotionsMutation,
|
||||||
variables: { from: { id: 'u176' }, to: { id: 'p143' }, data: { emotion: 'funny' } },
|
variables: { from: { id: 'u176' }, to: { id: 'p143' }, data: { emotion: 'funny' } },
|
||||||
}
|
}
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('decreases the postEmotionsCountByEmotion for the emotion clicked', async () => {
|
it('decreases the PostsEmotionsCountByEmotion for the emotion clicked', async () => {
|
||||||
expect(wrapper.vm.postsEmotionsCountByEmotion.funny).toEqual(0)
|
expect(wrapper.vm.PostsEmotionsCountByEmotion.funny).toEqual(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('removes an emotion from selectedEmotions to show the default image', async () => {
|
it('removes an emotion from selectedEmotions to show the default image', async () => {
|
||||||
@ -1,18 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-flex :gutter="{ lg: 'large' }" class="emotions-flex">
|
<ds-flex :gutter="{ lg: 'large' }" class="emotions-flex">
|
||||||
<div v-for="emotion in Object.keys(postsEmotionsCountByEmotion)" :key="emotion">
|
<div v-for="emotion in Object.keys(PostsEmotionsCountByEmotion)" :key="emotion">
|
||||||
<ds-flex-item :width="{ lg: '100%' }">
|
<ds-flex-item :width="{ lg: '100%' }">
|
||||||
<ds-button size="large" ghost @click="toggleEmotion(emotion)" class="emotions-buttons">
|
<hc-emotions-button
|
||||||
<img :src="iconPath(emotion)" width="40" />
|
@toggleEmotion="toggleEmotion"
|
||||||
</ds-button>
|
:PostsEmotionsCountByEmotion="PostsEmotionsCountByEmotion"
|
||||||
<ds-space margin-bottom="xx-small" />
|
:iconPath="iconPath(emotion)"
|
||||||
<div class="emotions-mobile-space">
|
:emotion="emotion"
|
||||||
<p class="emotions-label">{{ $t(`contribution.emotions-label.${emotion}`) }}</p>
|
/>
|
||||||
<ds-text style="display: inline" size="medium" :key="postsEmotionsCountByEmotion[emotion]">
|
|
||||||
{{ postsEmotionsCountByEmotion[emotion] }}x
|
|
||||||
</ds-text>
|
|
||||||
{{ $t('contribution.emotions-label.emoted') }}
|
|
||||||
</div>
|
|
||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
</div>
|
</div>
|
||||||
</ds-flex>
|
</ds-flex>
|
||||||
@ -20,17 +15,21 @@
|
|||||||
<script>
|
<script>
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { postsEmotionsCountByCurrentUser } from '~/graphql/PostQuery.js'
|
import HcEmotionsButton from '~/components/EmotionsButton/EmotionsButton'
|
||||||
|
import { PostsEmotionsByCurrentUser } from '~/graphql/PostQuery.js'
|
||||||
import PostMutations from '~/graphql/PostMutations.js'
|
import PostMutations from '~/graphql/PostMutations.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
HcEmotionsButton,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
post: { type: Object, default: () => {} },
|
post: { type: Object, default: () => {} },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedEmotions: [],
|
selectedEmotions: [],
|
||||||
postsEmotionsCountByEmotion: { funny: 0, happy: 0, surprised: 0, cry: 0, angry: 0 },
|
PostsEmotionsCountByEmotion: { funny: 0, happy: 0, surprised: 0, cry: 0, angry: 0 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -39,7 +38,7 @@ export default {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
Object.keys(this.postsEmotionsCountByEmotion).map(emotion => {
|
Object.keys(this.PostsEmotionsCountByEmotion).map(emotion => {
|
||||||
this.emotionsCount(emotion)
|
this.emotionsCount(emotion)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -54,8 +53,8 @@ export default {
|
|||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
mutation: this.isActive(emotion)
|
mutation: this.isActive(emotion)
|
||||||
? PostMutations().removePostEmotionsMutation
|
? PostMutations().RemovePostEmotionsMutation
|
||||||
: PostMutations().addPostEmotionsMutation,
|
: PostMutations().AddPostEmotionsMutation,
|
||||||
variables: {
|
variables: {
|
||||||
from: { id: this.currentUser.id },
|
from: { id: this.currentUser.id },
|
||||||
to: { id: this.post.id },
|
to: { id: this.post.id },
|
||||||
@ -64,8 +63,8 @@ export default {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isActive(emotion)
|
this.isActive(emotion)
|
||||||
? this.postsEmotionsCountByEmotion[emotion]--
|
? this.PostsEmotionsCountByEmotion[emotion]--
|
||||||
: this.postsEmotionsCountByEmotion[emotion]++
|
: this.PostsEmotionsCountByEmotion[emotion]++
|
||||||
|
|
||||||
const index = this.selectedEmotions.indexOf(emotion)
|
const index = this.selectedEmotions.indexOf(emotion)
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
@ -87,52 +86,31 @@ export default {
|
|||||||
.query({
|
.query({
|
||||||
query: gql`
|
query: gql`
|
||||||
query($postId: ID!, $data: _EMOTEDInput!) {
|
query($postId: ID!, $data: _EMOTEDInput!) {
|
||||||
postsEmotionsCountByEmotion(postId: $postId, data: $data)
|
PostsEmotionsCountByEmotion(postId: $postId, data: $data)
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: { postId: this.post.id, data: { emotion } },
|
variables: { postId: this.post.id, data: { emotion } },
|
||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: 'no-cache',
|
||||||
})
|
})
|
||||||
.then(({ data: { postsEmotionsCountByEmotion } }) => {
|
.then(({ data: { PostsEmotionsCountByEmotion } }) => {
|
||||||
this.postsEmotionsCountByEmotion[emotion] = postsEmotionsCountByEmotion
|
this.PostsEmotionsCountByEmotion[emotion] = PostsEmotionsCountByEmotion
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
postsEmotionsCountByCurrentUser: {
|
PostsEmotionsByCurrentUser: {
|
||||||
query() {
|
query() {
|
||||||
return postsEmotionsCountByCurrentUser()
|
return PostsEmotionsByCurrentUser()
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
postId: this.post.id,
|
postId: this.post.id,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
result({ data: { postsEmotionsCountByCurrentUser } }) {
|
result({ data: { PostsEmotionsByCurrentUser } }) {
|
||||||
this.selectedEmotions = postsEmotionsCountByCurrentUser
|
this.selectedEmotions = PostsEmotionsByCurrentUser
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
|
||||||
.emotions-flex {
|
|
||||||
justify-content: space-evenly;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emotions-label {
|
|
||||||
font-size: $font-size-small;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emotions-buttons {
|
|
||||||
&:hover {
|
|
||||||
background-color: $background-color-base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.emotions-mobile-space {
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
50
webapp/components/EmotionsButton/EmotionsButton.vue
Normal file
50
webapp/components/EmotionsButton/EmotionsButton.vue
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ds-button size="large" ghost @click="toggleEmotion(emotion)" class="emotions-buttons">
|
||||||
|
<img :src="iconPath" width="40" />
|
||||||
|
</ds-button>
|
||||||
|
<ds-space margin-bottom="xx-small" />
|
||||||
|
<div class="emotions-mobile-space">
|
||||||
|
<p class="emotions-label">{{ $t(`contribution.emotions-label.${emotion}`) }}</p>
|
||||||
|
<p style="display: inline" :key="PostsEmotionsCountByEmotion[emotion]">
|
||||||
|
{{ PostsEmotionsCountByEmotion[emotion] }}x
|
||||||
|
</p>
|
||||||
|
{{ $t('contribution.emotions-label.emoted') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
iconPath: { type: String, default: null },
|
||||||
|
PostsEmotionsCountByEmotion: { type: Object, default: () => {} },
|
||||||
|
emotion: { type: String, default: null },
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleEmotion(emotion) {
|
||||||
|
this.$emit('toggleEmotion', emotion)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.emotions-flex {
|
||||||
|
justify-content: space-evenly;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emotions-label {
|
||||||
|
font-size: $font-size-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emotions-buttons {
|
||||||
|
&:hover {
|
||||||
|
background-color: $background-color-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 960px) {
|
||||||
|
.emotions-mobile-space {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -60,7 +60,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
addPostEmotionsMutation: gql`
|
AddPostEmotionsMutation: gql`
|
||||||
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
||||||
AddPostEmotions(from: $from, to: $to, data: $data) {
|
AddPostEmotions(from: $from, to: $to, data: $data) {
|
||||||
emotion
|
emotion
|
||||||
@ -73,9 +73,9 @@ export default () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
removePostEmotionsMutation: gql`
|
RemovePostEmotionsMutation: gql`
|
||||||
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
mutation($to: _PostInput!, $data: _EMOTEDInput!) {
|
||||||
RemovePostEmotions(from: $from, to: $to, data: $data)
|
RemovePostEmotions(to: $to, data: $data)
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,10 +122,10 @@ export const filterPosts = i18n => {
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const postsEmotionsCountByCurrentUser = () => {
|
export const PostsEmotionsByCurrentUser = () => {
|
||||||
return gql`
|
return gql`
|
||||||
query postsEmotionsCountByCurrentUser($postId: ID!) {
|
query PostsEmotionsByCurrentUser($postId: ID!) {
|
||||||
postsEmotionsCountByCurrentUser(postId: $postId)
|
PostsEmotionsByCurrentUser(postId: $postId)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
:width="{ lg: '75%', md: '75%', sm: '75%' }"
|
:width="{ lg: '75%', md: '75%', sm: '75%' }"
|
||||||
class="emotions-buttons-mobile"
|
class="emotions-buttons-mobile"
|
||||||
>
|
>
|
||||||
<hc-emotions-buttons :post="post" />
|
<hc-emotions :post="post" />
|
||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
<ds-flex-item :width="{ lg: '10%', md: '3%', sm: '3%' }" />
|
<ds-flex-item :width="{ lg: '10%', md: '3%', sm: '3%' }" />
|
||||||
<!-- Shout Button -->
|
<!-- Shout Button -->
|
||||||
@ -85,7 +85,7 @@ import HcCommentForm from '~/components/comments/CommentForm'
|
|||||||
import HcCommentList from '~/components/comments/CommentList'
|
import HcCommentList from '~/components/comments/CommentList'
|
||||||
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
|
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
|
||||||
import PostQuery from '~/graphql/PostQuery.js'
|
import PostQuery from '~/graphql/PostQuery.js'
|
||||||
import HcEmotionsButtons from '~/components/EmotionsButtons/EmotionsButtons'
|
import HcEmotions from '~/components/Emotions/Emotions'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PostSlug',
|
name: 'PostSlug',
|
||||||
@ -101,7 +101,7 @@ export default {
|
|||||||
ContentMenu,
|
ContentMenu,
|
||||||
HcCommentForm,
|
HcCommentForm,
|
||||||
HcCommentList,
|
HcCommentList,
|
||||||
HcEmotionsButtons,
|
HcEmotions,
|
||||||
ContentViewer,
|
ContentViewer,
|
||||||
},
|
},
|
||||||
head() {
|
head() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user