mirror of
https://github.com/IT4Change/gradido.git
synced 2026-03-01 12:44:43 +00:00
642 lines
21 KiB
TypeScript
642 lines
21 KiB
TypeScript
import { ContributionStatus } from '@enum/ContributionStatus'
|
|
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
|
|
import { ApolloServerTestClient } from 'apollo-server-testing'
|
|
import { getLogger } from 'config-schema/test/testSetup'
|
|
import { sendAddedContributionMessageEmail } from 'core'
|
|
import { AppDatabase, Contribution as DbContribution, Event as DbEvent } from 'database'
|
|
import { GraphQLError } from 'graphql'
|
|
import { DataSource } from 'typeorm'
|
|
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
|
import { EventType } from '@/event/Events'
|
|
import { userFactory } from '@/seeds/factory/user'
|
|
import {
|
|
adminCreateContributionMessage,
|
|
createContribution,
|
|
createContributionMessage,
|
|
login,
|
|
} from '@/seeds/graphql/mutations'
|
|
import { adminListContributionMessages, listContributionMessages } from '@/seeds/graphql/queries'
|
|
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
|
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
|
|
import { peterLustig } from '@/seeds/users/peter-lustig'
|
|
|
|
const logger = getLogger(
|
|
`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.ContributionMessageResolver`,
|
|
)
|
|
const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`)
|
|
const interactionLogger = getLogger(
|
|
`${LOG4JS_BASE_CATEGORY_NAME}.interactions.updateUnconfirmedContribution`,
|
|
)
|
|
|
|
jest.mock('@/password/EncryptorUtils')
|
|
jest.mock('core', () => {
|
|
const originalModule = jest.requireActual('core')
|
|
return {
|
|
__esModule: true,
|
|
...originalModule,
|
|
sendAddedContributionMessageEmail: jest.fn(),
|
|
}
|
|
})
|
|
|
|
let mutate: ApolloServerTestClient['mutate']
|
|
let con: DataSource
|
|
let db: AppDatabase
|
|
let testEnv: {
|
|
mutate: ApolloServerTestClient['mutate']
|
|
query: ApolloServerTestClient['query']
|
|
con: DataSource
|
|
db: AppDatabase
|
|
}
|
|
let result: any
|
|
|
|
beforeAll(async () => {
|
|
testEnv = await testEnvironment(logger)
|
|
mutate = testEnv.mutate
|
|
con = testEnv.con
|
|
db = testEnv.db
|
|
await cleanDB()
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await cleanDB()
|
|
await con.destroy()
|
|
await db.getRedisClient().quit()
|
|
})
|
|
|
|
describe('ContributionMessageResolver', () => {
|
|
describe('adminCreateContributionMessage', () => {
|
|
describe('unauthenticated', () => {
|
|
it('returns an error', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: adminCreateContributionMessage,
|
|
variables: { contributionId: 1, message: 'This is a test message' },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [new GraphQLError('401 Unauthorized')],
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('authenticated', () => {
|
|
beforeAll(async () => {
|
|
await userFactory(testEnv, bibiBloxberg)
|
|
await userFactory(testEnv, peterLustig)
|
|
await userFactory(testEnv, bobBaumeister)
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
})
|
|
result = await mutate({
|
|
mutation: createContribution,
|
|
variables: {
|
|
amount: 100.0,
|
|
memo: 'Test env contribution',
|
|
contributionDate: new Date().toString(),
|
|
},
|
|
})
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
|
})
|
|
})
|
|
|
|
afterAll(() => {
|
|
resetToken()
|
|
})
|
|
|
|
describe('input not valid', () => {
|
|
it('throws error when contribution does not exist', async () => {
|
|
jest.clearAllMocks()
|
|
await expect(
|
|
mutate({
|
|
mutation: adminCreateContributionMessage,
|
|
variables: {
|
|
contributionId: -1,
|
|
message: 'Test',
|
|
},
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [
|
|
new GraphQLError(
|
|
'ContributionMessage was not sent successfully: Error: Contribution not found',
|
|
),
|
|
],
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('logs the error "ContributionMessage was not sent successfully: Error: Contribution not found"', () => {
|
|
expect(logErrorLogger.error).toBeCalledWith(
|
|
'ContributionMessage was not sent successfully: Error: Contribution not found',
|
|
new Error('Contribution not found'),
|
|
)
|
|
})
|
|
|
|
it('treat the logged-in user as a normal user, not as a moderator or admin if contribution.userId equals user.id', async () => {
|
|
jest.clearAllMocks()
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
|
})
|
|
const result2 = await mutate({
|
|
mutation: createContribution,
|
|
variables: {
|
|
amount: 100.0,
|
|
memo: 'Test env contribution',
|
|
contributionDate: new Date().toString(),
|
|
},
|
|
})
|
|
const mutationResult = await mutate({
|
|
mutation: adminCreateContributionMessage,
|
|
variables: {
|
|
contributionId: result2.data.createContribution.id,
|
|
message: 'Test',
|
|
},
|
|
})
|
|
expect(interactionLogger.debug).toBeCalledWith(
|
|
'use UnconfirmedContributionUserAddMessageRole',
|
|
)
|
|
expect(mutationResult).toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
adminCreateContributionMessage: expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userLastName: 'Lustig',
|
|
}),
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('contribution message type MODERATOR', () => {
|
|
beforeAll(() => {
|
|
jest.clearAllMocks()
|
|
})
|
|
|
|
it('creates ContributionMessage', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: adminCreateContributionMessage,
|
|
variables: {
|
|
contributionId: result.data.createContribution.id,
|
|
message: 'Internal moderator communication',
|
|
messageType: 'MODERATOR',
|
|
},
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
adminCreateContributionMessage: expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Internal moderator communication',
|
|
type: 'MODERATOR',
|
|
userFirstName: 'Peter',
|
|
userLastName: 'Lustig',
|
|
}),
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('does not call sendAddedContributionMessageEmail', () => {
|
|
expect(sendAddedContributionMessageEmail).not.toBeCalled()
|
|
})
|
|
|
|
it('does not change contribution status', async () => {
|
|
await expect(DbContribution.find()).resolves.toContainEqual(
|
|
expect.objectContaining({
|
|
id: result.data.createContribution.id,
|
|
contributionStatus: ContributionStatus.PENDING,
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('valid input', () => {
|
|
it('creates ContributionMessage', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: adminCreateContributionMessage,
|
|
variables: {
|
|
contributionId: result.data.createContribution.id,
|
|
message: 'Admin Test',
|
|
},
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
adminCreateContributionMessage: expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Admin Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userLastName: 'Lustig',
|
|
}),
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('calls sendAddedContributionMessageEmail', () => {
|
|
expect(sendAddedContributionMessageEmail).toBeCalledWith({
|
|
firstName: 'Bibi',
|
|
lastName: 'Bloxberg',
|
|
email: 'bibi@bloxberg.de',
|
|
language: 'de',
|
|
message: 'Admin Test',
|
|
senderFirstName: 'Peter',
|
|
senderLastName: 'Lustig',
|
|
contributionMemo: 'Test env contribution',
|
|
contributionFrontendLink: `http://localhost/contributions/own-contributions/1#contributionListItem-${result.data.createContribution.id}`,
|
|
})
|
|
})
|
|
|
|
it('changes contribution status', async () => {
|
|
await expect(DbContribution.find()).resolves.toContainEqual(
|
|
expect.objectContaining({
|
|
id: result.data.createContribution.id,
|
|
contributionStatus: ContributionStatus.IN_PROGRESS,
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('stores the ADMIN_CONTRIBUTION_MESSAGE_CREATE event in the database', async () => {
|
|
await expect(DbEvent.find()).resolves.toContainEqual(
|
|
expect.objectContaining({
|
|
type: EventType.ADMIN_CONTRIBUTION_MESSAGE_CREATE,
|
|
affectedUserId: expect.any(Number),
|
|
actingUserId: expect.any(Number),
|
|
involvedContributionId: result.data.createContribution.id,
|
|
involvedContributionMessageId: expect.any(Number),
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('createContributionMessage', () => {
|
|
describe('unauthenticated', () => {
|
|
it('returns an error', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: createContributionMessage,
|
|
variables: { contributionId: 1, message: 'This is a test message' },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [new GraphQLError('401 Unauthorized')],
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('authenticated', () => {
|
|
beforeAll(async () => {
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
})
|
|
})
|
|
|
|
afterAll(() => {
|
|
resetToken()
|
|
})
|
|
|
|
describe('input not valid', () => {
|
|
it('throws error when contribution does not exist', async () => {
|
|
jest.clearAllMocks()
|
|
await expect(
|
|
mutate({
|
|
mutation: createContributionMessage,
|
|
variables: {
|
|
contributionId: -1,
|
|
message: 'Test',
|
|
},
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [
|
|
new GraphQLError(
|
|
'ContributionMessage was not sent successfully: Error: Contribution not found',
|
|
),
|
|
],
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('logs the error "ContributionMessage was not sent successfully: Error: Contribution not found"', () => {
|
|
expect(logErrorLogger.error).toBeCalledWith(
|
|
'ContributionMessage was not sent successfully: Error: Contribution not found',
|
|
new Error('Contribution not found'),
|
|
)
|
|
})
|
|
|
|
it('other user tries to send createContributionMessage but is also moderator or admin so it is allowed', async () => {
|
|
jest.clearAllMocks()
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
|
})
|
|
|
|
const mutationResult = await mutate({
|
|
mutation: createContributionMessage,
|
|
variables: {
|
|
contributionId: result.data.createContribution.id,
|
|
message: 'Test',
|
|
},
|
|
})
|
|
|
|
expect(interactionLogger.debug).toBeCalledWith(
|
|
'use UnconfirmedContributionAdminAddMessageRole',
|
|
)
|
|
|
|
expect(mutationResult).toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
createContributionMessage: expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userLastName: 'Lustig',
|
|
}),
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('throws error when other user tries to send createContributionMessage', async () => {
|
|
jest.clearAllMocks()
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'bob@baumeister.de', password: 'Aa12345_' },
|
|
})
|
|
const mutationResult = await mutate({
|
|
mutation: createContributionMessage,
|
|
variables: {
|
|
contributionId: result.data.createContribution.id,
|
|
message: 'Test',
|
|
},
|
|
})
|
|
expect(interactionLogger.debug).toBeCalledWith(
|
|
'use UnconfirmedContributionAdminAddMessageRole',
|
|
)
|
|
|
|
expect(mutationResult).toEqual(
|
|
expect.objectContaining({
|
|
errors: [
|
|
new GraphQLError(
|
|
'ContributionMessage was not sent successfully: Error: missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user',
|
|
),
|
|
],
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('logs the error "ContributionMessage was not sent successfully: Error: missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user"', () => {
|
|
expect(logErrorLogger.error).toHaveBeenNthCalledWith(
|
|
1,
|
|
'missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user',
|
|
expect.any(Number),
|
|
)
|
|
expect(logErrorLogger.error).toHaveBeenNthCalledWith(
|
|
2,
|
|
'ContributionMessage was not sent successfully: Error: missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user',
|
|
new Error('missing right ADMIN_CREATE_CONTRIBUTION_MESSAGE for user'),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('valid input', () => {
|
|
beforeAll(async () => {
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
})
|
|
})
|
|
|
|
it('creates ContributionMessage', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: createContributionMessage,
|
|
variables: {
|
|
contributionId: result.data.createContribution.id,
|
|
message: 'User Test',
|
|
},
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
createContributionMessage: expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'User Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Bibi',
|
|
userLastName: 'Bloxberg',
|
|
}),
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
|
|
it('stores the CONTRIBUTION_MESSAGE_CREATE event in the database', async () => {
|
|
await expect(DbEvent.find()).resolves.toContainEqual(
|
|
expect.objectContaining({
|
|
type: EventType.CONTRIBUTION_MESSAGE_CREATE,
|
|
affectedUserId: expect.any(Number),
|
|
actingUserId: expect.any(Number),
|
|
involvedContributionId: result.data.createContribution.id,
|
|
involvedContributionMessageId: expect.any(Number),
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('listContributionMessages', () => {
|
|
describe('unauthenticated', () => {
|
|
it('returns an error', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: listContributionMessages,
|
|
variables: { contributionId: 1 },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [new GraphQLError('401 Unauthorized')],
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('authenticated', () => {
|
|
beforeAll(async () => {
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
})
|
|
})
|
|
|
|
afterAll(() => {
|
|
resetToken()
|
|
})
|
|
|
|
it('returns a list of contributionmessages without type MODERATOR', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: listContributionMessages,
|
|
variables: { contributionId: result.data.createContribution.id },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
listContributionMessages: {
|
|
count: 3,
|
|
messages: expect.arrayContaining([
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Admin Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Lustig',
|
|
}),
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Lustig',
|
|
}),
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'User Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Bibi',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Bloxberg',
|
|
}),
|
|
]),
|
|
},
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('adminListContributionMessages', () => {
|
|
describe('unauthenticated', () => {
|
|
it('returns an error', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: adminListContributionMessages,
|
|
variables: { contributionId: 1 },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [new GraphQLError('401 Unauthorized')],
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('authenticated as user', () => {
|
|
beforeAll(async () => {
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
})
|
|
})
|
|
|
|
it('returns an error', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: adminListContributionMessages,
|
|
variables: { contributionId: 1 },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
errors: [new GraphQLError('401 Unauthorized')],
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('authenticated as admin', () => {
|
|
beforeAll(async () => {
|
|
await mutate({
|
|
mutation: login,
|
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
|
})
|
|
})
|
|
|
|
afterAll(() => {
|
|
resetToken()
|
|
})
|
|
|
|
it('returns a list of contributionmessages with type MODERATOR', async () => {
|
|
await expect(
|
|
mutate({
|
|
mutation: adminListContributionMessages,
|
|
variables: { contributionId: result.data.createContribution.id },
|
|
}),
|
|
).resolves.toEqual(
|
|
expect.objectContaining({
|
|
data: {
|
|
adminListContributionMessages: {
|
|
count: 4,
|
|
messages: expect.arrayContaining([
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Admin Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Lustig',
|
|
}),
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Peter',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Lustig',
|
|
}),
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'User Test',
|
|
type: 'DIALOG',
|
|
userFirstName: 'Bibi',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Bloxberg',
|
|
}),
|
|
expect.objectContaining({
|
|
id: expect.any(Number),
|
|
message: 'Internal moderator communication',
|
|
type: 'MODERATOR',
|
|
userFirstName: 'Peter',
|
|
userId: expect.any(Number),
|
|
userLastName: 'Lustig',
|
|
}),
|
|
]),
|
|
},
|
|
},
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
})
|
|
})
|