Merge pull request #6197 from Ocelot-Social-Community/create-posts-for-events

feat(backend): create and update posts with labels
This commit is contained in:
Moriz Wahl 2023-04-04 15:59:26 +02:00 committed by GitHub
commit 204a3758c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 53 deletions

View File

@ -11,6 +11,7 @@ export const createPostMutation = () => {
$content: String!
$categoryIds: [ID]
$groupId: ID
$postType: PostType
) {
CreatePost(
id: $id
@ -19,11 +20,21 @@ export const createPostMutation = () => {
content: $content
categoryIds: $categoryIds
groupId: $groupId
postType: $postType
) {
id
slug
title
content
disabled
deleted
postType
author {
name
}
categories {
id
}
}
}
`

View File

@ -125,12 +125,13 @@ export default {
SET post.updatedAt = toString(datetime())
SET post.clickedCount = 0
SET post.viewedTeaserCount = 0
SET post:${params.postType}
WITH post
MATCH (author:User {id: $userId})
MERGE (post)<-[:WROTE]-(author)
${categoriesCypher}
${groupCypher}
RETURN post {.*}
RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post") }
`,
{ userId: context.user.id, categoryIds, groupId, params },
)
@ -183,7 +184,16 @@ export default {
`
}
updatePostCypher += `RETURN post {.*}`
if (params.postType) {
updatePostCypher += `
REMOVE post:Article
REMOVE post:Event
SET post:${params.postType}
WITH post
`
}
updatePostCypher += `RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post")}`
const updatePostVariables = { categoryIds, params }
try {
const writeTxResultPromise = session.writeTransaction(async (transaction) => {

View File

@ -3,6 +3,10 @@ import Factory, { cleanDatabase } from '../../db/factories'
import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'
import { createPostMutation } from '../../graphql/posts'
import CONFIG from '../../config'
CONFIG.CATEGORIES_ACTIVE = true
const driver = getDriver()
const neode = getNeode()
@ -15,29 +19,6 @@ let user
const categoryIds = ['cat9', 'cat4', 'cat15']
let variables
const createPostMutation = gql`
mutation ($id: ID, $title: String!, $content: String!, $language: String, $categoryIds: [ID]) {
CreatePost(
id: $id
title: $title
content: $content
language: $language
categoryIds: $categoryIds
) {
id
title
content
slug
disabled
deleted
language
author {
name
}
}
}
`
beforeAll(async () => {
await cleanDatabase()
@ -281,7 +262,7 @@ describe('CreatePost', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({ mutation: createPostMutation, variables })
const { errors } = await mutate({ mutation: createPostMutation(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@ -296,7 +277,7 @@ describe('CreatePost', () => {
data: { CreatePost: { title: 'I am a title', content: 'Some content' } },
errors: undefined,
}
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject(
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject(
expected,
)
})
@ -313,25 +294,76 @@ describe('CreatePost', () => {
},
errors: undefined,
}
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject(
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject(
expected,
)
})
it('`disabled` and `deleted` default to `false`', async () => {
const expected = { data: { CreatePost: { disabled: false, deleted: false } } }
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject(
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject(
expected,
)
})
it('has label "Article" as default', async () => {
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject({
data: { CreatePost: { postType: ['Article'] } },
})
})
describe('with post type "Event"', () => {
it('has label "Event" set', async () => {
await expect(
mutate({
mutation: createPostMutation(),
variables: { ...variables, postType: 'Event' },
}),
).resolves.toMatchObject({
data: { CreatePost: { postType: ['Event'] } },
})
})
})
describe('with invalid post type', () => {
it('throws an error', async () => {
await expect(
mutate({
mutation: createPostMutation(),
variables: { ...variables, postType: 'not-valid' },
}),
).resolves.toMatchObject({
errors: [
{
message:
'Variable "$postType" got invalid value "not-valid"; Expected type PostType.',
},
],
})
})
})
})
})
describe('UpdatePost', () => {
let author, newlyCreatedPost
const updatePostMutation = gql`
mutation ($id: ID!, $title: String!, $content: String!, $image: ImageInput) {
UpdatePost(id: $id, title: $title, content: $content, image: $image) {
mutation (
$id: ID!
$title: String!
$content: String!
$image: ImageInput
$categoryIds: [ID]
$postType: PostType
) {
UpdatePost(
id: $id
title: $title
content: $content
image: $image
categoryIds: $categoryIds
postType: $postType
) {
id
title
content
@ -341,26 +373,27 @@ describe('UpdatePost', () => {
}
createdAt
updatedAt
categories {
id
}
postType
}
}
`
beforeEach(async () => {
author = await Factory.build('user', { slug: 'the-author' })
newlyCreatedPost = await Factory.build(
'post',
{
id: 'p9876',
authenticatedUser = await author.toJson()
const { data } = await mutate({
mutation: createPostMutation(),
variables: {
title: 'Old title',
content: 'Old content',
},
{
author,
categoryIds,
},
)
})
newlyCreatedPost = data.CreatePost
variables = {
id: 'p9876',
id: newlyCreatedPost.id,
title: 'New title',
content: 'New content',
}
@ -394,7 +427,7 @@ describe('UpdatePost', () => {
it('updates a post', async () => {
const expected = {
data: { UpdatePost: { id: 'p9876', content: 'New content' } },
data: { UpdatePost: { id: newlyCreatedPost.id, content: 'New content' } },
errors: undefined,
}
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
@ -405,7 +438,11 @@ describe('UpdatePost', () => {
it('updates a post, but maintains non-updated attributes', async () => {
const expected = {
data: {
UpdatePost: { id: 'p9876', content: 'New content', createdAt: expect.any(String) },
UpdatePost: {
id: newlyCreatedPost.id,
content: 'New content',
createdAt: expect.any(String),
},
},
errors: undefined,
}
@ -415,23 +452,20 @@ describe('UpdatePost', () => {
})
it('updates the updatedAt attribute', async () => {
newlyCreatedPost = await newlyCreatedPost.toJson()
const {
data: { UpdatePost },
} = await mutate({ mutation: updatePostMutation, variables })
expect(newlyCreatedPost.updatedAt).toBeTruthy()
expect(Date.parse(newlyCreatedPost.updatedAt)).toEqual(expect.any(Number))
expect(UpdatePost.updatedAt).toBeTruthy()
expect(Date.parse(UpdatePost.updatedAt)).toEqual(expect.any(Number))
expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePost.updatedAt)
})
/* describe('no new category ids provided for update', () => {
describe('no new category ids provided for update', () => {
it('resolves and keeps current categories', async () => {
const expected = {
data: {
UpdatePost: {
id: 'p9876',
id: newlyCreatedPost.id,
categories: expect.arrayContaining([{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]),
},
},
@ -441,9 +475,9 @@ describe('UpdatePost', () => {
expected,
)
})
}) */
})
/* describe('given category ids', () => {
describe('given category ids', () => {
beforeEach(() => {
variables = { ...variables, categoryIds: ['cat27'] }
})
@ -452,7 +486,7 @@ describe('UpdatePost', () => {
const expected = {
data: {
UpdatePost: {
id: 'p9876',
id: newlyCreatedPost.id,
categories: expect.arrayContaining([{ id: 'cat27' }]),
},
},
@ -462,9 +496,25 @@ describe('UpdatePost', () => {
expected,
)
})
}) */
})
describe('params.image', () => {
describe('post type', () => {
it('changes the post type', async () => {
await expect(
mutate({ mutation: updatePostMutation, variables: { ...variables, postType: 'Event' } }),
).resolves.toMatchObject({
data: {
UpdatePost: {
id: newlyCreatedPost.id,
postType: ['Event'],
},
},
errors: undefined,
})
})
})
describe.skip('params.image', () => {
describe('is object', () => {
beforeEach(() => {
variables = { ...variables, image: { sensitive: true } }

View File

@ -0,0 +1,4 @@
enum PostType {
Article
Event
}

View File

@ -171,6 +171,8 @@ type Post {
@cypher(statement: "MATCH (this)<-[emoted:EMOTED]-(:User) RETURN COUNT(DISTINCT emoted)")
group: Group @relation(name: "IN", direction: "OUT")
postType: [PostType]
@cypher(statement: "RETURN filter(l IN labels(this) WHERE NOT l = 'Post')")
}
input _PostInput {
@ -189,6 +191,7 @@ type Mutation {
categoryIds: [ID]
contentExcerpt: String
groupId: ID
postType: PostType = Article
): Post
UpdatePost(
id: ID!
@ -200,6 +203,7 @@ type Mutation {
visibility: Visibility
language: String
categoryIds: [ID]
postType: PostType
): Post
DeletePost(id: ID!): Post
AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED