3159 lines
106 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories'
import {
createGroupMutation,
updateGroupMutation,
joinGroupMutation,
leaveGroupMutation,
changeGroupMemberRoleMutation,
removeUserFromGroupMutation,
groupMembersQuery,
groupQuery,
} from '../../graphql/groups'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'
import CONFIG from '../../config'
const driver = getDriver()
const neode = getNeode()
let authenticatedUser
let user
let noMemberUser
let pendingMemberUser
let usualMemberUser
let adminMemberUser
let ownerMemberUser
let secondOwnerMemberUser
const categoryIds = ['cat9', 'cat4', 'cat15']
const descriptionAdditional100 =
' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789'
let variables = {}
const { server } = createServer({
context: () => {
return {
driver,
neode,
user: authenticatedUser,
}
},
})
const { mutate, query } = createTestClient(server)
const seedBasicsAndClearAuthentication = 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: 'cat4',
name: 'Environment & Nature',
slug: 'environment-nature',
icon: 'tree',
}),
neode.create('Category', {
id: 'cat9',
name: 'Democracy & Politics',
slug: 'democracy-politics',
icon: 'university',
}),
neode.create('Category', {
id: 'cat15',
name: 'Consumption & Sustainability',
slug: 'consumption-sustainability',
icon: 'shopping-cart',
}),
neode.create('Category', {
id: 'cat27',
name: 'Animal Protection',
slug: 'animal-protection',
icon: 'paw',
}),
])
authenticatedUser = null
}
const seedComplexScenarioAndClearAuthentication = async () => {
await seedBasicsAndClearAuthentication()
// create users
noMemberUser = await Factory.build(
'user',
{
id: 'none-member-user',
name: 'None Member TestUser',
},
{
email: 'none-member-user@example.org',
password: '1234',
},
)
pendingMemberUser = await Factory.build(
'user',
{
id: 'pending-member-user',
name: 'Pending Member TestUser',
},
{
email: 'pending-member-user@example.org',
password: '1234',
},
)
usualMemberUser = await Factory.build(
'user',
{
id: 'usual-member-user',
name: 'Usual Member TestUser',
},
{
email: 'usual-member-user@example.org',
password: '1234',
},
)
adminMemberUser = await Factory.build(
'user',
{
id: 'admin-member-user',
name: 'Admin Member TestUser',
},
{
email: 'admin-member-user@example.org',
password: '1234',
},
)
ownerMemberUser = await Factory.build(
'user',
{
id: 'owner-member-user',
name: 'Owner Member TestUser',
},
{
email: 'owner-member-user@example.org',
password: '1234',
},
)
secondOwnerMemberUser = await Factory.build(
'user',
{
id: 'second-owner-member-user',
name: 'Second Owner Member TestUser',
},
{
email: 'second-owner-member-user@example.org',
password: '1234',
},
)
// create groups
// public-group
authenticatedUser = await usualMemberUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'public-group',
name: 'The Best Group',
about: 'We will change the world!',
description: 'Some description' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
categoryIds,
},
})
await mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-closed-group',
},
})
await mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-hidden-group',
},
})
// closed-group
authenticatedUser = await ownerMemberUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'closed-group',
name: 'Uninteresting Group',
about: 'We will change nothing!',
description: 'We love it like it is!?' + descriptionAdditional100,
groupType: 'closed',
actionRadius: 'national',
categoryIds,
},
})
// hidden-group
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
about: 'We will change all.',
description: 'We research …' + descriptionAdditional100,
groupType: 'hidden',
actionRadius: 'global',
categoryIds,
},
})
// 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'usual-member-user',
roleInGroup: 'usual',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'admin-member-user',
roleInGroup: 'admin',
},
})
authenticatedUser = null
}
beforeAll(async () => {
await cleanDatabase()
})
afterAll(async () => {
await cleanDatabase()
driver.close()
})
describe('in mode', () => {
describe('clean db after each single test', () => {
beforeEach(async () => {
await seedBasicsAndClearAuthentication()
})
// 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('CreateGroup', () => {
beforeEach(() => {
variables = {
...variables,
id: 'g589',
name: 'The Best Group',
slug: 'the-group',
about: 'We will change the world!',
description: 'Some description' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
categoryIds,
locationName: 'Hamburg, Germany',
}
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({ mutation: createGroupMutation(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
it('creates a group', async () => {
await expect(
mutate({ mutation: createGroupMutation(), variables }),
).resolves.toMatchObject({
data: {
CreateGroup: {
name: 'The Best Group',
slug: 'the-group',
about: 'We will change the world!',
description: 'Some description' + descriptionAdditional100,
descriptionExcerpt: 'Some description' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
locationName: 'Hamburg, Germany',
location: expect.objectContaining({
name: 'Hamburg',
nameDE: 'Hamburg',
nameEN: 'Hamburg',
}),
},
},
errors: undefined,
})
})
it('assigns the authenticated user as owner', async () => {
await expect(
mutate({ mutation: createGroupMutation(), variables }),
).resolves.toMatchObject({
data: {
CreateGroup: {
name: 'The Best Group',
myRole: 'owner',
},
},
errors: undefined,
})
})
it('has "disabled" and "deleted" default to "false"', async () => {
await expect(
mutate({ mutation: createGroupMutation(), variables }),
).resolves.toMatchObject({
data: { CreateGroup: { disabled: false, deleted: false } },
})
})
describe('description', () => {
describe('length without HTML', () => {
describe('less then 100 chars', () => {
it('throws error: "Description too short!"', async () => {
const { errors } = await mutate({
mutation: createGroupMutation(),
variables: {
...variables,
description:
'0123456789' +
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0123456789</a>',
},
})
expect(errors[0]).toHaveProperty('message', 'Description too short!')
})
})
})
})
describe('categories', () => {
beforeEach(() => {
CONFIG.CATEGORIES_ACTIVE = true
})
describe('with matching amount of categories', () => {
it('has new categories', async () => {
await expect(
mutate({
mutation: createGroupMutation(),
variables: {
...variables,
categoryIds: ['cat4', 'cat27'],
},
}),
).resolves.toMatchObject({
data: {
CreateGroup: {
categories: expect.arrayContaining([
expect.objectContaining({ id: 'cat4' }),
expect.objectContaining({ id: 'cat27' }),
]),
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('not even one', () => {
describe('by "categoryIds: null"', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
mutation: createGroupMutation(),
variables: { ...variables, categoryIds: null },
})
expect(errors[0]).toHaveProperty('message', 'Too view categories!')
})
})
describe('by "categoryIds: []"', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
mutation: createGroupMutation(),
variables: { ...variables, categoryIds: [] },
})
expect(errors[0]).toHaveProperty('message', 'Too view categories!')
})
})
})
describe('four', () => {
it('throws error: "Too many categories!"', async () => {
const { errors } = await mutate({
mutation: createGroupMutation(),
variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] },
})
expect(errors[0]).toHaveProperty('message', 'Too many categories!')
})
})
})
})
})
})
describe('building up clean db after each resolver', () => {
describe('Group', () => {
beforeAll(async () => {
await seedBasicsAndClearAuthentication()
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await query({ query: groupQuery(), variables: {} })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
let otherUser
let ownerOfHiddenGroupUser
beforeAll(async () => {
otherUser = await Factory.build(
'user',
{
id: 'other-user',
name: 'Other TestUser',
},
{
email: 'other-user@example.org',
password: '1234',
},
)
ownerOfHiddenGroupUser = await Factory.build(
'user',
{
id: 'owner-of-hidden-group',
name: 'Owner Of Hidden Group',
},
{
email: 'owner-of-hidden-group@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!?' + descriptionAdditional100,
groupType: 'closed',
actionRadius: 'global',
categoryIds,
},
})
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
about: 'We will change all.',
description: 'We research …' + descriptionAdditional100,
groupType: 'hidden',
actionRadius: 'global',
categoryIds,
},
})
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'second-hidden-group',
name: 'Second Investigative Journalism Group',
about: 'We will change all.',
description: 'We research …' + descriptionAdditional100,
groupType: 'hidden',
actionRadius: 'global',
categoryIds,
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'second-hidden-group',
userId: 'current-user',
roleInGroup: 'pending',
},
})
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'third-hidden-group',
name: 'Third Investigative Journalism Group',
about: 'We will change all.',
description: 'We research …' + descriptionAdditional100,
groupType: 'hidden',
actionRadius: 'global',
categoryIds,
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'third-hidden-group',
userId: 'current-user',
roleInGroup: 'usual',
},
})
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' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
categoryIds,
locationName: 'Hamburg, Germany',
},
})
})
describe('query groups', () => {
describe('in general finds only listed groups no hidden groups where user is none or pending member', () => {
describe('without any filters', () => {
it('finds all listed groups including the set descriptionExcerpts and locations', async () => {
const result = await query({ query: groupQuery(), variables: {} })
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
descriptionExcerpt: 'Some description' + descriptionAdditional100,
locationName: 'Hamburg, Germany',
location: expect.objectContaining({
name: 'Hamburg',
nameDE: 'Hamburg',
nameEN: 'Hamburg',
}),
myRole: 'owner',
}),
expect.objectContaining({
id: 'others-group',
slug: 'uninteresting-group',
descriptionExcerpt: 'We love it like it is!?' + descriptionAdditional100,
locationName: null,
location: null,
myRole: null,
}),
expect.objectContaining({
id: 'third-hidden-group',
slug: 'third-investigative-journalism-group',
descriptionExcerpt: 'We research …' + descriptionAdditional100,
myRole: 'usual',
locationName: null,
location: null,
}),
]),
},
errors: undefined,
})
expect(result.data.Group.length).toBe(3)
})
describe('categories', () => {
beforeEach(() => {
CONFIG.CATEGORIES_ACTIVE = true
})
it('has set categories', async () => {
await expect(
query({ query: groupQuery(), variables: {} }),
).resolves.toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
categories: expect.arrayContaining([
expect.objectContaining({ id: 'cat4' }),
expect.objectContaining({ id: 'cat9' }),
expect.objectContaining({ id: 'cat15' }),
]),
myRole: 'owner',
}),
expect.objectContaining({
id: 'others-group',
slug: 'uninteresting-group',
categories: expect.arrayContaining([
expect.objectContaining({ id: 'cat4' }),
expect.objectContaining({ id: 'cat9' }),
expect.objectContaining({ id: 'cat15' }),
]),
myRole: null,
}),
]),
},
errors: undefined,
})
})
})
})
describe('with given id', () => {
describe("id = 'my-group'", () => {
it('finds only the listed group with this id', async () => {
const result = await query({ query: groupQuery(), variables: { id: 'my-group' } })
expect(result).toMatchObject({
data: {
Group: [
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
myRole: 'owner',
}),
],
},
errors: undefined,
})
expect(result.data.Group.length).toBe(1)
})
})
describe("id = 'third-hidden-group'", () => {
it("finds only the hidden group where I'm 'usual' member", async () => {
const result = await query({
query: groupQuery(),
variables: { id: 'third-hidden-group' },
})
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'third-hidden-group',
slug: 'third-investigative-journalism-group',
myRole: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.Group.length).toBe(1)
})
})
describe("id = 'second-hidden-group'", () => {
it("finds no hidden group where I'm 'pending' member", async () => {
const result = await query({
query: groupQuery(),
variables: { id: 'second-hidden-group' },
})
expect(result.data.Group.length).toBe(0)
})
})
describe("id = 'hidden-group'", () => {
it("finds no hidden group where I'm not(!) a member at all", async () => {
const result = await query({
query: groupQuery(),
variables: { id: 'hidden-group' },
})
expect(result.data.Group.length).toBe(0)
})
})
})
describe('with given slug', () => {
describe("slug = 'the-best-group'", () => {
it('finds only the listed group with this slug', async () => {
const result = await query({
query: groupQuery(),
variables: { slug: 'the-best-group' },
})
expect(result).toMatchObject({
data: {
Group: [
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
myRole: 'owner',
}),
],
},
errors: undefined,
})
expect(result.data.Group.length).toBe(1)
})
})
describe("slug = 'third-investigative-journalism-group'", () => {
it("finds only the hidden group where I'm 'usual' member", async () => {
const result = await query({
query: groupQuery(),
variables: { slug: 'third-investigative-journalism-group' },
})
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'third-hidden-group',
slug: 'third-investigative-journalism-group',
myRole: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.Group.length).toBe(1)
})
})
describe("slug = 'second-investigative-journalism-group'", () => {
it("finds no hidden group where I'm 'pending' member", async () => {
const result = await query({
query: groupQuery(),
variables: { slug: 'second-investigative-journalism-group' },
})
expect(result.data.Group.length).toBe(0)
})
})
describe("slug = 'investigative-journalism-group'", () => {
it("finds no hidden group where I'm not(!) a member at all", async () => {
const result = await query({
query: groupQuery(),
variables: { slug: 'investigative-journalism-group' },
})
expect(result.data.Group.length).toBe(0)
})
})
})
describe('isMember = true', () => {
it('finds only listed groups where user is member', async () => {
const result = await query({ query: groupQuery(), variables: { isMember: true } })
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
myRole: 'owner',
}),
expect.objectContaining({
id: 'third-hidden-group',
slug: 'third-investigative-journalism-group',
myRole: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.Group.length).toBe(2)
})
})
describe('isMember = false', () => {
it('finds only listed groups where user is not(!) member', async () => {
const result = await query({ query: groupQuery(), variables: { isMember: false } })
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'others-group',
slug: 'uninteresting-group',
myRole: null,
}),
]),
},
errors: undefined,
})
expect(result.data.Group.length).toBe(1)
})
})
})
})
})
})
describe('JoinGroup', () => {
beforeAll(async () => {
await seedBasicsAndClearAuthentication()
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'not-existing-group',
userId: 'current-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
let ownerOfClosedGroupUser
let ownerOfHiddenGroupUser
beforeAll(async () => {
// create users
ownerOfClosedGroupUser = await Factory.build(
'user',
{
id: 'owner-of-closed-group',
name: 'Owner Of Closed Group',
},
{
email: 'owner-of-closed-group@example.org',
password: '1234',
},
)
ownerOfHiddenGroupUser = await Factory.build(
'user',
{
id: 'owner-of-hidden-group',
name: 'Owner Of Hidden Group',
},
{
email: 'owner-of-hidden-group@example.org',
password: '1234',
},
)
// create groups
// public-group
authenticatedUser = await ownerOfClosedGroupUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'closed-group',
name: 'Uninteresting Group',
about: 'We will change nothing!',
description: 'We love it like it is!?' + descriptionAdditional100,
groupType: 'closed',
actionRadius: 'national',
categoryIds,
},
})
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
about: 'We will change all.',
description: 'We research …' + descriptionAdditional100,
groupType: 'hidden',
actionRadius: 'global',
categoryIds,
},
})
authenticatedUser = await user.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'public-group',
name: 'The Best Group',
about: 'We will change the world!',
description: 'Some description' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
categoryIds,
},
})
})
describe('public group', () => {
describe('joined by "owner-of-closed-group"', () => {
it('has "usual" as membership role', async () => {
await expect(
mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-closed-group',
},
}),
).resolves.toMatchObject({
data: {
JoinGroup: {
id: 'owner-of-closed-group',
myRoleInGroup: 'usual',
},
},
errors: undefined,
})
})
})
describe('joined by its owner', () => {
describe('does not create additional "MEMBER_OF" relation and therefore', () => {
it('has still "owner" as membership role', async () => {
await expect(
mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'current-user',
},
}),
).resolves.toMatchObject({
data: {
JoinGroup: {
id: 'current-user',
myRoleInGroup: 'owner',
},
},
errors: undefined,
})
})
})
})
})
describe('closed group', () => {
describe('joined by "current-user"', () => {
it('has "pending" as membership role', async () => {
await expect(
mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'closed-group',
userId: 'current-user',
},
}),
).resolves.toMatchObject({
data: {
JoinGroup: {
id: 'current-user',
myRoleInGroup: 'pending',
},
},
errors: undefined,
})
})
})
describe('joined by its owner', () => {
describe('does not create additional "MEMBER_OF" relation and therefore', () => {
it('has still "owner" as membership role', async () => {
await expect(
mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'closed-group',
userId: 'owner-of-closed-group',
},
}),
).resolves.toMatchObject({
data: {
JoinGroup: {
id: 'owner-of-closed-group',
myRoleInGroup: 'owner',
},
},
errors: undefined,
})
})
})
})
})
describe('hidden group', () => {
describe('joined by "owner-of-closed-group"', () => {
it('throws authorization error', async () => {
const { errors } = await query({
query: joinGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-of-closed-group',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('joined by its owner', () => {
describe('does not create additional "MEMBER_OF" relation and therefore', () => {
it('has still "owner" as membership role', async () => {
await expect(
mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-of-hidden-group',
},
}),
).resolves.toMatchObject({
data: {
JoinGroup: {
id: 'owner-of-hidden-group',
myRoleInGroup: 'owner',
},
},
errors: undefined,
})
})
})
})
})
})
})
describe('GroupMembers', () => {
beforeAll(async () => {
await seedBasicsAndClearAuthentication()
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
variables = {
id: 'not-existing-group',
}
const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
let otherUser
let pendingUser
let ownerOfClosedGroupUser
let ownerOfHiddenGroupUser
beforeAll(async () => {
// create users
otherUser = await Factory.build(
'user',
{
id: 'other-user',
name: 'Other TestUser',
},
{
email: 'other-user@example.org',
password: '1234',
},
)
pendingUser = await Factory.build(
'user',
{
id: 'pending-user',
name: 'Pending TestUser',
},
{
email: 'pending@example.org',
password: '1234',
},
)
ownerOfClosedGroupUser = await Factory.build(
'user',
{
id: 'owner-of-closed-group',
name: 'Owner Of Closed Group',
},
{
email: 'owner-of-closed-group@example.org',
password: '1234',
},
)
ownerOfHiddenGroupUser = await Factory.build(
'user',
{
id: 'owner-of-hidden-group',
name: 'Owner Of Hidden Group',
},
{
email: 'owner-of-hidden-group@example.org',
password: '1234',
},
)
// create groups
// public-group
authenticatedUser = await user.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'public-group',
name: 'The Best Group',
about: 'We will change the world!',
description: 'Some description' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
categoryIds,
},
})
await mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-closed-group',
},
})
await mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-hidden-group',
},
})
// closed-group
authenticatedUser = await ownerOfClosedGroupUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'closed-group',
name: 'Uninteresting Group',
about: 'We will change nothing!',
description: 'We love it like it is!?' + descriptionAdditional100,
groupType: 'closed',
actionRadius: 'national',
categoryIds,
},
})
await mutate({
mutation: joinGroupMutation(),
variables: {
groupId: 'closed-group',
userId: 'current-user',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'owner-of-hidden-group',
roleInGroup: 'usual',
},
})
// hidden-group
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
about: 'We will change all.',
description: 'We research …' + descriptionAdditional100,
groupType: 'hidden',
actionRadius: 'global',
categoryIds,
},
})
// 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'pending-user',
roleInGroup: 'pending',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'current-user',
roleInGroup: 'usual',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-of-closed-group',
roleInGroup: 'admin',
},
})
authenticatedUser = null
})
describe('public group', () => {
beforeEach(async () => {
variables = {
id: 'public-group',
}
})
describe('query group members', () => {
describe('by owner "current-user"', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'owner',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'usual',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(3)
})
})
describe('by usual member "owner-of-closed-group"', () => {
beforeEach(async () => {
authenticatedUser = await ownerOfClosedGroupUser.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'owner',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'usual',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(3)
})
})
describe('by none member "other-user"', () => {
beforeEach(async () => {
authenticatedUser = await otherUser.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'owner',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'usual',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(3)
})
})
})
})
describe('closed group', () => {
beforeEach(async () => {
variables = {
id: 'closed-group',
}
})
describe('query group members', () => {
describe('by owner "owner-of-closed-group"', () => {
beforeEach(async () => {
authenticatedUser = await ownerOfClosedGroupUser.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'pending',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'owner',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(3)
})
})
describe('by usual member "owner-of-hidden-group"', () => {
beforeEach(async () => {
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'pending',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'owner',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'usual',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(3)
})
})
describe('by pending member "current-user"', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
it('throws authorization error', async () => {
const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('by none member "other-user"', () => {
beforeEach(async () => {
authenticatedUser = await otherUser.toJson()
})
it('throws authorization error', async () => {
const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
describe('hidden group', () => {
beforeEach(async () => {
variables = {
id: 'hidden-group',
}
})
describe('query group members', () => {
describe('by owner "owner-of-hidden-group"', () => {
beforeEach(async () => {
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'pending-user',
myRoleInGroup: 'pending',
}),
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'usual',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'admin',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'owner',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(4)
})
})
describe('by usual member "current-user"', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'pending-user',
myRoleInGroup: 'pending',
}),
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'usual',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'admin',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'owner',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(4)
})
})
describe('by admin member "owner-of-closed-group"', () => {
beforeEach(async () => {
authenticatedUser = await ownerOfClosedGroupUser.toJson()
})
it('finds all members', async () => {
const result = await query({
query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
data: {
GroupMembers: expect.arrayContaining([
expect.objectContaining({
id: 'pending-user',
myRoleInGroup: 'pending',
}),
expect.objectContaining({
id: 'current-user',
myRoleInGroup: 'usual',
}),
expect.objectContaining({
id: 'owner-of-closed-group',
myRoleInGroup: 'admin',
}),
expect.objectContaining({
id: 'owner-of-hidden-group',
myRoleInGroup: 'owner',
}),
]),
},
errors: undefined,
})
expect(result.data.GroupMembers.length).toBe(4)
})
})
describe('by pending member "pending-user"', () => {
beforeEach(async () => {
authenticatedUser = await pendingUser.toJson()
})
it('throws authorization error', async () => {
const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('by none member "other-user"', () => {
beforeEach(async () => {
authenticatedUser = await otherUser.toJson()
})
it('throws authorization error', async () => {
const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
})
})
describe('ChangeGroupMemberRole', () => {
beforeAll(async () => {
await seedComplexScenarioAndClearAuthentication()
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'not-existing-group',
userId: 'current-user',
roleInGroup: 'pending',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
describe('in all group types here "closed-group" for example', () => {
beforeEach(async () => {
variables = {
groupId: 'closed-group',
}
})
describe('join the members and give them their prospective roles', () => {
describe('by owner "owner-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await ownerMemberUser.toJson()
})
describe('for "usual-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'usual-member-user',
}
})
describe('as usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('has role usual', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'usual-member-user',
myRoleInGroup: 'usual',
},
},
errors: undefined,
})
})
// the GQL mutation needs this fields in the result for testing
it.todo('has "updatedAt" newer as "createdAt"')
})
})
describe('for "admin-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'admin-member-user',
}
})
describe('as admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('has role admin', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'admin-member-user',
myRoleInGroup: 'admin',
},
},
errors: undefined,
})
})
})
})
describe('for "second-owner-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'second-owner-member-user',
}
})
describe('as owner', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'owner',
}
})
it('has role owner', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'second-owner-member-user',
myRoleInGroup: 'owner',
},
},
errors: undefined,
})
})
})
})
})
})
describe('switch role', () => {
describe('of owner "owner-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'owner-member-user',
}
})
describe('by owner themself "owner-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await ownerMemberUser.toJson()
})
describe('to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
// shall this be possible in the future?
// or shall only an owner who gave the second owner the owner role downgrade themself for savety?
// otherwise the first owner who downgrades the other one has the victory over the group!
describe('by second owner "second-owner-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await secondOwnerMemberUser.toJson()
})
describe('to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('to same role owner', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'owner',
}
})
it('has role owner still', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'owner-member-user',
myRoleInGroup: 'owner',
},
},
errors: undefined,
})
})
})
})
describe('by admin "admin-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await adminMemberUser.toJson()
})
describe('to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by usual member "usual-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await usualMemberUser.toJson()
})
describe('to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by still pending member "pending-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await pendingMemberUser.toJson()
})
describe('to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
describe('of admin "admin-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'admin-member-user',
}
})
describe('by owner "owner-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await ownerMemberUser.toJson()
})
describe('to owner', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'owner',
}
})
it('has role owner', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'admin-member-user',
myRoleInGroup: 'owner',
},
},
errors: undefined,
})
})
})
describe('back to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by usual member "usual-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await usualMemberUser.toJson()
})
describe('upgrade to owner', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'owner',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('degrade to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by still pending member "pending-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await pendingMemberUser.toJson()
})
describe('upgrade to owner', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'owner',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('degrade to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by none member "current-user"', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
describe('upgrade to owner', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'owner',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('degrade to pending again', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'pending',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
describe('of usual member "usual-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'usual-member-user',
}
})
describe('by owner "owner-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await ownerMemberUser.toJson()
})
describe('to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('has role admin', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'usual-member-user',
myRoleInGroup: 'admin',
},
},
errors: undefined,
})
})
})
describe('back to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('has role usual again', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'usual-member-user',
myRoleInGroup: 'usual',
},
},
errors: undefined,
})
})
})
})
describe('by usual member "usual-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await usualMemberUser.toJson()
})
describe('upgrade to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('degrade to pending', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'pending',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by still pending member "pending-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await pendingMemberUser.toJson()
})
describe('upgrade to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('degrade to pending', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'pending',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by none member "current-user"', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
describe('upgrade to admin', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'admin',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('degrade to pending again', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'pending',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
describe('of still pending member "pending-member-user"', () => {
beforeEach(async () => {
variables = {
...variables,
userId: 'pending-member-user',
}
})
describe('by owner "owner-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await ownerMemberUser.toJson()
})
describe('to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('has role usual', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'pending-member-user',
myRoleInGroup: 'usual',
},
},
errors: undefined,
})
})
})
describe('back to pending', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'pending',
}
})
it('has role usual again', async () => {
await expect(
mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
data: {
ChangeGroupMemberRole: {
id: 'pending-member-user',
myRoleInGroup: 'pending',
},
},
errors: undefined,
})
})
})
})
describe('by usual member "usual-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await usualMemberUser.toJson()
})
describe('upgrade to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by still pending member "pending-member-user"', () => {
beforeEach(async () => {
authenticatedUser = await pendingMemberUser.toJson()
})
describe('upgrade to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
describe('by none member "current-user"', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
describe('upgrade to usual', () => {
beforeEach(async () => {
variables = {
...variables,
roleInGroup: 'usual',
}
})
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
})
})
})
})
describe('LeaveGroup', () => {
beforeAll(async () => {
await seedComplexScenarioAndClearAuthentication()
// closed-group
authenticatedUser = await ownerMemberUser.toJson()
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'pending-member-user',
roleInGroup: 'pending',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'usual-member-user',
roleInGroup: 'usual',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'admin-member-user',
roleInGroup: 'admin',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'second-owner-member-user',
roleInGroup: 'owner',
},
})
authenticatedUser = null
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: leaveGroupMutation(),
variables: {
groupId: 'not-existing-group',
userId: 'current-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
describe('in all group types', () => {
describe('here "closed-group" for example', () => {
const memberInGroup = async (userId, groupId) => {
const result = await query({
query: groupMembersQuery(),
variables: {
id: groupId,
},
})
return result.data && result.data.GroupMembers
? !!result.data.GroupMembers.find((member) => member.id === userId)
: null
}
beforeEach(async () => {
authenticatedUser = null
variables = {
groupId: 'closed-group',
}
})
describe('left by "pending-member-user"', () => {
it('has "null" as membership role, was in the group, and left the group', async () => {
authenticatedUser = await ownerMemberUser.toJson()
expect(await memberInGroup('pending-member-user', 'closed-group')).toBe(true)
authenticatedUser = await pendingMemberUser.toJson()
await expect(
mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'pending-member-user',
},
}),
).resolves.toMatchObject({
data: {
LeaveGroup: {
id: 'pending-member-user',
myRoleInGroup: null,
},
},
errors: undefined,
})
authenticatedUser = await ownerMemberUser.toJson()
expect(await memberInGroup('pending-member-user', 'closed-group')).toBe(false)
})
})
describe('left by "usual-member-user"', () => {
it('has "null" as membership role, was in the group, and left the group', async () => {
authenticatedUser = await ownerMemberUser.toJson()
expect(await memberInGroup('usual-member-user', 'closed-group')).toBe(true)
authenticatedUser = await usualMemberUser.toJson()
await expect(
mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'usual-member-user',
},
}),
).resolves.toMatchObject({
data: {
LeaveGroup: {
id: 'usual-member-user',
myRoleInGroup: null,
},
},
errors: undefined,
})
authenticatedUser = await ownerMemberUser.toJson()
expect(await memberInGroup('usual-member-user', 'closed-group')).toBe(false)
})
})
describe('left by "admin-member-user"', () => {
it('has "null" as membership role, was in the group, and left the group', async () => {
authenticatedUser = await ownerMemberUser.toJson()
expect(await memberInGroup('admin-member-user', 'closed-group')).toBe(true)
authenticatedUser = await adminMemberUser.toJson()
await expect(
mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'admin-member-user',
},
}),
).resolves.toMatchObject({
data: {
LeaveGroup: {
id: 'admin-member-user',
myRoleInGroup: null,
},
},
errors: undefined,
})
authenticatedUser = await ownerMemberUser.toJson()
expect(await memberInGroup('admin-member-user', 'closed-group')).toBe(false)
})
})
describe('left by "owner-member-user"', () => {
it('throws authorization error', async () => {
authenticatedUser = await ownerMemberUser.toJson()
const { errors } = await mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'owner-member-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('left by "second-owner-member-user"', () => {
it('throws authorization error', async () => {
authenticatedUser = await secondOwnerMemberUser.toJson()
const { errors } = await mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'second-owner-member-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('left by "none-member-user"', () => {
it('throws authorization error', async () => {
authenticatedUser = await noMemberUser.toJson()
const { errors } = await mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'none-member-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('as "owner-member-user" try to leave member "usual-member-user"', () => {
it('throws authorization error', async () => {
authenticatedUser = await ownerMemberUser.toJson()
const { errors } = await mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'usual-member-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('as "usual-member-user" try to leave member "admin-member-user"', () => {
it('throws authorization error', async () => {
authenticatedUser = await usualMemberUser.toJson()
const { errors } = await mutate({
mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'admin-member-user',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
})
})
describe('UpdateGroup', () => {
beforeAll(async () => {
await seedBasicsAndClearAuthentication()
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
slug: 'my-best-group',
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('authenticated', () => {
let noMemberUser
beforeAll(async () => {
noMemberUser = await Factory.build(
'user',
{
id: 'none-member-user',
name: 'None Member TestUser',
},
{
email: 'none-member-user@example.org',
password: '1234',
},
)
usualMemberUser = await Factory.build(
'user',
{
id: 'usual-member-user',
name: 'Usual Member TestUser',
},
{
email: 'usual-member-user@example.org',
password: '1234',
},
)
authenticatedUser = await noMemberUser.toJson()
await mutate({
mutation: createGroupMutation(),
variables: {
id: 'others-group',
name: 'Uninteresting Group',
about: 'We will change nothing!',
description: 'We love it like it is!?' + descriptionAdditional100,
groupType: 'closed',
actionRadius: 'global',
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' + descriptionAdditional100,
groupType: 'public',
actionRadius: 'regional',
categoryIds,
locationName: 'Berlin, Germany',
},
})
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'my-group',
userId: 'usual-member-user',
roleInGroup: 'usual',
},
})
})
describe('change group settings', () => {
describe('as owner', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
describe('all standard settings excluding location', () => {
it('has updated the settings', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
name: 'The New Group For Our Country',
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
// avatar, // test this as result
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
name: 'The New Group For Our Country',
slug: 'the-best-group', // changing the slug is tested in the slugifyMiddleware
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
descriptionExcerpt:
'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
// avatar, // test this as result
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('location', () => {
describe('"locationName" is undefined shall not change location', () => {
it('has left locaton unchanged as "Berlin"', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
locationName: 'Berlin, Germany',
location: expect.objectContaining({
name: 'Berlin',
nameDE: 'Berlin',
nameEN: 'Berlin',
}),
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('"locationName" is null shall change location "Berlin" to unset location', () => {
it('has updated the location to unset location', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
locationName: null,
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
locationName: null,
location: null,
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('change unset location to "Paris"', () => {
it('has updated the location to "Paris"', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
locationName: 'Paris, France',
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
locationName: 'Paris, France',
location: expect.objectContaining({
name: 'Paris',
nameDE: 'Paris',
nameEN: 'Paris',
}),
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('change location "Paris" to "Hamburg"', () => {
it('has updated the location to "Hamburg"', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
locationName: 'Hamburg, Germany',
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
locationName: 'Hamburg, Germany',
location: expect.objectContaining({
name: 'Hamburg',
nameDE: 'Hamburg',
nameEN: 'Hamburg',
}),
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('"locationName" is empty string shall change location "Hamburg" to unset location ', () => {
it('has updated the location to unset', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
locationName: '', // empty string '' sets it to null
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
locationName: null,
location: null,
myRole: 'owner',
},
},
errors: undefined,
})
})
})
})
describe('description', () => {
describe('length without HTML', () => {
describe('less then 100 chars', () => {
it('throws error: "Description too short!"', async () => {
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
description:
'0123456789' +
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0123456789</a>',
},
})
expect(errors[0]).toHaveProperty('message', 'Description too short!')
})
})
})
})
describe('categories', () => {
beforeEach(async () => {
CONFIG.CATEGORIES_ACTIVE = true
})
describe('with matching amount of categories', () => {
it('has new categories', async () => {
await expect(
mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
categoryIds: ['cat4', 'cat27'],
},
}),
).resolves.toMatchObject({
data: {
UpdateGroup: {
id: 'my-group',
categories: expect.arrayContaining([
expect.objectContaining({ id: 'cat4' }),
expect.objectContaining({ id: 'cat27' }),
]),
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('not even one', () => {
describe('by "categoryIds: []"', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
categoryIds: [],
},
})
expect(errors[0]).toHaveProperty('message', 'Too view categories!')
})
})
})
describe('four', () => {
it('throws error: "Too many categories!"', async () => {
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'],
},
})
expect(errors[0]).toHaveProperty('message', 'Too many categories!')
})
})
})
})
describe('as "usual-member-user" member, no(!) owner', () => {
it('throws authorization error', async () => {
authenticatedUser = await usualMemberUser.toJson()
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
name: 'The New Group For Our Country',
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
categoryIds: ['cat4', 'cat27'],
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
describe('as "none-member-user"', () => {
it('throws authorization error', async () => {
authenticatedUser = await noMemberUser.toJson()
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
name: 'The New Group For Our Country',
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
categoryIds: ['cat4', 'cat27'],
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})
})
})
})
describe('RemoveUserFromGroup', () => {
beforeAll(async () => {
await seedComplexScenarioAndClearAuthentication()
})
afterAll(async () => {
await cleanDatabase()
})
describe('unauthenticated', () => {
it('throws an error', async () => {
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'usual-member-user',
},
}),
).resolves.toMatchObject({
errors: expect.arrayContaining([
expect.objectContaining({
message: 'Not Authorized!',
}),
]),
})
})
})
describe('authenticated', () => {
describe('as usual member', () => {
it('throws an error', async () => {
authenticatedUser = await usualMemberUser.toJson()
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'admin-member-user',
},
}),
).resolves.toMatchObject({
errors: expect.arrayContaining([
expect.objectContaining({
message: 'Not Authorized!',
}),
]),
})
})
})
describe('as owner', () => {
beforeEach(async () => {
authenticatedUser = await ownerMemberUser.toJson()
})
it('removes the user from the group', async () => {
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'usual-member-user',
},
}),
).resolves.toMatchObject({
data: {
RemoveUserFromGroup: expect.objectContaining({
id: 'usual-member-user',
myRoleInGroup: null,
}),
},
errors: undefined,
})
})
it('cannot remove self', async () => {
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-member-user',
},
}),
).resolves.toMatchObject({
errors: expect.arrayContaining([
expect.objectContaining({
message: 'Not Authorized!',
}),
]),
})
})
})
describe('as admin', () => {
beforeEach(async () => {
authenticatedUser = await adminMemberUser.toJson()
await mutate({
mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'usual-member-user',
roleInGroup: 'usual',
},
})
})
it('throws an error', async () => {
authenticatedUser = await usualMemberUser.toJson()
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'admin-member-user',
},
}),
).resolves.toMatchObject({
errors: expect.arrayContaining([
expect.objectContaining({
message: 'Not Authorized!',
}),
]),
})
})
/*
it('removes the user from the group', async () => {
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'usual-member-user',
},
}),
).resolves.toMatchObject({
data: {
RemoveUserFromGroup: expect.objectContaining({
id: 'usual-member-user',
myRoleInGroup: null,
}),
},
errors: undefined,
})
})
it('cannot remove self', async () => {
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'admin-member-user',
},
}),
).resolves.toMatchObject({
errors: expect.arrayContaining([
expect.objectContaining({
message: 'Not Authorized!',
}),
]),
})
})
it('cannot remove owner', async () => {
await expect(
mutate({
mutation: removeUserFromGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-member-user',
},
}),
).resolves.toMatchObject({
errors: expect.arrayContaining([
expect.objectContaining({
message: 'Not Authorized!',
}),
]),
})
})
*/
})
})
})
})