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' +
'0123456789',
},
})
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' +
'0123456789',
},
})
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!',
}),
]),
})
})
*/
})
})
})
})