diff --git a/backend/src/schema/resolvers/moderation.spec.js b/backend/src/schema/resolvers/moderation.spec.js index 3107a5799..2ac0dd934 100644 --- a/backend/src/schema/resolvers/moderation.spec.js +++ b/backend/src/schema/resolvers/moderation.spec.js @@ -1,420 +1,349 @@ -import { GraphQLClient } from 'graphql-request' +import { createTestClient } from 'apollo-server-testing' import Factory from '../../seed/factories' -import { host, login, gql } from '../../jest/helpers' -import { neode } from '../../bootstrap/neo4j' +import { gql } from '../../jest/helpers' +import { neode as getNeode, getDriver } from '../../bootstrap/neo4j' +import createServer from '../../server' -let client const factory = Factory() -const instance = neode() -const categoryIds = ['cat9'] +const neode = getNeode() +const driver = getDriver() -const setupAuthenticateClient = params => { - const authenticateClient = async () => { - await factory.create('User', params) - const headers = await login(params) - client = new GraphQLClient(host, { headers }) +let query, mutate, authenticatedUser, variables, moderator, nonModerator + +const disableMutation = gql` + mutation($id: ID!) { + disable(id: $id) } - return authenticateClient -} - -let createResource -let authenticateClient -let createPostVariables -let createCommentVariables - -beforeEach(async () => { - createResource = () => {} - authenticateClient = () => { - client = new GraphQLClient(host) +` +const enableMutation = gql` + mutation($id: ID!) { + enable(id: $id) } - await instance.create('Category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', - }) -}) +` -const setup = async () => { - await createResource() - await authenticateClient() -} - -afterEach(async () => { - await factory.cleanDatabase() -}) - -describe('disable', () => { - const mutation = gql` - mutation($id: ID!) { - disable(id: $id) +const commentQuery = gql` + query($id: ID!) { + Comment(id: $id) { + id + disabled + disabledBy { + id + } } - ` - let variables - - beforeEach(() => { - // our defaul set of variables - variables = { - id: 'blabla', - } - }) - - const action = async () => { - return client.request(mutation, variables) } +` - it('throws authorization error', async () => { - await setup() - await expect(action()).rejects.toThrow('Not Authorised') +const postQuery = gql` + query($id: ID) { + Post(id: $id) { + id + disabled + disabledBy { + id + } + } + } +` + +describe('moderate resources', () => { + beforeAll(() => { + authenticatedUser = undefined + const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + } + }, + }) + mutate = createTestClient(server).mutate + query = createTestClient(server).query }) - describe('authenticated', () => { + beforeEach(async () => { + variables = {} + authenticatedUser = null + moderator = await factory.create('User', { + id: 'moderator-id', + name: 'Moderator', + email: 'moderator@example.org', + password: '1234', + role: 'moderator', + }) + }) + + afterEach(async () => { + await factory.cleanDatabase() + }) + + describe('disable', () => { beforeEach(() => { - authenticateClient = setupAuthenticateClient({ - email: 'user@example.org', - password: '1234', + variables = { + id: 'some-resource', + } + }) + describe('unauthenticated', () => { + it('throws authorization error', async () => { + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) }) }) - - it('throws authorization error', async () => { - await setup() - await expect(action()).rejects.toThrow('Not Authorised') - }) - - describe('as moderator', () => { - beforeEach(() => { - authenticateClient = setupAuthenticateClient({ - id: 'u7', - email: 'moderator@example.org', - password: '1234', - role: 'moderator', + describe('authenticated', () => { + describe('non moderator', () => { + beforeEach(async () => { + nonModerator = await factory.create('User', { + id: 'non-moderator', + name: 'Non Moderator', + email: 'non.moderator@example.org', + password: '1234', + }) + authenticatedUser = await nonModerator.toJson() + }) + it('throws authorization error', async () => { + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) }) }) - describe('on something that is not a (Comment|Post|User) ', () => { + describe('moderator', () => { beforeEach(async () => { - variables = { - id: 't23', - } - createResource = () => { - return Promise.all([factory.create('Tag', { id: 't23' })]) - } + authenticatedUser = await moderator.toJson() }) - it('returns null', async () => { - const expected = { disable: null } - await setup() - await expect(action()).resolves.toEqual(expected) - }) - }) + describe('moderate a resource that is not a (Comment|Post|User) ', () => { + beforeEach(async () => { + variables = { + id: 'sample-tag-id', + } + await factory.create('Tag', { id: 'sample-tag-id' }) + }) - describe('on a comment', () => { - beforeEach(async () => { - variables = { - id: 'c47', - } - createPostVariables = { - id: 'p3', - title: 'post to comment on', - content: 'please comment on me', - categoryIds, - } - createCommentVariables = { - id: 'c47', - postId: 'p3', - content: 'this comment was created for this post', - } - createResource = async () => { - await factory.create('User', { - id: 'u45', - email: 'commenter@example.org', - password: '1234', + it('returns null', async () => { + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: null }, }) - const asAuthenticatedUser = await factory.authenticateAs({ - email: 'commenter@example.org', - password: '1234', + }) + }) + + describe('moderate a comment', () => { + beforeEach(async () => { + variables = {} + await factory.create('Comment', { + id: 'comment-id', }) - await asAuthenticatedUser.create('Post', createPostVariables) - await asAuthenticatedUser.create('Comment', createCommentVariables) - } + }) + + it('returns disabled resource id', async () => { + variables = { id: 'comment-id' } + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: 'comment-id' }, + errors: undefined, + }) + }) + + it('changes .disabledBy', async () => { + variables = { id: 'comment-id' } + const before = { data: { Comment: [{ id: 'comment-id', disabledBy: null }] } } + const expected = { + data: { Comment: [{ id: 'comment-id', disabledBy: { id: 'moderator-id' } }] }, + } + await expect(query({ query: commentQuery, variables })).resolves.toMatchObject(before) + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: 'comment-id' }, + }) + await expect(query({ query: commentQuery, variables })).resolves.toMatchObject(expected) + }) + + it('updates .disabled on comment', async () => { + variables = { id: 'comment-id' } + const before = { data: { Comment: [{ id: 'comment-id', disabled: false }] } } + const expected = { data: { Comment: [{ id: 'comment-id', disabled: true }] } } + + await expect(query({ query: commentQuery, variables })).resolves.toMatchObject(before) + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: 'comment-id' }, + }) + await expect(query({ query: commentQuery, variables })).resolves.toMatchObject(expected) + }) }) - it('returns disabled resource id', async () => { - const expected = { disable: 'c47' } - await setup() - await expect(action()).resolves.toEqual(expected) - }) - - it('changes .disabledBy', async () => { - const before = { Comment: [{ id: 'c47', disabledBy: null }] } - const expected = { Comment: [{ id: 'c47', disabledBy: { id: 'u7' } }] } - - await setup() - await expect(client.request('{ Comment { id, disabledBy { id } } }')).resolves.toEqual( - before, - ) - await action() - await expect( - client.request('{ Comment(disabled: true) { id, disabledBy { id } } }'), - ).resolves.toEqual(expected) - }) - - it('updates .disabled on comment', async () => { - const before = { Comment: [{ id: 'c47', disabled: false }] } - const expected = { Comment: [{ id: 'c47', disabled: true }] } - - await setup() - await expect(client.request('{ Comment { id disabled } }')).resolves.toEqual(before) - await action() - await expect( - client.request('{ Comment(disabled: true) { id disabled } }'), - ).resolves.toEqual(expected) - }) - }) - - describe('on a post', () => { - beforeEach(async () => { - variables = { - id: 'p9', - } - - createResource = async () => { - await factory.create('User', { email: 'author@example.org', password: '1234' }) - await factory.authenticateAs({ email: 'author@example.org', password: '1234' }) + describe('moderate a post', () => { + beforeEach(async () => { + variables = {} await factory.create('Post', { - id: 'p9', // that's the ID we will look for - categoryIds, + id: 'sample-post-id', }) - } + }) + + it('returns disabled resource id', async () => { + variables = { id: 'sample-post-id' } + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: 'sample-post-id' }, + }) + }) + + it('changes .disabledBy', async () => { + variables = { id: 'sample-post-id' } + const before = { data: { Post: [{ id: 'sample-post-id', disabledBy: null }] } } + const expected = { + data: { Post: [{ id: 'sample-post-id', disabledBy: { id: 'moderator-id' } }] }, + } + + await expect(query({ query: postQuery, variables })).resolves.toMatchObject(before) + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: 'sample-post-id' }, + }) + await expect(query({ query: postQuery, variables })).resolves.toMatchObject(expected) + }) + + it('updates .disabled on post', async () => { + const before = { data: { Post: [{ id: 'sample-post-id', disabled: false }] } } + const expected = { data: { Post: [{ id: 'sample-post-id', disabled: true }] } } + variables = { id: 'sample-post-id' } + + await expect(query({ query: postQuery, variables })).resolves.toMatchObject(before) + await expect(mutate({ mutation: disableMutation, variables })).resolves.toMatchObject({ + data: { disable: 'sample-post-id' }, + }) + await expect(query({ query: postQuery, variables })).resolves.toMatchObject(expected) + }) + }) + }) + }) + }) + + describe('enable', () => { + describe('unautenticated user', () => { + it('throws authorization error', async () => { + variables = { id: 'sample-post-id' } + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) + }) + }) + + describe('authenticated user', () => { + describe('non moderator', () => { + beforeEach(async () => { + nonModerator = await factory.create('User', { + id: 'non-moderator', + name: 'Non Moderator', + email: 'non.moderator@example.org', + password: '1234', + }) + authenticatedUser = await nonModerator.toJson() + }) + it('throws authorization error', async () => { + variables = { id: 'sample-post-id' } + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) + }) + }) + + describe('moderator', () => { + beforeEach(async () => { + authenticatedUser = await moderator.toJson() + }) + describe('moderate a resource that is not a (Comment|Post|User) ', () => { + beforeEach(async () => { + await Promise.all([factory.create('Tag', { id: 'sample-tag-id' })]) + }) + + it('returns null', async () => { + await expect( + mutate({ mutation: enableMutation, variables: { id: 'sample-tag-id' } }), + ).resolves.toMatchObject({ + data: { enable: null }, + }) + }) }) - it('returns disabled resource id', async () => { - const expected = { disable: 'p9' } - await setup() - await expect(action()).resolves.toEqual(expected) + describe('moderate a comment', () => { + beforeEach(async () => { + variables = { id: 'comment-id' } + await factory.create('Comment', { + id: 'comment-id', + }) + await mutate({ mutation: disableMutation, variables }) + }) + + it('returns enabled resource id', async () => { + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + data: { enable: 'comment-id' }, + errors: undefined, + }) + }) + + it('changes .disabledBy', async () => { + const expected = { + data: { Comment: [{ id: 'comment-id', disabledBy: null }] }, + errors: undefined, + } + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + data: { enable: 'comment-id' }, + errors: undefined, + }) + await expect(query({ query: commentQuery, variables })).resolves.toMatchObject(expected) + }) + + it('updates .disabled on comment', async () => { + const expected = { + data: { Comment: [{ id: 'comment-id', disabled: false }] }, + errors: undefined, + } + + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + data: { enable: 'comment-id' }, + errors: undefined, + }) + await expect(query({ query: commentQuery, variables })).resolves.toMatchObject(expected) + }) }) - it('changes .disabledBy', async () => { - const before = { Post: [{ id: 'p9', disabledBy: null }] } - const expected = { Post: [{ id: 'p9', disabledBy: { id: 'u7' } }] } + describe('moderate a post', () => { + beforeEach(async () => { + variables = { id: 'post-id' } + await factory.create('Post', { + id: 'post-id', + }) + await mutate({ mutation: disableMutation, variables }) + }) - await setup() - await expect(client.request('{ Post { id, disabledBy { id } } }')).resolves.toEqual( - before, - ) - await action() - await expect( - client.request('{ Post(disabled: true) { id, disabledBy { id } } }'), - ).resolves.toEqual(expected) - }) + it('returns enabled resource id', async () => { + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + data: { enable: 'post-id' }, + errors: undefined, + }) + }) - it('updates .disabled on post', async () => { - const before = { Post: [{ id: 'p9', disabled: false }] } - const expected = { Post: [{ id: 'p9', disabled: true }] } + it('changes .disabledBy', async () => { + const expected = { + data: { Post: [{ id: 'post-id', disabledBy: null }] }, + errors: undefined, + } + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + data: { enable: 'post-id' }, + errors: undefined, + }) + await expect(query({ query: postQuery, variables })).resolves.toMatchObject(expected) + }) - await setup() - await expect(client.request('{ Post { id disabled } }')).resolves.toEqual(before) - await action() - await expect(client.request('{ Post(disabled: true) { id disabled } }')).resolves.toEqual( - expected, - ) - }) - }) - }) - }) -}) - -describe('enable', () => { - const mutation = gql` - mutation($id: ID!) { - enable(id: $id) - } - ` - let variables - - const action = async () => { - return client.request(mutation, variables) - } - - beforeEach(() => { - // our defaul set of variables - variables = { - id: 'blabla', - } - }) - - it('throws authorization error', async () => { - await setup() - await expect(action()).rejects.toThrow('Not Authorised') - }) - - describe('authenticated', () => { - beforeEach(() => { - authenticateClient = setupAuthenticateClient({ - email: 'user@example.org', - password: '1234', - }) - }) - - it('throws authorization error', async () => { - await setup() - await expect(action()).rejects.toThrow('Not Authorised') - }) - - describe('as moderator', () => { - beforeEach(async () => { - authenticateClient = setupAuthenticateClient({ - role: 'moderator', - email: 'someuser@example.org', - password: '1234', - }) - }) - - describe('on something that is not a (Comment|Post|User) ', () => { - beforeEach(async () => { - variables = { - id: 't23', - } - createResource = () => { - // we cannot create a :DISABLED relationship here - return Promise.all([factory.create('Tag', { id: 't23' })]) - } - }) - - it('returns null', async () => { - const expected = { enable: null } - await setup() - await expect(action()).resolves.toEqual(expected) - }) - }) - - describe('on a comment', () => { - beforeEach(async () => { - variables = { - id: 'c456', - } - createPostVariables = { - id: 'p9', - title: 'post to comment on', - content: 'please comment on me', - categoryIds, - } - createCommentVariables = { - id: 'c456', - postId: 'p9', - content: 'this comment was created for this post', - } - createResource = async () => { - await factory.create('User', { - id: 'u123', - email: 'author@example.org', - password: '1234', - }) - const asAuthenticatedUser = await factory.authenticateAs({ - email: 'author@example.org', - password: '1234', - }) - await asAuthenticatedUser.create('Post', createPostVariables) - await asAuthenticatedUser.create('Comment', createCommentVariables) - - const disableMutation = gql` - mutation { - disable(id: "c456") - } - ` - await factory.mutate(disableMutation) // that's we want to delete - } - }) - - it('returns disabled resource id', async () => { - const expected = { enable: 'c456' } - await setup() - await expect(action()).resolves.toEqual(expected) - }) - - it('changes .disabledBy', async () => { - const before = { Comment: [{ id: 'c456', disabledBy: { id: 'u123' } }] } - const expected = { Comment: [{ id: 'c456', disabledBy: null }] } - - await setup() - await expect( - client.request('{ Comment(disabled: true) { id, disabledBy { id } } }'), - ).resolves.toEqual(before) - await action() - await expect(client.request('{ Comment { id, disabledBy { id } } }')).resolves.toEqual( - expected, - ) - }) - - it('updates .disabled on post', async () => { - const before = { Comment: [{ id: 'c456', disabled: true }] } - const expected = { Comment: [{ id: 'c456', disabled: false }] } - - await setup() - await expect( - client.request('{ Comment(disabled: true) { id disabled } }'), - ).resolves.toEqual(before) - await action() // this updates .disabled - await expect(client.request('{ Comment { id disabled } }')).resolves.toEqual(expected) - }) - }) - - describe('on a post', () => { - beforeEach(async () => { - variables = { - id: 'p9', - } - - createResource = async () => { - await factory.create('User', { - id: 'u123', - email: 'author@example.org', - password: '1234', - }) - await factory.authenticateAs({ email: 'author@example.org', password: '1234' }) - await factory.create('Post', { - id: 'p9', // that's the ID we will look for - categoryIds, - }) - - const disableMutation = gql` - mutation { - disable(id: "p9") - } - ` - await factory.mutate(disableMutation) // that's we want to delete - } - }) - - it('returns disabled resource id', async () => { - const expected = { enable: 'p9' } - await setup() - await expect(action()).resolves.toEqual(expected) - }) - - it('changes .disabledBy', async () => { - const before = { Post: [{ id: 'p9', disabledBy: { id: 'u123' } }] } - const expected = { Post: [{ id: 'p9', disabledBy: null }] } - - await setup() - await expect( - client.request('{ Post(disabled: true) { id, disabledBy { id } } }'), - ).resolves.toEqual(before) - await action() - await expect(client.request('{ Post { id, disabledBy { id } } }')).resolves.toEqual( - expected, - ) - }) - - it('updates .disabled on post', async () => { - const before = { Post: [{ id: 'p9', disabled: true }] } - const expected = { Post: [{ id: 'p9', disabled: false }] } - - await setup() - await expect(client.request('{ Post(disabled: true) { id disabled } }')).resolves.toEqual( - before, - ) - await action() // this updates .disabled - await expect(client.request('{ Post { id disabled } }')).resolves.toEqual(expected) + it('updates .disabled on post', async () => { + const expected = { + data: { Post: [{ id: 'post-id', disabled: false }] }, + errors: undefined, + } + + await expect(mutate({ mutation: enableMutation, variables })).resolves.toMatchObject({ + data: { enable: 'post-id' }, + errors: undefined, + }) + await expect(query({ query: postQuery, variables })).resolves.toMatchObject(expected) + }) }) }) })