From 9d5c192869ec0b088fa071d827b27cf6ca442b78 Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 30 Jul 2020 11:45:51 +0200 Subject: [PATCH] tests user.spec.js tests once clean once broken always alternating --- .../src/schema/resolvers/statistics.spec.js | 196 +-- backend/src/schema/resolvers/users.spec.js | 1366 +++++++---------- 2 files changed, 628 insertions(+), 934 deletions(-) diff --git a/backend/src/schema/resolvers/statistics.spec.js b/backend/src/schema/resolvers/statistics.spec.js index c5bb5f88b..440359afe 100644 --- a/backend/src/schema/resolvers/statistics.spec.js +++ b/backend/src/schema/resolvers/statistics.spec.js @@ -8,7 +8,7 @@ let query, authenticatedUser const instance = getNeode() const driver = getDriver() -const statisticsQuery = gql` +const statisticsQuery = gql ` query { statistics { countUsers @@ -22,118 +22,118 @@ const statisticsQuery = gql` } ` beforeAll(() => { - authenticatedUser = undefined - const { server } = createServer({ - context: () => { - return { - driver, - neode: instance, - user: authenticatedUser, - } - }, - }) - query = createTestClient(server).query + authenticatedUser = undefined + const { server } = createServer({ + context: () => { + return { + driver, + neode: instance, + user: authenticatedUser, + } + }, + }) + query = createTestClient(server).query }) -afterEach(async () => { - await cleanDatabase() +afterEach(async() => { + await cleanDatabase() }) describe('statistics', () => { - describe('countUsers', () => { - beforeEach(async () => { - await Promise.all( - [...Array(6).keys()].map(() => { - return Factory.build('user') - }), - ) + describe('countUsers', () => { + beforeEach(async() => { + await Promise.all( + [...Array(6).keys()].map(() => { + return Factory.build('user') + }), + ) + }) + + it('returns the count of all users', async() => { + await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ + data: { statistics: { countUsers: 6 } }, + errors: undefined, + }) + }) }) - it('returns the count of all users', async () => { - await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ - data: { statistics: { countUsers: 6 } }, - errors: undefined, - }) - }) - }) + describe('countPosts', () => { + beforeEach(async() => { + await Promise.all( + [...Array(3).keys()].map(() => { + return Factory.build('post') + }), + ) + }) - describe('countPosts', () => { - beforeEach(async () => { - await Promise.all( - [...Array(3).keys()].map(() => { - return Factory.build('post') - }), - ) + it('returns the count of all posts', async() => { + await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ + data: { statistics: { countPosts: 3 } }, + errors: undefined, + }) + }) }) - it('returns the count of all posts', async () => { - await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ - data: { statistics: { countPosts: 3 } }, - errors: undefined, - }) - }) - }) + describe('countComments', () => { + beforeEach(async() => { + await Promise.all( + [...Array(2).keys()].map(() => { + return Factory.build('comment') + }), + ) + }) - describe('countComments', () => { - beforeEach(async () => { - await Promise.all( - [...Array(2).keys()].map(() => { - return Factory.build('comment') - }), - ) + it('returns the count of all comments', async() => { + await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ + data: { statistics: { countComments: 2 } }, + errors: undefined, + }) + }) }) - it('returns the count of all comments', async () => { - await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ - data: { statistics: { countComments: 2 } }, - errors: undefined, - }) - }) - }) + describe('countFollows', () => { + let users + beforeEach(async() => { + users = await Promise.all( + [...Array(2).keys()].map(() => { + return Factory.build('user') + }), + ) + await users[0].relateTo(users[1], 'following') + }) - describe('countFollows', () => { - let users - beforeEach(async () => { - users = await Promise.all( - [...Array(2).keys()].map(() => { - return Factory.build('user') - }), - ) - await users[0].relateTo(users[1], 'following') + it('returns the count of all follows', async() => { + await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ + data: { statistics: { countFollows: 1 } }, + errors: undefined, + }) + }) }) - it('returns the count of all follows', async () => { - await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ - data: { statistics: { countFollows: 1 } }, - errors: undefined, - }) - }) - }) + describe('countShouts', () => { + let users, posts + beforeEach(async() => { + users = await Promise.all( + [...Array(2).keys()].map(() => { + return Factory.build('user') + }), + ) + posts = await Promise.all( + [...Array(3).keys()].map(() => { + return Factory.build('post') + }), + ) + await Promise.all([ + users[0].relateTo(posts[1], 'shouted'), + users[1].relateTo(posts[0], 'shouted'), + ]) + }) - describe('countShouts', () => { - let users, posts - beforeEach(async () => { - users = await Promise.all( - [...Array(2).keys()].map(() => { - return Factory.build('user') - }), - ) - posts = await Promise.all( - [...Array(3).keys()].map(() => { - return Factory.build('post') - }), - ) - await Promise.all([ - users[0].relateTo(posts[1], 'shouted'), - users[1].relateTo(posts[0], 'shouted'), - ]) + it('returns the count of all shouts', async() => { + await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ + data: { statistics: { countShouts: 2 } }, + errors: undefined, + }) + }) }) - - it('returns the count of all shouts', async () => { - await expect(query({ query: statisticsQuery })).resolves.toMatchObject({ - data: { statistics: { countShouts: 2 } }, - errors: undefined, - }) - }) - }) -}) +}) \ No newline at end of file diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index cb9012133..0e6e2b8dc 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -6,105 +6,478 @@ import { createTestClient } from 'apollo-server-testing' const categoryIds = ['cat9'] let user +let anotherUser +let moderator +let admin +let authenticatedUser let query let mutate -let authenticatedUser let variables const driver = getDriver() const neode = getNeode() -beforeAll(() => { - const { server } = createServer({ - context: () => { - return { - driver, - neode, - user: authenticatedUser, + +const deleteUserMutation = gql ` +mutation($id: ID!, $resource: [Deletable]) { + DeleteUser(id: $id, resource: $resource) { + id + name + about + deleted + contributions { + id + content + contentExcerpt + deleted + comments { + id + content + contentExcerpt + deleted } - }, - }) - query = createTestClient(server).query - mutate = createTestClient(server).mutate + } + comments { + id + content + contentExcerpt + deleted + } + } +} +` + + +beforeAll(() => { + const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + } + }, + }) + query = createTestClient(server).query + mutate = createTestClient(server).mutate + console.log("z18 beforeAll") }) -beforeEach(async () => { - await cleanDatabase() +beforeEach(async() => { + await cleanDatabase() }) -describe('User', () => { - describe('query by email address', () => { - beforeEach(async () => { - await Factory.build('user', { name: 'Johnny' }, { email: 'any-email-address@example.org' }) + + + + + +describe('Delete a User as another user', () => { + beforeEach(async() => { + variables = { id: ' u343', resource: [] } + + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', + }) }) - const userQuery = gql` + beforeEach(async() => { + const anotherUser = await Factory.build( + 'user', { + role: 'user', + }, { + email: 'user@example.org', + password: '1234', + }, + ) + + authenticatedUser = await anotherUser.toJson() + }) + + it("an ordinary user has no authorization to delete another user's account", async() => { + const { errors } = await mutate({ mutation: deleteUserMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) +}) + +describe('Delete a User as moderator', () => { + beforeEach(async() => { + variables = { id: ' u343', resource: [] } + + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', + }) + }) + + beforeEach(async() => { + const moderator = await Factory.build( + 'user', { + role: 'moderator', + }, { + email: 'moderator@example.org', + password: '1234', + }, + ) + + authenticatedUser = await moderator.toJson() + }) + + it('moderator is not allowed to delete other user accounts', async() => { + const { errors } = await mutate({ mutation: deleteUserMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) +}) + + +describe('User', () => { + describe('query by email address', () => { + beforeEach(async() => { + await Factory.build('user', { name: 'Johnny' }, { email: 'any-email-address@example.org' }) + }) + + const userQuery = gql ` query($email: String) { User(email: $email) { name } } ` - const variables = { email: 'any-email-address@example.org' } + const variables = { email: 'any-email-address@example.org' } - it('is forbidden', async () => { - await expect(query({ query: userQuery, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], - }) - }) - - describe('as admin', () => { - beforeEach(async () => { - const admin = await Factory.build( - 'user', - { - role: 'admin', - }, - { - email: 'admin@example.org', - password: '1234', - }, - ) - authenticatedUser = await admin.toJson() - }) - - it('is permitted', async () => { - await expect(query({ query: userQuery, variables })).resolves.toMatchObject({ - data: { User: [{ name: 'Johnny' }] }, - errors: undefined, + it('is forbidden', async() => { + await expect(query({ query: userQuery, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) }) - }) - it('non-existing email address, issue #2294', async () => { - // see: https://github.com/Human-Connection/Human-Connection/issues/2294 - await expect( - query({ - query: userQuery, - variables: { - email: 'this-email-does-not-exist@example.org', - }, - }), - ).resolves.toMatchObject({ - data: { User: [] }, - errors: undefined, + describe('as admin', () => { + beforeEach(async() => { + const admin = await Factory.build( + 'user', { + role: 'admin', + }, { + email: 'admin@example.org', + password: '1234', + }, + ) + authenticatedUser = await admin.toJson() + }) + + it('is permitted', async() => { + await expect(query({ query: userQuery, variables })).resolves.toMatchObject({ + data: { User: [{ name: 'Johnny' }] }, + errors: undefined, + }) + }) + + it('non-existing email address, issue #2294', async() => { + // see: https://github.com/Human-Connection/Human-Connection/issues/2294 + await expect( + query({ + query: userQuery, + variables: { + email: 'this-email-does-not-exist@example.org', + }, + }), + ).resolves.toMatchObject({ + data: { User: [] }, + errors: undefined, + }) + }) }) - }) }) - }) }) + + + + +describe('Delete a User as admin', () => { + + beforeEach(async() => { + variables = { id: ' u343', resource: [] } + + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', + }) + }) + + describe('authenticated as Admin', () => { + beforeEach(async() => { + admin = await Factory.build( + 'user', { + role: 'admin', + }, { + email: 'admin@example.org', + password: '1234', + }, + ) + authenticatedUser = await admin.toJson() + }) + + describe('deleting a user account', () => { + beforeEach(() => { + variables = {...variables, id: 'u343' } + }) + + describe('given posts and comments', () => { + beforeEach(async() => { + await Factory.build('category', { + id: 'cat9', + name: 'Democracy & Politics', + icon: 'university', + }) + await Factory.build( + 'post', { + id: 'p139', + content: 'Post by user u343', + }, { + author: user, + categoryIds, + }, + ) + await Factory.build( + 'comment', { + id: 'c155', + content: 'Comment by user u343', + }, { + author: user, + }, + ) + await Factory.build( + 'comment', { + id: 'c156', + content: "A comment by someone else on user u343's post", + }, { + postId: 'p139', + }, + ) + }) + + it("deletes account, but doesn't delete posts or comments by default", async() => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [{ + id: 'p139', + content: 'Post by user u343', + contentExcerpt: 'Post by user u343', + deleted: false, + comments: [{ + id: 'c156', + content: "A comment by someone else on user u343's post", + contentExcerpt: "A comment by someone else on user u343's post", + deleted: false, + }, ], + }, ], + comments: [{ + id: 'c155', + content: 'Comment by user u343', + contentExcerpt: 'Comment by user u343', + deleted: false, + }, ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + + describe('deletion of all post requested', () => { + + beforeEach(() => { + variables = {...variables, resource: ['Post'] } + }) + + + it('on request', async() => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [{ + id: 'p139', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + comments: [{ + id: 'c156', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, ], + }, ], + comments: [{ + id: 'c155', + content: 'Comment by user u343', + contentExcerpt: 'Comment by user u343', + deleted: false, + }, ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + + it('deletes user avatar and post hero images', async() => { + await expect(neode.all('Image')).resolves.toHaveLength(22) + await mutate({ mutation: deleteUserMutation, variables }) + await expect(neode.all('Image')).resolves.toHaveLength(20) + }) + + }) + + describe('deletion of all comments requested', () => { + beforeEach(() => { + variables = {...variables, resource: ['Comment'] } + }) + + + it('marks comments as deleted', async() => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [{ + id: 'p139', + content: 'Post by user u343', + contentExcerpt: 'Post by user u343', + deleted: false, + comments: [{ + id: 'c156', + content: "A comment by someone else on user u343's post", + contentExcerpt: "A comment by someone else on user u343's post", + deleted: false, + }, ], + }, ], + comments: [{ + id: 'c155', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + + + + }) + + describe('deletion of all posts and comments requested', () => { + beforeEach(() => { + variables = {...variables, + resource: ['Comment', 'Post'] + } + }) + + it('marks posts and comments as deleted', async() => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [{ + id: 'p139', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + comments: [{ + id: 'c156', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, ], + }, ], + comments: [{ + id: 'c155', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) + }) + + describe('connected `EmailAddress` nodes', () => { + it('will be removed completely', async() => { + await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) + await mutate({ mutation: deleteUserMutation, variables }) + + await expect(neode.all('EmailAddress')).resolves.toHaveLength(1) + }) + }) + + describe('connected `SocialMedia` nodes', () => { + beforeEach(async() => { + const socialMedia = await Factory.build('socialMedia') + await socialMedia.relateTo(user, 'ownedBy') + }) + + it('will be removed completely', async() => { + await expect(neode.all('SocialMedia')).resolves.toHaveLength(1) + await mutate({ mutation: deleteUserMutation, variables }) + await expect(neode.all('SocialMedia')).resolves.toHaveLength(0) + }) + }) + }) + }) + + + +}) + + + + + describe('UpdateUser', () => { - let variables + let variables - beforeEach(async () => { - variables = { - id: 'u47', - name: 'John Doughnut', - } - }) + beforeEach(async() => { + variables = { + id: 'u47', + name: 'John Doughnut', + } + }) - const updateUserMutation = gql` + const updateUserMutation = gql ` mutation( $id: ID! $name: String @@ -126,795 +499,116 @@ describe('UpdateUser', () => { } ` - beforeEach(async () => { - user = await Factory.build( - 'user', - { - id: 'u47', - name: 'John Doe', - termsAndConditionsAgreedVersion: null, - termsAndConditionsAgreedAt: null, - allowEmbedIframes: false, - }, - { - email: 'user@example.org', - }, - ) - }) - - describe('as another user', () => { - beforeEach(async () => { - const someoneElse = await Factory.build( - 'user', - { - name: 'James Doe', - }, - { - email: 'someone-else@example.org', - }, - ) - - authenticatedUser = await someoneElse.toJson() - }) - - it('is not allowed to change other user accounts', async () => { - const { errors } = await mutate({ mutation: updateUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('as the same user', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('updates the name', async () => { - const expected = { - data: { - UpdateUser: { - id: 'u47', - name: 'John Doughnut', - }, - }, - errors: undefined, - } - await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject( - expected, - ) - }) - - describe('given a new agreed version of terms and conditions', () => { - beforeEach(async () => { - variables = { ...variables, termsAndConditionsAgreedVersion: '0.0.2' } - }) - it('update termsAndConditionsAgreedVersion', async () => { - const expected = { - data: { - UpdateUser: expect.objectContaining({ - termsAndConditionsAgreedVersion: '0.0.2', - termsAndConditionsAgreedAt: expect.any(String), - }), - }, - errors: undefined, - } - - await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject( - expected, + beforeEach(async() => { + user = await Factory.build( + 'user', { + id: 'u47', + name: 'John Doe', + termsAndConditionsAgreedVersion: null, + termsAndConditionsAgreedAt: null, + allowEmbedIframes: false, + }, { + email: 'user@example.org', + }, ) - }) }) - describe('given any attribute other than termsAndConditionsAgreedVersion', () => { - beforeEach(async () => { - variables = { ...variables, name: 'any name' } - }) - it('update termsAndConditionsAgreedVersion', async () => { - const expected = { - data: { - UpdateUser: expect.objectContaining({ - termsAndConditionsAgreedVersion: null, - termsAndConditionsAgreedAt: null, - }), - }, - errors: undefined, - } + describe('as another user', () => { + beforeEach(async() => { + const someoneElse = await Factory.build( + 'user', { + name: 'James Doe', + }, { + email: 'someone-else@example.org', + }, + ) - await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject( - expected, - ) - }) - }) - - it('rejects if version of terms and conditions has wrong format', async () => { - variables = { - ...variables, - termsAndConditionsAgreedVersion: 'invalid version format', - } - const { errors } = await mutate({ mutation: updateUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Invalid version format!') - }) - - it('supports updating location', async () => { - variables = { ...variables, locationName: 'Hamburg, New Jersey, United States of America' } - await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({ - data: { UpdateUser: { locationName: 'Hamburg, New Jersey, United States of America' } }, - errors: undefined, - }) - }) - }) -}) - -describe('DeleteUser', () => { - const deleteUserMutation = gql` - mutation($id: ID!, $resource: [Deletable]) { - DeleteUser(id: $id, resource: $resource) { - id - name - about - deleted - contributions { - id - content - contentExcerpt - deleted - comments { - id - content - contentExcerpt - deleted - } - } - comments { - id - content - contentExcerpt - deleted - } - } - } - ` - describe('as another user', () => { - beforeEach(async () => { - variables = { id: ' u343', resource: [] } - - user = await Factory.build('user', { - name: 'My name should be deleted', - about: 'along with my about', - id: 'u343', - }) - }) - - beforeEach(async () => { - const anotherUser = await Factory.build( - 'user', - { - role: 'user', - }, - { - email: 'user@example.org', - password: '1234', - }, - ) - - authenticatedUser = await anotherUser.toJson() - }) - - it("an ordinary user has no authorization to delete another user's account", async () => { - const { errors } = await mutate({ mutation: deleteUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('as moderator', () => { - beforeEach(async () => { - variables = { id: ' u343', resource: [] } - - user = await Factory.build('user', { - name: 'My name should be deleted', - about: 'along with my about', - id: 'u343', - }) - }) - - beforeEach(async () => { - const moderator = await Factory.build( - 'user', - { - role: 'moderator', - }, - { - email: 'moderator@example.org', - password: '1234', - }, - ) - - authenticatedUser = await moderator.toJson() - }) - - it('moderator is not allowed to delete other user accounts', async () => { - const { errors } = await mutate({ mutation: deleteUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('as admin', () => { - beforeEach(async () => { - variables = { id: ' u343', resource: [] } - - user = await Factory.build('user', { - name: 'My name should be deleted', - about: 'along with my about', - id: 'u343', - }) - }) - - describe('authenticated as Admin', () => { - beforeEach(async () => { - const admin = await Factory.build( - 'user', - { - role: 'admin', - }, - { - email: 'admin@example.org', - password: '1234', - }, - ) - authenticatedUser = await admin.toJson() - }) - - describe('deleting a user account', () => { - beforeEach(() => { - variables = { ...variables, id: 'u343' } + authenticatedUser = await someoneElse.toJson() }) - describe('given posts and comments', () => { - beforeEach(async () => { - await Factory.build('category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', - }) - await Factory.build( - 'post', - { - id: 'p139', - content: 'Post by user u343', - }, - { - author: user, - categoryIds, - }, - ) - await Factory.build( - 'comment', - { - id: 'c155', - content: 'Comment by user u343', - }, - { - author: user, - }, - ) - await Factory.build( - 'comment', - { - id: 'c156', - content: "A comment by someone else on user u343's post", - }, - { - postId: 'p139', - }, - ) - }) + it('is not allowed to change other user accounts', async() => { + const { errors } = await mutate({ mutation: updateUserMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) - it("deletes account, but doesn't delete posts or comments by default", async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'Post by user u343', - contentExcerpt: 'Post by user u343', - deleted: false, - comments: [ - { - id: 'c156', - content: "A comment by someone else on user u343's post", - contentExcerpt: "A comment by someone else on user u343's post", - deleted: false, - }, - ], + describe('as the same user', () => { + beforeEach(async() => { + authenticatedUser = await user.toJson() + }) + + it('updates the name', async() => { + const expected = { + data: { + UpdateUser: { + id: 'u47', + name: 'John Doughnut', }, - ], - comments: [ - { - id: 'c155', - content: 'Comment by user u343', - contentExcerpt: 'Comment by user u343', - deleted: false, - }, - ], }, - }, - errors: undefined, + errors: undefined, } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) + await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject( + expected, + ) + }) - describe('deletion of all post requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Post'] } + describe('given a new agreed version of terms and conditions', () => { + beforeEach(async() => { + variables = {...variables, termsAndConditionsAgreedVersion: '0.0.2' } }) - - describe("marks user's posts as deleted", () => { - it('on request', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - comments: [ - { - id: 'c156', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'Comment by user u343', - contentExcerpt: 'Comment by user u343', - deleted: false, - }, - ], + it('update termsAndConditionsAgreedVersion', async() => { + const expected = { + data: { + UpdateUser: expect.objectContaining({ + termsAndConditionsAgreedVersion: '0.0.2', + termsAndConditionsAgreedAt: expect.any(String), + }), }, - }, - errors: undefined, + errors: undefined, } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - it('deletes user avatar and post hero images', async () => { - await expect(neode.all('Image')).resolves.toHaveLength(22) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('Image')).resolves.toHaveLength(20) - }) + await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject( + expected, + ) }) - }) - - describe('deletion of all comments requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Comment'] } - }) - - it('marks comments as deleted', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'Post by user u343', - contentExcerpt: 'Post by user u343', - deleted: false, - comments: [ - { - id: 'c156', - content: "A comment by someone else on user u343's post", - contentExcerpt: "A comment by someone else on user u343's post", - deleted: false, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - }, - errors: undefined, - } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - }) - - describe('deletion of all posts and comments requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Post', 'Comment'] } - }) - - it('marks posts and comments as deleted', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - comments: [ - { - id: 'c156', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - }, - errors: undefined, - } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - }) }) - describe('connected `EmailAddress` nodes', () => { - it('will be removed completely', async () => { - await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('EmailAddress')).resolves.toHaveLength(1) - }) - }) - - describe('connected `SocialMedia` nodes', () => { - beforeEach(async () => { - const socialMedia = await Factory.build('socialMedia') - await socialMedia.relateTo(user, 'ownedBy') - }) - - it('will be removed completely', async () => { - await expect(neode.all('SocialMedia')).resolves.toHaveLength(1) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('SocialMedia')).resolves.toHaveLength(0) - }) - }) - }) - }) - }) - - describe('user deletes his own account', () => { - beforeEach(async () => { - variables = { id: 'u343', resource: [] } - - user = await Factory.build('user', { - name: 'My name should be deleted', - about: 'along with my about', - id: 'u343', - }) - await Factory.build( - 'user', - { - id: 'not-my-account', - }, - { - email: 'friends-account@example.org', - }, - ) - }) - - describe('authenticated', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - describe("attempting to delete another user's account", () => { - beforeEach(() => { - variables = { ...variables, id: 'not-my-account' } - }) - - it('throws an authorization error', async () => { - const { errors } = await mutate({ mutation: deleteUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('attempting to delete my own account', () => { - beforeEach(() => { - variables = { ...variables, id: 'u343' } - }) - - describe('given posts and comments', () => { - beforeEach(async () => { - await Factory.build('category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', + describe('given any attribute other than termsAndConditionsAgreedVersion', () => { + beforeEach(async() => { + variables = {...variables, name: 'any name' } }) - await Factory.build( - 'post', - { - id: 'p139', - content: 'Post by user u343', - }, - { - author: user, - categoryIds, - }, - ) - await Factory.build( - 'comment', - { - id: 'c155', - content: 'Comment by user u343', - }, - { - author: user, - }, - ) - await Factory.build( - 'comment', - { - id: 'c156', - content: "A comment by someone else on user u343's post", - }, - { - postId: 'p139', - }, - ) - }) - - it("deletes my account, but doesn't delete posts or comments by default", async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'Post by user u343', - contentExcerpt: 'Post by user u343', - deleted: false, - comments: [ - { - id: 'c156', - content: "A comment by someone else on user u343's post", - contentExcerpt: "A comment by someone else on user u343's post", - deleted: false, - }, - ], + it('update termsAndConditionsAgreedVersion', async() => { + const expected = { + data: { + UpdateUser: expect.objectContaining({ + termsAndConditionsAgreedVersion: null, + termsAndConditionsAgreedAt: null, + }), }, - ], - comments: [ - { - id: 'c155', - content: 'Comment by user u343', - contentExcerpt: 'Comment by user u343', - deleted: false, - }, - ], - }, - }, - errors: undefined, + errors: undefined, + } + + await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject( + expected, + ) + }) + }) + + it('rejects if version of terms and conditions has wrong format', async() => { + variables = { + ...variables, + termsAndConditionsAgreedVersion: 'invalid version format', } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - - describe('deletion of all post requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Post'] } - }) - - describe("marks user's posts as deleted", () => { - it('posts on request', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - comments: [ - { - id: 'c156', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'Comment by user u343', - contentExcerpt: 'Comment by user u343', - deleted: false, - }, - ], - }, - }, - errors: undefined, - } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - - it('deletes user avatar and post hero images', async () => { - await expect(neode.all('Image')).resolves.toHaveLength(22) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('Image')).resolves.toHaveLength(20) - }) - }) - }) - - describe('deletion of all comments requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Comment'] } - }) - - it('marks comments as deleted', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'Post by user u343', - contentExcerpt: 'Post by user u343', - deleted: false, - comments: [ - { - id: 'c156', - content: "A comment by someone else on user u343's post", - contentExcerpt: "A comment by someone else on user u343's post", - deleted: false, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - }, - errors: undefined, - } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - }) - describe('deletion of all post and comments requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Post', 'Comment'] } - }) - - it('marks posts and comments as deleted', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - comments: [ - { - id: 'c156', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - }, - errors: undefined, - } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) - }) - }) + const { errors } = await mutate({ mutation: updateUserMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Invalid version format!') }) - }) - }) - describe('connected `EmailAddress` nodes', () => { - it('will be removed completely', async () => { - await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('EmailAddress')).resolves.toHaveLength(1) - }) + it('supports updating location', async() => { + variables = {...variables, locationName: 'Hamburg, New Jersey, United States of America' } + await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({ + data: { UpdateUser: { locationName: 'Hamburg, New Jersey, United States of America' } }, + errors: undefined, + }) + }) }) - - describe('connected `SocialMedia` nodes', () => { - beforeEach(async () => { - const socialMedia = await Factory.build('socialMedia') - await socialMedia.relateTo(user, 'ownedBy') - }) - - it('will be removed completely', async () => { - await expect(neode.all('SocialMedia')).resolves.toHaveLength(1) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('SocialMedia')).resolves.toHaveLength(0) - }) - }) - }) -}) +}) \ No newline at end of file