Test 'UpdateGroup' in general resolver and 'Group' resolver with 'id'

This commit is contained in:
Wolfgang Huß 2022-09-02 08:10:46 +02:00
parent b82dcd45aa
commit 7ec6086915
4 changed files with 231 additions and 86 deletions

View File

@ -38,14 +38,15 @@ export const createGroupMutation = gql`
description
groupType
actionRadius
# categories {
# id
# slug
# name
# icon
# }
# avatar
# locationName
categories {
# test this as result
id
slug
name
icon
}
# avatar # test this as result
# locationName # test this as result
myRole
}
}
@ -85,14 +86,15 @@ export const updateGroupMutation = gql`
description
groupType
actionRadius
# categories {
# id
# slug
# name
# icon
# }
# avatar
# locationName
categories {
# test this as result
id
slug
name
icon
}
# avatar # test this as result
# locationName # test this as result
myRole
}
}
@ -166,6 +168,7 @@ export const groupQuery = gql`
actionRadius
myRole
categories {
# test this as result
id
slug
name

View File

@ -9,25 +9,26 @@ import Resolver from './helpers/Resolver'
export default {
Query: {
Group: async (_object, params, context, _resolveInfo) => {
const { isMember } = params
const { id: groupId, isMember } = params
const session = context.driver.session()
const readTxResultPromise = session.readTransaction(async (txc) => {
const groupIdCypher = groupId ? ` {id: "${groupId}"}` : ''
let groupCypher
if (isMember === true) {
groupCypher = `
MATCH (:User {id: $userId})-[membership:MEMBER_OF]->(group:Group)
MATCH (:User {id: $userId})-[membership:MEMBER_OF]->(group:Group${groupIdCypher})
RETURN group {.*, myRole: membership.role}
`
} else {
if (isMember === false) {
groupCypher = `
MATCH (group:Group)
MATCH (group:Group${groupIdCypher})
WHERE NOT (:User {id: $userId})-[:MEMBER_OF]->(group)
RETURN group {.*, myRole: NULL}
`
} else {
groupCypher = `
MATCH (group:Group)
MATCH (group:Group${groupIdCypher})
OPTIONAL MATCH (:User {id: $userId})-[membership:MEMBER_OF]->(group)
RETURN group {.*, myRole: membership.role}
`
@ -153,6 +154,16 @@ export default {
throw new UserInputError('Description too short!')
}
const session = context.driver.session()
if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
const cypherDeletePreviousRelations = `
MATCH (group:Group {id: $groupId})-[previousRelations:CATEGORIZED]->(category:Category)
DELETE previousRelations
RETURN group, category
`
await session.writeTransaction((transaction) => {
return transaction.run(cypherDeletePreviousRelations, { groupId })
})
}
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
let updateGroupCypher = `
MATCH (group:Group {id: $groupId})
@ -161,14 +172,6 @@ export default {
WITH group
`
if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
const cypherDeletePreviousRelations = `
MATCH (group:Group {id: $groupId})-[previousRelations:CATEGORIZED]->(category:Category)
DELETE previousRelations
RETURN group, category
`
await session.writeTransaction((transaction) => {
return transaction.run(cypherDeletePreviousRelations, { groupId })
})
updateGroupCypher += `
UNWIND $categoryIds AS categoryId
MATCH (category:Category {id: categoryId})

View File

@ -107,6 +107,8 @@ describe('in mode', () => {
groupType: 'public',
actionRadius: 'regional',
categoryIds,
// avatar, // test this as result
// locationName, // test this as result
}
})
@ -183,13 +185,50 @@ describe('in mode', () => {
CONFIG.CATEGORIES_ACTIVE = true
})
describe('not even one', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
mutation: createGroupMutation,
variables: { ...variables, categoryIds: null },
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!')
})
expect(errors[0]).toHaveProperty('message', 'Too view categories!')
})
})
@ -290,6 +329,25 @@ describe('in mode', () => {
})
})
describe("id = 'my-group'", () => {
it('finds only the group with this id', async () => {
await expect(
query({ query: groupQuery, variables: { id: 'my-group' } }),
).resolves.toMatchObject({
data: {
Group: [
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
myRole: 'owner',
}),
],
},
errors: undefined,
})
})
})
describe('isMember = true', () => {
it('finds only groups where user is member', async () => {
await expect(
@ -2055,7 +2113,7 @@ describe('in mode', () => {
})
describe('unauthenticated', () => {
it.only('throws authorization error', async () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
query: updateGroupMutation,
variables: {
@ -2110,64 +2168,141 @@ describe('in mode', () => {
})
})
describe('query groups', () => {
describe('without any filters', () => {
it('finds all groups', async () => {
await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({
describe('change group settings', () => {
describe('as owner', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
})
it('has set the settings', async () => {
await expect(
mutate({
mutation: updateGroupMutation,
variables: {
id: 'my-group',
name: 'The New Group For Our Coutry',
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
// avatar, // test this as result
// locationName, // test this as result
},
}),
).resolves.toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
myRole: 'owner',
}),
expect.objectContaining({
id: 'others-group',
slug: 'uninteresting-group',
myRole: null,
}),
]),
UpdateGroup: {
id: 'my-group',
name: 'The New Group For Our Coutry',
slug: 'the-new-group-for-our-coutry', // changing the slug is tested in the slugifyMiddleware
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
// avatar, // test this as result
// locationName, // test this as result
myRole: 'owner',
},
},
errors: undefined,
})
})
})
describe('isMember = true', () => {
it('finds only groups where user is member', async () => {
await expect(
query({ query: groupQuery, variables: { isMember: true } }),
).resolves.toMatchObject({
data: {
Group: [
{
id: 'my-group',
slug: 'the-best-group',
myRole: 'owner',
describe('description', () => {
describe('length without HTML', () => {
describe('less then 100 chars', () => {
it('throws error: "Too view categories!"', 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,
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('isMember = false', () => {
it('finds only groups where user is not(!) member', async () => {
await expect(
query({ query: groupQuery, variables: { isMember: false } }),
).resolves.toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'others-group',
slug: 'uninteresting-group',
myRole: null,
}),
]),
describe('as no(!) owner', () => {
it('throws authorization error', async () => {
authenticatedUser = await otherUser.toJson()
const { errors } = await mutate({
mutation: updateGroupMutation,
variables: {
id: 'my-group',
name: 'The New Group For Our Coutry',
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
categoryIds: ['cat4', 'cat27'], // test this as result
// avatar, // test this as result
// locationName, // test this as result
},
errors: undefined,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
})

View File

@ -67,6 +67,9 @@ type Query {
updatedAt: String
about: String
description: String
# groupType: GroupType # test this
# actionRadius: GroupActionRadius # test this
# avatar: ImageInput # test this
locationName: String
first: Int
offset: Int
@ -93,13 +96,13 @@ type Mutation {
id: ID
name: String!
slug: String
avatar: ImageInput
about: String
description: String!
groupType: GroupType!
actionRadius: GroupActionRadius!
categoryIds: [ID]
locationName: String
categoryIds: [ID] # test this as result
avatar: ImageInput # test this as result
locationName: String # test this as result
): Group
UpdateGroup(
@ -108,10 +111,11 @@ type Mutation {
slug: String
about: String
description: String
# groupType: GroupType # is not possible at the moment and has to be discussed. may be in the stronger direction: public → closed → hidden
actionRadius: GroupActionRadius
categoryIds: [ID]
avatar: ImageInput
locationName: String
categoryIds: [ID] # test this as result
avatar: ImageInput # test this as result
locationName: String # test this as result
): Group
# DeleteGroup(id: ID!): Group