mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
721 lines
21 KiB
JavaScript
721 lines
21 KiB
JavaScript
import { createTestClient } from 'apollo-server-testing'
|
|
import Factory, { cleanDatabase } from '../../db/factories'
|
|
import { createGroupMutation, groupQuery } from '../../db/graphql/groups'
|
|
import { getNeode, getDriver } from '../../db/neo4j'
|
|
import createServer from '../../server'
|
|
|
|
const driver = getDriver()
|
|
const neode = getNeode()
|
|
|
|
let query
|
|
let mutate
|
|
let authenticatedUser
|
|
let user
|
|
|
|
const categoryIds = ['cat9', 'cat4', 'cat15']
|
|
let variables = {}
|
|
|
|
beforeAll(async () => {
|
|
await cleanDatabase()
|
|
|
|
const { server } = createServer({
|
|
context: () => {
|
|
return {
|
|
driver,
|
|
neode,
|
|
user: authenticatedUser,
|
|
}
|
|
},
|
|
})
|
|
query = createTestClient(server).query
|
|
mutate = createTestClient(server).mutate
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await cleanDatabase()
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
variables = {}
|
|
user = await Factory.build(
|
|
'user',
|
|
{
|
|
id: 'current-user',
|
|
name: 'TestUser',
|
|
},
|
|
{
|
|
email: 'test@example.org',
|
|
password: '1234',
|
|
},
|
|
)
|
|
await Promise.all([
|
|
neode.create('Category', {
|
|
id: 'cat9',
|
|
name: 'Democracy & Politics',
|
|
icon: 'university',
|
|
}),
|
|
neode.create('Category', {
|
|
id: 'cat4',
|
|
name: 'Environment & Nature',
|
|
icon: 'tree',
|
|
}),
|
|
neode.create('Category', {
|
|
id: 'cat15',
|
|
name: 'Consumption & Sustainability',
|
|
icon: 'shopping-cart',
|
|
}),
|
|
neode.create('Category', {
|
|
id: 'cat27',
|
|
name: 'Animal Protection',
|
|
icon: 'paw',
|
|
}),
|
|
])
|
|
authenticatedUser = null
|
|
})
|
|
|
|
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543
|
|
afterEach(async () => {
|
|
await cleanDatabase()
|
|
})
|
|
|
|
describe('Group', () => {
|
|
describe('unauthenticated', () => {
|
|
it('throws authorization error', async () => {
|
|
const { errors } = await query({ query: groupQuery, variables: {} })
|
|
expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
})
|
|
})
|
|
|
|
describe('authenticated', () => {
|
|
beforeEach(async () => {
|
|
authenticatedUser = await user.toJson()
|
|
})
|
|
|
|
let otherUser
|
|
|
|
beforeEach(async () => {
|
|
otherUser = await Factory.build(
|
|
'user',
|
|
{
|
|
id: 'other-user',
|
|
name: 'Other TestUser',
|
|
},
|
|
{
|
|
email: 'test2@example.org',
|
|
password: '1234',
|
|
},
|
|
)
|
|
authenticatedUser = await otherUser.toJson()
|
|
await mutate({
|
|
mutation: createGroupMutation,
|
|
variables: {
|
|
id: 'others-group',
|
|
name: 'Uninteresting Group',
|
|
about: 'We will change nothing!',
|
|
description: 'We love it like it is!?',
|
|
groupType: 'closed',
|
|
actionRadius: 'international',
|
|
categoryIds,
|
|
},
|
|
})
|
|
authenticatedUser = await user.toJson()
|
|
await mutate({
|
|
mutation: createGroupMutation,
|
|
variables: {
|
|
id: 'my-group',
|
|
name: 'The Best Group',
|
|
about: 'We will change the world!',
|
|
description: 'Some description',
|
|
groupType: 'public',
|
|
actionRadius: 'regional',
|
|
categoryIds,
|
|
},
|
|
})
|
|
})
|
|
|
|
describe('query can fetch', () => {
|
|
it('groups where user is member (or owner in this case)', async () => {
|
|
const expected = {
|
|
data: {
|
|
Group: [
|
|
{
|
|
id: 'my-group',
|
|
slug: 'the-best-group',
|
|
myRole: 'owner',
|
|
},
|
|
],
|
|
},
|
|
errors: undefined,
|
|
}
|
|
await expect(
|
|
query({ query: groupQuery, variables: { isMember: true } }),
|
|
).resolves.toMatchObject(expected)
|
|
})
|
|
|
|
it('groups where user is not(!) member', async () => {
|
|
const expected = {
|
|
data: {
|
|
Group: expect.arrayContaining([
|
|
expect.objectContaining({
|
|
id: 'others-group',
|
|
slug: 'uninteresting-group',
|
|
myRole: null,
|
|
}),
|
|
]),
|
|
},
|
|
errors: undefined,
|
|
}
|
|
await expect(
|
|
query({ query: groupQuery, variables: { isMember: false } }),
|
|
).resolves.toMatchObject(expected)
|
|
})
|
|
|
|
it('all groups', async () => {
|
|
const expected = {
|
|
data: {
|
|
Group: expect.arrayContaining([
|
|
expect.objectContaining({
|
|
id: 'my-group',
|
|
slug: 'the-best-group',
|
|
myRole: 'owner',
|
|
}),
|
|
expect.objectContaining({
|
|
id: 'others-group',
|
|
slug: 'uninteresting-group',
|
|
myRole: null,
|
|
}),
|
|
]),
|
|
},
|
|
errors: undefined,
|
|
}
|
|
await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected)
|
|
})
|
|
})
|
|
|
|
// Wolle: describe('can be filtered', () => {
|
|
// let followedUser, happyPost, cryPost
|
|
// beforeEach(async () => {
|
|
// ;[followedUser] = await Promise.all([
|
|
// Factory.build(
|
|
// 'user',
|
|
// {
|
|
// id: 'followed-by-me',
|
|
// name: 'Followed User',
|
|
// },
|
|
// {
|
|
// email: 'followed@example.org',
|
|
// password: '1234',
|
|
// },
|
|
// ),
|
|
// ])
|
|
// ;[happyPost, cryPost] = await Promise.all([
|
|
// Factory.build('post', { id: 'happy-post' }, { categoryIds: ['cat4'] }),
|
|
// Factory.build('post', { id: 'cry-post' }, { categoryIds: ['cat15'] }),
|
|
// Factory.build(
|
|
// 'post',
|
|
// {
|
|
// id: 'post-by-followed-user',
|
|
// },
|
|
// {
|
|
// categoryIds: ['cat9'],
|
|
// author: followedUser,
|
|
// },
|
|
// ),
|
|
// ])
|
|
// })
|
|
// describe('no filter', () => {
|
|
// it('returns all posts', async () => {
|
|
// const postQueryNoFilters = gql`
|
|
// query Post($filter: _PostFilter) {
|
|
// Post(filter: $filter) {
|
|
// id
|
|
// }
|
|
// }
|
|
// `
|
|
// const expected = [{ id: 'happy-post' }, { id: 'cry-post' }, { id: 'post-by-followed-user' }]
|
|
// variables = { filter: {} }
|
|
// await expect(query({ query: postQueryNoFilters, variables })).resolves.toMatchObject({
|
|
// data: {
|
|
// Post: expect.arrayContaining(expected),
|
|
// },
|
|
// })
|
|
// })
|
|
// })
|
|
// /* it('by categories', async () => {
|
|
// const postQueryFilteredByCategories = gql`
|
|
// query Post($filter: _PostFilter) {
|
|
// Post(filter: $filter) {
|
|
// id
|
|
// categories {
|
|
// id
|
|
// }
|
|
// }
|
|
// }
|
|
// `
|
|
// const expected = {
|
|
// data: {
|
|
// Post: [
|
|
// {
|
|
// id: 'post-by-followed-user',
|
|
// categories: [{ id: 'cat9' }],
|
|
// },
|
|
// ],
|
|
// },
|
|
// }
|
|
// variables = { ...variables, filter: { categories_some: { id_in: ['cat9'] } } }
|
|
// await expect(
|
|
// query({ query: postQueryFilteredByCategories, variables }),
|
|
// ).resolves.toMatchObject(expected)
|
|
// }) */
|
|
// describe('by emotions', () => {
|
|
// const postQueryFilteredByEmotions = gql`
|
|
// query Post($filter: _PostFilter) {
|
|
// Post(filter: $filter) {
|
|
// id
|
|
// emotions {
|
|
// emotion
|
|
// }
|
|
// }
|
|
// }
|
|
// `
|
|
// it('filters by single emotion', async () => {
|
|
// const expected = {
|
|
// data: {
|
|
// Post: [
|
|
// {
|
|
// id: 'happy-post',
|
|
// emotions: [{ emotion: 'happy' }],
|
|
// },
|
|
// ],
|
|
// },
|
|
// }
|
|
// await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
|
// variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy'] } } }
|
|
// await expect(
|
|
// query({ query: postQueryFilteredByEmotions, variables }),
|
|
// ).resolves.toMatchObject(expected)
|
|
// })
|
|
// it('filters by multiple emotions', async () => {
|
|
// const expected = [
|
|
// {
|
|
// id: 'happy-post',
|
|
// emotions: [{ emotion: 'happy' }],
|
|
// },
|
|
// {
|
|
// id: 'cry-post',
|
|
// emotions: [{ emotion: 'cry' }],
|
|
// },
|
|
// ]
|
|
// await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
|
// await user.relateTo(cryPost, 'emoted', { emotion: 'cry' })
|
|
// variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy', 'cry'] } } }
|
|
// await expect(
|
|
// query({ query: postQueryFilteredByEmotions, variables }),
|
|
// ).resolves.toMatchObject({
|
|
// data: {
|
|
// Post: expect.arrayContaining(expected),
|
|
// },
|
|
// errors: undefined,
|
|
// })
|
|
// })
|
|
// })
|
|
// it('by followed-by', async () => {
|
|
// const postQueryFilteredByUsersFollowed = gql`
|
|
// query Post($filter: _PostFilter) {
|
|
// Post(filter: $filter) {
|
|
// id
|
|
// author {
|
|
// id
|
|
// name
|
|
// }
|
|
// }
|
|
// }
|
|
// `
|
|
// await user.relateTo(followedUser, 'following')
|
|
// variables = { filter: { author: { followedBy_some: { id: 'current-user' } } } }
|
|
// await expect(
|
|
// query({ query: postQueryFilteredByUsersFollowed, variables }),
|
|
// ).resolves.toMatchObject({
|
|
// data: {
|
|
// Post: [
|
|
// {
|
|
// id: 'post-by-followed-user',
|
|
// author: { id: 'followed-by-me', name: 'Followed User' },
|
|
// },
|
|
// ],
|
|
// },
|
|
// errors: undefined,
|
|
// })
|
|
// })
|
|
// })
|
|
})
|
|
})
|
|
|
|
describe('CreateGroup', () => {
|
|
beforeEach(() => {
|
|
variables = {
|
|
...variables,
|
|
id: 'g589',
|
|
name: 'The Best Group',
|
|
slug: 'the-group',
|
|
about: 'We will change the world!',
|
|
description: 'Some description',
|
|
groupType: 'public',
|
|
actionRadius: 'regional',
|
|
categoryIds,
|
|
}
|
|
})
|
|
|
|
describe('unauthenticated', () => {
|
|
it('throws authorization error', async () => {
|
|
const { errors } = await mutate({ mutation: createGroupMutation, variables })
|
|
expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
})
|
|
})
|
|
|
|
describe('authenticated', () => {
|
|
beforeEach(async () => {
|
|
authenticatedUser = await user.toJson()
|
|
})
|
|
|
|
it('creates a group', async () => {
|
|
const expected = {
|
|
data: {
|
|
CreateGroup: {
|
|
name: 'The Best Group',
|
|
slug: 'the-group',
|
|
about: 'We will change the world!',
|
|
},
|
|
},
|
|
errors: undefined,
|
|
}
|
|
await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
|
|
expected,
|
|
)
|
|
})
|
|
|
|
it('assigns the authenticated user as owner', async () => {
|
|
const expected = {
|
|
data: {
|
|
CreateGroup: {
|
|
name: 'The Best Group',
|
|
myRole: 'owner',
|
|
// Wolle: owner: {
|
|
// name: 'TestUser',
|
|
// },
|
|
},
|
|
},
|
|
errors: undefined,
|
|
}
|
|
await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
|
|
expected,
|
|
)
|
|
})
|
|
|
|
it('`disabled` and `deleted` default to `false`', async () => {
|
|
const expected = { data: { CreateGroup: { disabled: false, deleted: false } } }
|
|
await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
|
|
expected,
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
// 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) {
|
|
// id
|
|
// title
|
|
// content
|
|
// author {
|
|
// name
|
|
// slug
|
|
// }
|
|
// createdAt
|
|
// updatedAt
|
|
// }
|
|
// }
|
|
// `
|
|
// beforeEach(async () => {
|
|
// author = await Factory.build('user', { slug: 'the-author' })
|
|
// newlyCreatedPost = await Factory.build(
|
|
// 'post',
|
|
// {
|
|
// id: 'p9876',
|
|
// title: 'Old title',
|
|
// content: 'Old content',
|
|
// },
|
|
// {
|
|
// author,
|
|
// categoryIds,
|
|
// },
|
|
// )
|
|
|
|
// variables = {
|
|
// id: 'p9876',
|
|
// title: 'New title',
|
|
// content: 'New content',
|
|
// }
|
|
// })
|
|
|
|
// describe('unauthenticated', () => {
|
|
// it('throws authorization error', async () => {
|
|
// authenticatedUser = null
|
|
// expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject({
|
|
// errors: [{ message: 'Not Authorised!' }],
|
|
// data: { UpdatePost: null },
|
|
// })
|
|
// })
|
|
// })
|
|
|
|
// describe('authenticated but not the author', () => {
|
|
// beforeEach(async () => {
|
|
// authenticatedUser = await user.toJson()
|
|
// })
|
|
|
|
// it('throws authorization error', async () => {
|
|
// const { errors } = await mutate({ mutation: updatePostMutation, variables })
|
|
// expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
// })
|
|
// })
|
|
|
|
// describe('authenticated as author', () => {
|
|
// beforeEach(async () => {
|
|
// authenticatedUser = await author.toJson()
|
|
// })
|
|
|
|
// it('updates a post', async () => {
|
|
// const expected = {
|
|
// data: { UpdatePost: { id: 'p9876', content: 'New content' } },
|
|
// errors: undefined,
|
|
// }
|
|
// await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
|
|
// expected,
|
|
// )
|
|
// })
|
|
|
|
// it('updates a post, but maintains non-updated attributes', async () => {
|
|
// const expected = {
|
|
// data: {
|
|
// UpdatePost: { id: 'p9876', content: 'New content', createdAt: expect.any(String) },
|
|
// },
|
|
// errors: undefined,
|
|
// }
|
|
// await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
|
|
// expected,
|
|
// )
|
|
// })
|
|
|
|
// 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', () => {
|
|
// it('resolves and keeps current categories', async () => {
|
|
// const expected = {
|
|
// data: {
|
|
// UpdatePost: {
|
|
// id: 'p9876',
|
|
// categories: expect.arrayContaining([{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]),
|
|
// },
|
|
// },
|
|
// errors: undefined,
|
|
// }
|
|
// await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
|
|
// expected,
|
|
// )
|
|
// })
|
|
// }) */
|
|
|
|
// /* describe('given category ids', () => {
|
|
// beforeEach(() => {
|
|
// variables = { ...variables, categoryIds: ['cat27'] }
|
|
// })
|
|
|
|
// it('updates categories of a post', async () => {
|
|
// const expected = {
|
|
// data: {
|
|
// UpdatePost: {
|
|
// id: 'p9876',
|
|
// categories: expect.arrayContaining([{ id: 'cat27' }]),
|
|
// },
|
|
// },
|
|
// errors: undefined,
|
|
// }
|
|
// await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
|
|
// expected,
|
|
// )
|
|
// })
|
|
// }) */
|
|
|
|
// describe('params.image', () => {
|
|
// describe('is object', () => {
|
|
// beforeEach(() => {
|
|
// variables = { ...variables, image: { sensitive: true } }
|
|
// })
|
|
// it('updates the image', async () => {
|
|
// await expect(neode.first('Image', { sensitive: true })).resolves.toBeFalsy()
|
|
// await mutate({ mutation: updatePostMutation, variables })
|
|
// await expect(neode.first('Image', { sensitive: true })).resolves.toBeTruthy()
|
|
// })
|
|
// })
|
|
|
|
// describe('is null', () => {
|
|
// beforeEach(() => {
|
|
// variables = { ...variables, image: null }
|
|
// })
|
|
// it('deletes the image', async () => {
|
|
// await expect(neode.all('Image')).resolves.toHaveLength(6)
|
|
// await mutate({ mutation: updatePostMutation, variables })
|
|
// await expect(neode.all('Image')).resolves.toHaveLength(5)
|
|
// })
|
|
// })
|
|
|
|
// describe('is undefined', () => {
|
|
// beforeEach(() => {
|
|
// delete variables.image
|
|
// })
|
|
// it('keeps the image unchanged', async () => {
|
|
// await expect(neode.first('Image', { sensitive: true })).resolves.toBeFalsy()
|
|
// await mutate({ mutation: updatePostMutation, variables })
|
|
// await expect(neode.first('Image', { sensitive: true })).resolves.toBeFalsy()
|
|
// })
|
|
// })
|
|
// })
|
|
// })
|
|
// })
|
|
|
|
// describe('DeletePost', () => {
|
|
// let author
|
|
// const deletePostMutation = gql`
|
|
// mutation ($id: ID!) {
|
|
// DeletePost(id: $id) {
|
|
// id
|
|
// deleted
|
|
// content
|
|
// contentExcerpt
|
|
// image {
|
|
// url
|
|
// }
|
|
// comments {
|
|
// deleted
|
|
// content
|
|
// contentExcerpt
|
|
// }
|
|
// }
|
|
// }
|
|
// `
|
|
|
|
// beforeEach(async () => {
|
|
// author = await Factory.build('user')
|
|
// await Factory.build(
|
|
// 'post',
|
|
// {
|
|
// id: 'p4711',
|
|
// title: 'I will be deleted',
|
|
// content: 'To be deleted',
|
|
// },
|
|
// {
|
|
// image: Factory.build('image', {
|
|
// url: 'path/to/some/image',
|
|
// }),
|
|
// author,
|
|
// categoryIds,
|
|
// },
|
|
// )
|
|
// variables = { ...variables, id: 'p4711' }
|
|
// })
|
|
|
|
// describe('unauthenticated', () => {
|
|
// it('throws authorization error', async () => {
|
|
// const { errors } = await mutate({ mutation: deletePostMutation, variables })
|
|
// expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
// })
|
|
// })
|
|
|
|
// describe('authenticated but not the author', () => {
|
|
// beforeEach(async () => {
|
|
// authenticatedUser = await user.toJson()
|
|
// })
|
|
|
|
// it('throws authorization error', async () => {
|
|
// const { errors } = await mutate({ mutation: deletePostMutation, variables })
|
|
// expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
|
// })
|
|
// })
|
|
|
|
// describe('authenticated as author', () => {
|
|
// beforeEach(async () => {
|
|
// authenticatedUser = await author.toJson()
|
|
// })
|
|
|
|
// it('marks the post as deleted and blacks out attributes', async () => {
|
|
// const expected = {
|
|
// data: {
|
|
// DeletePost: {
|
|
// id: 'p4711',
|
|
// deleted: true,
|
|
// content: 'UNAVAILABLE',
|
|
// contentExcerpt: 'UNAVAILABLE',
|
|
// image: null,
|
|
// comments: [],
|
|
// },
|
|
// },
|
|
// }
|
|
// await expect(mutate({ mutation: deletePostMutation, variables })).resolves.toMatchObject(
|
|
// expected,
|
|
// )
|
|
// })
|
|
|
|
// describe('if there are comments on the post', () => {
|
|
// beforeEach(async () => {
|
|
// await Factory.build(
|
|
// 'comment',
|
|
// {
|
|
// content: 'to be deleted comment content',
|
|
// contentExcerpt: 'to be deleted comment content',
|
|
// },
|
|
// {
|
|
// postId: 'p4711',
|
|
// },
|
|
// )
|
|
// })
|
|
|
|
// it('marks the comments as deleted', async () => {
|
|
// const expected = {
|
|
// data: {
|
|
// DeletePost: {
|
|
// id: 'p4711',
|
|
// deleted: true,
|
|
// content: 'UNAVAILABLE',
|
|
// contentExcerpt: 'UNAVAILABLE',
|
|
// image: null,
|
|
// comments: [
|
|
// {
|
|
// deleted: true,
|
|
// // Should we black out the comment content in the database, too?
|
|
// content: 'UNAVAILABLE',
|
|
// contentExcerpt: 'UNAVAILABLE',
|
|
// },
|
|
// ],
|
|
// },
|
|
// },
|
|
// }
|
|
// await expect(mutate({ mutation: deletePostMutation, variables })).resolves.toMatchObject(
|
|
// expected,
|
|
// )
|
|
// })
|
|
// })
|
|
// })
|
|
// })
|