From d714927315df2695f8c83143c689575a5e62bdc3 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 26 Jun 2019 11:26:44 -0300 Subject: [PATCH] Set up backend for Post creation with categories --- backend/src/schema/resolvers/posts.js | 45 +++++++++++- backend/src/schema/resolvers/posts.spec.js | 82 ++++++++++++++++++---- backend/src/schema/types/schema.gql | 17 +++++ 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/backend/src/schema/resolvers/posts.js b/backend/src/schema/resolvers/posts.js index ea962a662..7769fad14 100644 --- a/backend/src/schema/resolvers/posts.js +++ b/backend/src/schema/resolvers/posts.js @@ -9,8 +9,9 @@ export default { }, CreatePost: async (object, params, context, resolveInfo) => { + const { categories } = params params = await fileUpload(params, { file: 'imageUpload', url: 'image' }) - const result = await neo4jgraphql(object, params, context, resolveInfo, false) + let post = await neo4jgraphql(object, params, context, resolveInfo, false) const session = context.driver.session() await session.run( @@ -19,12 +20,50 @@ export default { 'RETURN author', { userId: context.user.id, - postId: result.id, + postId: post.id, }, ) + if (categories && categories.length) { + let postsCategoriesArray = [] + await Promise.all( + categories.map(async categoryId => { + let postsCategoriesTransaction = await session.run( + `MATCH (category:Category { id: $categoryId}), (post:Post {id: $postId}) + MERGE (post)-[:CATEGORIZED]->(category) + RETURN category + `, + { + categoryId, + postId: post.id, + }, + ) + postsCategoriesArray.push(postsCategoriesTransaction) + }), + ) + let categoryArray = [] + postsCategoriesArray.map(categoryRecord => { + let [category] = categoryRecord.records.map(record => { + return { + category: record.get('category'), + } + }) + categoryArray.push(category) + }) + let categoriesPropertiesArray = [] + categoryArray.map(node => { + let { category } = node + let categories = { ...category.properties } + categoriesPropertiesArray.push(categories) + }) + + post = { + ...post, + categories: categoriesPropertiesArray, + } + } session.close() - return result + return post }, }, } diff --git a/backend/src/schema/resolvers/posts.spec.js b/backend/src/schema/resolvers/posts.spec.js index 3bff53ddb..56b2c8b95 100644 --- a/backend/src/schema/resolvers/posts.spec.js +++ b/backend/src/schema/resolvers/posts.spec.js @@ -4,7 +4,9 @@ import { host, login } from '../../jest/helpers' const factory = Factory() let client - +const postTitle = 'I am a title' +const postContent = 'Some content' +const createPostVariables = { title: postTitle, content: postContent } beforeEach(async () => { await factory.create('User', { email: 'test@example.org', @@ -18,8 +20,8 @@ afterEach(async () => { describe('CreatePost', () => { const mutation = ` - mutation { - CreatePost(title: "I am a title", content: "Some content") { + mutation($title: String!, $content: String!) { + CreatePost(title: $title, content: $content) { title content slug @@ -32,7 +34,7 @@ describe('CreatePost', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { client = new GraphQLClient(host) - await expect(client.request(mutation)).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, createPostVariables)).rejects.toThrow('Not Authorised') }) }) @@ -46,15 +48,15 @@ describe('CreatePost', () => { it('creates a post', async () => { const expected = { CreatePost: { - title: 'I am a title', - content: 'Some content', + title: postTitle, + content: postContent, }, } - await expect(client.request(mutation)).resolves.toMatchObject(expected) + await expect(client.request(mutation, createPostVariables)).resolves.toMatchObject(expected) }) it('assigns the authenticated user as author', async () => { - await client.request(mutation) + await client.request(mutation, createPostVariables) const { User } = await client.request( `{ User(email:"test@example.org") { @@ -65,29 +67,79 @@ describe('CreatePost', () => { }`, { headers }, ) - expect(User).toEqual([{ contributions: [{ title: 'I am a title' }] }]) + expect(User).toEqual([{ contributions: [{ title: postTitle }] }]) }) describe('disabled and deleted', () => { it('initially false', async () => { const expected = { CreatePost: { disabled: false, deleted: false } } - await expect(client.request(mutation)).resolves.toMatchObject(expected) + await expect(client.request(mutation, createPostVariables)).resolves.toMatchObject(expected) }) }) describe('language', () => { it('allows a user to set the language of the post', async () => { const createPostWithLanguageMutation = ` - mutation { - CreatePost(title: "I am a title", content: "Some content", language: "en") { + mutation($title: String!, $content: String!, $language: String) { + CreatePost(title: $title, content: $content, language: $language) { language } } ` + const createPostWithLanguageVariables = { + title: postTitle, + content: postContent, + language: 'en', + } const expected = { CreatePost: { language: 'en' } } - await expect(client.request(createPostWithLanguageMutation)).resolves.toEqual( - expect.objectContaining(expected), - ) + await expect( + client.request(createPostWithLanguageMutation, createPostWithLanguageVariables), + ).resolves.toEqual(expect.objectContaining(expected)) + }) + }) + + describe('categories', () => { + it('allows a user to set the categories of the post', async () => { + await Promise.all([ + factory.create('Category', { + id: 'cat9', + name: 'Democracy & Politics', + icon: 'university', + }), + factory.create('Category', { + id: 'cat4', + name: 'Environment & Nature', + icon: 'tree', + }), + factory.create('Category', { + id: 'cat15', + name: 'Consumption & Sustainability', + icon: 'shopping-cart', + }), + ]) + const createPostWithCategoriesMutation = ` + mutation($title: String!, $content: String!, $categories: [ID]) { + CreatePost(title: $title, content: $content, categories: $categories) { + categories { + id + } + } + } + ` + const postCategories = ['cat9', 'cat4', 'cat15'] + const creatPostWithCategoriesVariables = { + title: postTitle, + content: postContent, + categories: postCategories, + } + const expected = { + CreatePost: { + categories: [{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }], + }, + } + await expect( + client.request(createPostWithCategoriesMutation, creatPostWithCategoriesVariables), + ).resolves.toEqual(expect.objectContaining(expected)) }) }) }) diff --git a/backend/src/schema/types/schema.gql b/backend/src/schema/types/schema.gql index 1ef83bac3..6a6191313 100644 --- a/backend/src/schema/types/schema.gql +++ b/backend/src/schema/types/schema.gql @@ -41,6 +41,23 @@ type Mutation { # Unfollow the given Type and ID unfollow(id: ID!, type: FollowTypeEnum): Boolean! DeleteUser(id: ID!, resource: [String]): User + CreatePost( + id: ID + activityId: String + objectId: String + title: String! + slug: String + content: String! + image: String + imageUpload: Upload + visibility: Visibility + deleted: Boolean + disabled: Boolean + createdAt: String + updatedAt: String + language: String + categories: [ID] + ): Post } type Statistics {