Refactor comments.spec, refactor post factory

This commit is contained in:
roschaefer 2019-08-30 17:36:29 +02:00
parent 1098d5d37d
commit 4bfc0ff2bf
2 changed files with 129 additions and 194 deletions

View File

@ -1,48 +1,38 @@
import { GraphQLClient } from 'graphql-request'
import Factory from '../../seed/factories'
import { host, login, gql } from '../../jest/helpers'
import { neode } from '../../bootstrap/neo4j'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server'
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
const driver = getDriver()
const neode = getNeode()
const factory = Factory()
let client
let createCommentVariables
let createCommentVariablesSansPostId
let createCommentVariablesWithNonExistentPost
let userParams
let headers
const factory = Factory()
const instance = neode()
const categoryIds = ['cat9']
const createPostMutation = gql`
mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]!) {
CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
id
}
}
`
const createCommentMutation = gql`
mutation($id: ID, $postId: ID!, $content: String!) {
CreateComment(id: $id, postId: $postId, content: $content) {
id
content
}
}
`
const createPostVariables = {
id: 'p1',
title: 'post to comment on',
content: 'please comment on me',
categoryIds,
}
let variables
let mutate
let authenticatedUser
beforeAll(() => {
const { server } = createServer({
context: () => {
return {
driver,
user: authenticatedUser,
}
},
})
const client = createTestClient(server)
mutate = client.mutate
})
beforeEach(async () => {
userParams = {
name: 'TestUser',
email: 'test@example.org',
password: '1234',
}
await factory.create('User', userParams)
await instance.create('Category', {
variables = {}
await neode.create('Category', {
id: 'cat9',
name: 'Democracy & Politics',
icon: 'university',
@ -53,144 +43,97 @@ afterEach(async () => {
await factory.cleanDatabase()
})
const createCommentMutation = gql`
mutation($id: ID, $postId: ID!, $content: String!) {
CreateComment(id: $id, postId: $postId, content: $content) {
id
content
author {
name
}
}
}
`
describe('CreateComment', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
createCommentVariables = {
variables = {
...variables,
postId: 'p1',
content: "I'm not authorised to comment",
}
client = new GraphQLClient(host)
await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow(
'Not Authorised',
)
const result = await mutate({ mutation: createCommentMutation, variables })
expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!')
})
})
describe('authenticated', () => {
beforeEach(async () => {
headers = await login(userParams)
client = new GraphQLClient(host, {
headers,
})
createCommentVariables = {
postId: 'p1',
content: "I'm authorised to comment",
}
await client.request(createPostMutation, createPostVariables)
const user = await neode.create('User', { name: 'Author' })
authenticatedUser = await user.toJson()
})
it('creates a comment', async () => {
const expected = {
CreateComment: {
describe('given a post', () => {
beforeEach(async () => {
await factory.create('Post', { categoryIds, id: 'p1' })
variables = {
...variables,
postId: 'p1',
content: "I'm authorised to comment",
},
}
await expect(
client.request(createCommentMutation, createCommentVariables),
).resolves.toMatchObject(expected)
})
it('assigns the authenticated user as author', async () => {
await client.request(createCommentMutation, createCommentVariables)
const { User } = await client.request(gql`
{
User(name: "TestUser") {
comments {
content
}
}
}
`)
})
expect(User).toEqual([
{
comments: [
{
content: "I'm authorised to comment",
},
],
},
])
})
it('creates a comment', async () => {
await expect(mutate({ mutation: createCommentMutation, variables })).resolves.toMatchObject(
{
data: { CreateComment: { content: "I'm authorised to comment" } },
},
)
})
it('throw an error if an empty string is sent from the editor as content', async () => {
createCommentVariables = {
postId: 'p1',
content: '<p></p>',
}
it('assigns the authenticated user as author', async () => {
await expect(mutate({ mutation: createCommentMutation, variables })).resolves.toMatchObject(
{
data: { CreateComment: { author: { name: 'Author' } } },
},
)
})
await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow(
'Comment must be at least 1 character long!',
)
})
describe('comment content is empty', () => {
beforeEach(() => {
variables = { ...variables, content: '<p></p>' }
})
it('throws an error if a comment sent from the editor does not contain a single character', async () => {
createCommentVariables = {
postId: 'p1',
content: '<p> </p>',
}
it('throw UserInput error', async () => {
const { data, errors } = await mutate({ mutation: createCommentMutation, variables })
expect(data).toEqual({ CreateComment: null })
expect(errors[0]).toHaveProperty('message', 'Comment must be at least 1 character long!')
})
})
await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow(
'Comment must be at least 1 character long!',
)
})
describe('comment content contains only whitespaces', () => {
beforeEach(() => {
variables = { ...variables, content: ' <p> </p> ' }
})
it('throws an error if postId is sent as an empty string', async () => {
createCommentVariables = {
postId: 'p1',
content: '',
}
it('throw UserInput error', async () => {
const { data, errors } = await mutate({ mutation: createCommentMutation, variables })
expect(data).toEqual({ CreateComment: null })
expect(errors[0]).toHaveProperty('message', 'Comment must be at least 1 character long!')
})
})
await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow(
'Comment must be at least 1 character long!',
)
})
describe('invalid post id', () => {
beforeEach(() => {
variables = { ...variables, postId: 'does-not-exist' }
})
it('throws an error if content is sent as an string of empty characters', async () => {
createCommentVariables = {
postId: 'p1',
content: ' ',
}
await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow(
'Comment must be at least 1 character long!',
)
})
it('throws an error if postId is sent as an empty string', async () => {
createCommentVariablesSansPostId = {
postId: '',
content: 'this comment should not be created',
}
await expect(
client.request(createCommentMutation, createCommentVariablesSansPostId),
).rejects.toThrow('Comment cannot be created without a post!')
})
it('throws an error if postId is sent as an string of empty characters', async () => {
createCommentVariablesSansPostId = {
postId: ' ',
content: 'this comment should not be created',
}
await expect(
client.request(createCommentMutation, createCommentVariablesSansPostId),
).rejects.toThrow('Comment cannot be created without a post!')
})
it('throws an error if the post does not exist in the database', async () => {
createCommentVariablesWithNonExistentPost = {
postId: 'p2',
content: "comment should not be created cause the post doesn't exist",
}
await expect(
client.request(createCommentMutation, createCommentVariablesWithNonExistentPost),
).rejects.toThrow('Comment cannot be created without a post!')
it('throw UserInput error', async () => {
const { data, errors } = await mutate({ mutation: createCommentMutation, variables })
expect(data).toEqual({ CreateComment: null })
expect(errors[0]).toHaveProperty('message', 'Comment cannot be created without a post!')
})
})
})
})
})

View File

@ -1,51 +1,43 @@
import faker from 'faker'
import slugify from 'slug'
import uuid from 'uuid/v4'
export default function(params) {
const {
id = uuid(),
slug = '',
title = faker.lorem.sentence(),
content = [
faker.lorem.sentence(),
faker.lorem.sentence(),
faker.lorem.sentence(),
faker.lorem.sentence(),
faker.lorem.sentence(),
].join('. '),
image = faker.image.unsplash.imageUrl(),
visibility = 'public',
deleted = false,
categoryIds,
} = params
export default function create() {
return {
mutation: `
mutation(
$id: ID!
$slug: String
$title: String!
$content: String!
$image: String
$visibility: Visibility
$deleted: Boolean
$categoryIds: [ID]
) {
CreatePost(
id: $id
slug: $slug
title: $title
content: $content
image: $image
visibility: $visibility
deleted: $deleted
categoryIds: $categoryIds
) {
title
content
}
factory: async ({ args, neodeInstance }) => {
const defaults = {
id: uuid(),
slug: '',
title: faker.lorem.sentence(),
content: [
faker.lorem.sentence(),
faker.lorem.sentence(),
faker.lorem.sentence(),
faker.lorem.sentence(),
faker.lorem.sentence(),
].join('. '),
image: faker.image.unsplash.imageUrl(),
visibility: 'public',
deleted: false,
categoryIds: [],
}
`,
variables: { id, slug, title, content, image, visibility, deleted, categoryIds },
defaults.slug = slugify(defaults.title, { lower: true })
args = {
...defaults,
...args,
}
const { categoryIds } = args
if (!categoryIds.length) throw new Error('CategoryIds are empty!')
const categories = await Promise.all(
categoryIds.map(c => {
return neodeInstance.find('Category', c)
}),
)
const author = args.author || (await neodeInstance.create('User', args))
const post = await neodeInstance.create('Post', args)
await post.relateTo(author, 'author')
await Promise.all(categories.map(c => c.relateTo(post, 'post')))
return post
},
}
}