mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge pull request #2705 from gradido/authenticated_tests_for_TransactionLinkResolver
test(backend): authentication tests for TransactionLinkResolver
This commit is contained in:
commit
40d08120e3
@ -53,65 +53,81 @@ afterAll(async () => {
|
|||||||
|
|
||||||
describe('TransactionLinkResolver', () => {
|
describe('TransactionLinkResolver', () => {
|
||||||
describe('createTransactionLink', () => {
|
describe('createTransactionLink', () => {
|
||||||
beforeAll(async () => {
|
describe('unauthenticated', () => {
|
||||||
await mutate({
|
it('throws an error', async () => {
|
||||||
mutation: login,
|
jest.clearAllMocks()
|
||||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
resetToken()
|
||||||
|
await expect(
|
||||||
|
mutate({ mutation: createTransactionLink, variables: { amount: 0, memo: 'Test' } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws error when amount is zero', async () => {
|
describe('authenticated', () => {
|
||||||
jest.clearAllMocks()
|
beforeAll(async () => {
|
||||||
await expect(
|
await mutate({
|
||||||
mutate({
|
mutation: login,
|
||||||
mutation: createTransactionLink,
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
variables: {
|
})
|
||||||
amount: 0,
|
|
||||||
memo: 'Test',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toMatchObject({
|
|
||||||
errors: [new GraphQLError('Amount must be a positive number')],
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(0))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('throws error when amount is negative', async () => {
|
it('throws error when amount is zero', async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createTransactionLink,
|
mutation: createTransactionLink,
|
||||||
variables: {
|
variables: {
|
||||||
amount: -10,
|
amount: 0,
|
||||||
memo: 'Test',
|
memo: 'Test',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [new GraphQLError('Amount must be a positive number')],
|
errors: [new GraphQLError('Amount must be a positive number')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(0))
|
||||||
})
|
})
|
||||||
})
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(-10))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('throws error when user has not enough GDD', async () => {
|
it('throws error when amount is negative', async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createTransactionLink,
|
mutation: createTransactionLink,
|
||||||
variables: {
|
variables: {
|
||||||
amount: 1001,
|
amount: -10,
|
||||||
memo: 'Test',
|
memo: 'Test',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [new GraphQLError('User has not enough GDD')],
|
errors: [new GraphQLError('Amount must be a positive number')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(-10))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when user has not enough GDD', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: 1001,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('User has not enough GDD')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('User has not enough GDD', expect.any(Number))
|
||||||
})
|
})
|
||||||
})
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('User has not enough GDD', expect.any(Number))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -121,236 +137,37 @@ describe('TransactionLinkResolver', () => {
|
|||||||
resetToken()
|
resetToken()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('contributionLink', () => {
|
describe('unauthenticated', () => {
|
||||||
describe('input not valid', () => {
|
it('throws an error', async () => {
|
||||||
beforeAll(async () => {
|
jest.clearAllMocks()
|
||||||
await mutate({
|
resetToken()
|
||||||
mutation: login,
|
await expect(
|
||||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
mutate({ mutation: redeemTransactionLink, variables: { code: 'CL-123456' } }),
|
||||||
})
|
).resolves.toEqual(
|
||||||
})
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
it('throws error when link does not exists', async () => {
|
}),
|
||||||
jest.clearAllMocks()
|
)
|
||||||
await expect(
|
|
||||||
mutate({
|
|
||||||
mutation: redeemTransactionLink,
|
|
||||||
variables: {
|
|
||||||
code: 'CL-123456',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toMatchObject({
|
|
||||||
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith(
|
|
||||||
'No contribution link found to given code',
|
|
||||||
'CL-123456',
|
|
||||||
)
|
|
||||||
expect(logger.error).toBeCalledWith(
|
|
||||||
'Creation from contribution link was not successful',
|
|
||||||
new Error('No contribution link found to given code'),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const validFrom = new Date(now.getFullYear() + 1, 0, 1)
|
|
||||||
|
|
||||||
it('throws error when link is not valid yet', async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
const {
|
|
||||||
data: { createContributionLink: contributionLink },
|
|
||||||
} = await mutate({
|
|
||||||
mutation: createContributionLink,
|
|
||||||
variables: {
|
|
||||||
amount: new Decimal(5),
|
|
||||||
name: 'Daily Contribution Link',
|
|
||||||
memo: 'Thank you for contribute daily to the community',
|
|
||||||
cycle: 'DAILY',
|
|
||||||
validFrom: validFrom.toISOString(),
|
|
||||||
validTo: new Date(now.getFullYear() + 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
|
||||||
maxAmountPerMonth: new Decimal(200),
|
|
||||||
maxPerCycle: 1,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await expect(
|
|
||||||
mutate({
|
|
||||||
mutation: redeemTransactionLink,
|
|
||||||
variables: {
|
|
||||||
code: 'CL-' + contributionLink.code,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toMatchObject({
|
|
||||||
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
|
||||||
})
|
|
||||||
await resetEntity(DbContributionLink)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('Contribution link is not valid yet', validFrom)
|
|
||||||
expect(logger.error).toBeCalledWith(
|
|
||||||
'Creation from contribution link was not successful',
|
|
||||||
new Error('Contribution link is not valid yet'),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('throws error when contributionLink cycle is invalid', async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
const now = new Date()
|
|
||||||
const {
|
|
||||||
data: { createContributionLink: contributionLink },
|
|
||||||
} = await mutate({
|
|
||||||
mutation: createContributionLink,
|
|
||||||
variables: {
|
|
||||||
amount: new Decimal(5),
|
|
||||||
name: 'Daily Contribution Link',
|
|
||||||
memo: 'Thank you for contribute daily to the community',
|
|
||||||
cycle: 'INVALID',
|
|
||||||
validFrom: new Date(now.getFullYear(), 0, 1).toISOString(),
|
|
||||||
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999).toISOString(),
|
|
||||||
maxAmountPerMonth: new Decimal(200),
|
|
||||||
maxPerCycle: 1,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await expect(
|
|
||||||
mutate({
|
|
||||||
mutation: redeemTransactionLink,
|
|
||||||
variables: {
|
|
||||||
code: 'CL-' + contributionLink.code,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toMatchObject({
|
|
||||||
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
|
||||||
})
|
|
||||||
await resetEntity(DbContributionLink)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('Contribution link has unknown cycle', 'INVALID')
|
|
||||||
expect(logger.error).toBeCalledWith(
|
|
||||||
'Creation from contribution link was not successful',
|
|
||||||
new Error('Contribution link has unknown cycle'),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const validTo = new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59, 0)
|
|
||||||
it('throws error when link is no longer valid', async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
const {
|
|
||||||
data: { createContributionLink: contributionLink },
|
|
||||||
} = await mutate({
|
|
||||||
mutation: createContributionLink,
|
|
||||||
variables: {
|
|
||||||
amount: new Decimal(5),
|
|
||||||
name: 'Daily Contribution Link',
|
|
||||||
memo: 'Thank you for contribute daily to the community',
|
|
||||||
cycle: 'DAILY',
|
|
||||||
validFrom: new Date(now.getFullYear() - 1, 0, 1).toISOString(),
|
|
||||||
validTo: validTo.toISOString(),
|
|
||||||
maxAmountPerMonth: new Decimal(200),
|
|
||||||
maxPerCycle: 1,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await expect(
|
|
||||||
mutate({
|
|
||||||
mutation: redeemTransactionLink,
|
|
||||||
variables: {
|
|
||||||
code: 'CL-' + contributionLink.code,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toMatchObject({
|
|
||||||
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
|
||||||
})
|
|
||||||
await resetEntity(DbContributionLink)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('Contribution link is no longer valid', validTo)
|
|
||||||
expect(logger.error).toBeCalledWith(
|
|
||||||
'Creation from contribution link was not successful',
|
|
||||||
new Error('Contribution link is no longer valid'),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// TODO: have this test separated into a transactionLink and a contributionLink part
|
describe('authenticated', () => {
|
||||||
describe('redeem daily Contribution Link', () => {
|
describe('contributionLink', () => {
|
||||||
const now = new Date()
|
describe('input not valid', () => {
|
||||||
let contributionLink: DbContributionLink | undefined
|
|
||||||
let contribution: UnconfirmedContribution | undefined
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await mutate({
|
|
||||||
mutation: login,
|
|
||||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
|
||||||
})
|
|
||||||
await mutate({
|
|
||||||
mutation: createContributionLink,
|
|
||||||
variables: {
|
|
||||||
amount: new Decimal(5),
|
|
||||||
name: 'Daily Contribution Link',
|
|
||||||
memo: 'Thank you for contribute daily to the community',
|
|
||||||
cycle: 'DAILY',
|
|
||||||
validFrom: new Date(now.getFullYear(), 0, 1).toISOString(),
|
|
||||||
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999).toISOString(),
|
|
||||||
maxAmountPerMonth: new Decimal(200),
|
|
||||||
maxPerCycle: 1,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('has a daily contribution link in the database', async () => {
|
|
||||||
const cls = await DbContributionLink.find()
|
|
||||||
expect(cls).toHaveLength(1)
|
|
||||||
contributionLink = cls[0]
|
|
||||||
expect(contributionLink).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(Number),
|
|
||||||
name: 'Daily Contribution Link',
|
|
||||||
memo: 'Thank you for contribute daily to the community',
|
|
||||||
validFrom: new Date(now.getFullYear(), 0, 1),
|
|
||||||
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 0),
|
|
||||||
cycle: 'DAILY',
|
|
||||||
maxPerCycle: 1,
|
|
||||||
totalMaxCountOfContribution: null,
|
|
||||||
maxAccountBalance: null,
|
|
||||||
minGapHours: null,
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
deletedAt: null,
|
|
||||||
code: expect.stringMatching(/^[0-9a-f]{24,24}$/),
|
|
||||||
linkEnabled: true,
|
|
||||||
amount: expect.decimalEqual(5),
|
|
||||||
maxAmountPerMonth: expect.decimalEqual(200),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('user has pending contribution of 1000 GDD', () => {
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: login,
|
mutation: login,
|
||||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
})
|
})
|
||||||
const result = await mutate({
|
|
||||||
mutation: createContribution,
|
|
||||||
variables: {
|
|
||||||
amount: new Decimal(1000),
|
|
||||||
memo: 'I was brewing potions for the community the whole month',
|
|
||||||
creationDate: now.toISOString(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
contribution = result.data.createContribution
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not allow the user to redeem the contribution link', async () => {
|
it('throws error when link does not exists', async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
variables: {
|
variables: {
|
||||||
code: 'CL-' + (contributionLink ? contributionLink.code : ''),
|
code: 'CL-123456',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
@ -359,85 +176,247 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'No contribution link found to given code',
|
||||||
|
'CL-123456',
|
||||||
|
)
|
||||||
expect(logger.error).toBeCalledWith(
|
expect(logger.error).toBeCalledWith(
|
||||||
'Creation from contribution link was not successful',
|
'Creation from contribution link was not successful',
|
||||||
new Error(
|
new Error('No contribution link found to given code'),
|
||||||
'The amount to be created exceeds the amount still available for this month',
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
describe('user has no pending contributions that would not allow to redeem the link', () => {
|
const now = new Date()
|
||||||
beforeAll(async () => {
|
const validFrom = new Date(now.getFullYear() + 1, 0, 1)
|
||||||
await mutate({
|
|
||||||
mutation: login,
|
|
||||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
||||||
})
|
|
||||||
await mutate({
|
|
||||||
mutation: updateContribution,
|
|
||||||
variables: {
|
|
||||||
contributionId: contribution ? contribution.id : -1,
|
|
||||||
amount: new Decimal(800),
|
|
||||||
memo: 'I was brewing potions for the community the whole month',
|
|
||||||
creationDate: now.toISOString(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('allows the user to redeem the contribution link', async () => {
|
it('throws error when link is not valid yet', async () => {
|
||||||
await expect(
|
|
||||||
mutate({
|
|
||||||
mutation: redeemTransactionLink,
|
|
||||||
variables: {
|
|
||||||
code: 'CL-' + (contributionLink ? contributionLink.code : ''),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toMatchObject({
|
|
||||||
data: {
|
|
||||||
redeemTransactionLink: true,
|
|
||||||
},
|
|
||||||
errors: undefined,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('does not allow the user to redeem the contribution link a second time on the same day', async () => {
|
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
const {
|
||||||
|
data: { createContributionLink: contributionLink },
|
||||||
|
} = await mutate({
|
||||||
|
mutation: createContributionLink,
|
||||||
|
variables: {
|
||||||
|
amount: new Decimal(5),
|
||||||
|
name: 'Daily Contribution Link',
|
||||||
|
memo: 'Thank you for contribute daily to the community',
|
||||||
|
cycle: 'DAILY',
|
||||||
|
validFrom: validFrom.toISOString(),
|
||||||
|
validTo: new Date(now.getFullYear() + 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
||||||
|
maxAmountPerMonth: new Decimal(200),
|
||||||
|
maxPerCycle: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
variables: {
|
variables: {
|
||||||
code: 'CL-' + (contributionLink ? contributionLink.code : ''),
|
code: 'CL-' + contributionLink.code,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
})
|
})
|
||||||
|
await resetEntity(DbContributionLink)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Contribution link is not valid yet', validFrom)
|
||||||
expect(logger.error).toBeCalledWith(
|
expect(logger.error).toBeCalledWith(
|
||||||
'Creation from contribution link was not successful',
|
'Creation from contribution link was not successful',
|
||||||
new Error('Contribution link already redeemed today'),
|
new Error('Contribution link is not valid yet'),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('after one day', () => {
|
it('throws error when contributionLink cycle is invalid', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
const now = new Date()
|
||||||
|
const {
|
||||||
|
data: { createContributionLink: contributionLink },
|
||||||
|
} = await mutate({
|
||||||
|
mutation: createContributionLink,
|
||||||
|
variables: {
|
||||||
|
amount: new Decimal(5),
|
||||||
|
name: 'Daily Contribution Link',
|
||||||
|
memo: 'Thank you for contribute daily to the community',
|
||||||
|
cycle: 'INVALID',
|
||||||
|
validFrom: new Date(now.getFullYear(), 0, 1).toISOString(),
|
||||||
|
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999).toISOString(),
|
||||||
|
maxAmountPerMonth: new Decimal(200),
|
||||||
|
maxPerCycle: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: redeemTransactionLink,
|
||||||
|
variables: {
|
||||||
|
code: 'CL-' + contributionLink.code,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
|
})
|
||||||
|
await resetEntity(DbContributionLink)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Contribution link has unknown cycle', 'INVALID')
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link has unknown cycle'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const validTo = new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59, 0)
|
||||||
|
it('throws error when link is no longer valid', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
const {
|
||||||
|
data: { createContributionLink: contributionLink },
|
||||||
|
} = await mutate({
|
||||||
|
mutation: createContributionLink,
|
||||||
|
variables: {
|
||||||
|
amount: new Decimal(5),
|
||||||
|
name: 'Daily Contribution Link',
|
||||||
|
memo: 'Thank you for contribute daily to the community',
|
||||||
|
cycle: 'DAILY',
|
||||||
|
validFrom: new Date(now.getFullYear() - 1, 0, 1).toISOString(),
|
||||||
|
validTo: validTo.toISOString(),
|
||||||
|
maxAmountPerMonth: new Decimal(200),
|
||||||
|
maxPerCycle: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: redeemTransactionLink,
|
||||||
|
variables: {
|
||||||
|
code: 'CL-' + contributionLink.code,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
|
})
|
||||||
|
await resetEntity(DbContributionLink)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Contribution link is no longer valid', validTo)
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link is no longer valid'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: have this test separated into a transactionLink and a contributionLink part
|
||||||
|
describe('redeem daily Contribution Link', () => {
|
||||||
|
const now = new Date()
|
||||||
|
let contributionLink: DbContributionLink | undefined
|
||||||
|
let contribution: UnconfirmedContribution | undefined
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: createContributionLink,
|
||||||
|
variables: {
|
||||||
|
amount: new Decimal(5),
|
||||||
|
name: 'Daily Contribution Link',
|
||||||
|
memo: 'Thank you for contribute daily to the community',
|
||||||
|
cycle: 'DAILY',
|
||||||
|
validFrom: new Date(now.getFullYear(), 0, 1).toISOString(),
|
||||||
|
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999).toISOString(),
|
||||||
|
maxAmountPerMonth: new Decimal(200),
|
||||||
|
maxPerCycle: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has a daily contribution link in the database', async () => {
|
||||||
|
const cls = await DbContributionLink.find()
|
||||||
|
expect(cls).toHaveLength(1)
|
||||||
|
contributionLink = cls[0]
|
||||||
|
expect(contributionLink).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
name: 'Daily Contribution Link',
|
||||||
|
memo: 'Thank you for contribute daily to the community',
|
||||||
|
validFrom: new Date(now.getFullYear(), 0, 1),
|
||||||
|
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 0),
|
||||||
|
cycle: 'DAILY',
|
||||||
|
maxPerCycle: 1,
|
||||||
|
totalMaxCountOfContribution: null,
|
||||||
|
maxAccountBalance: null,
|
||||||
|
minGapHours: null,
|
||||||
|
createdAt: expect.any(Date),
|
||||||
|
deletedAt: null,
|
||||||
|
code: expect.stringMatching(/^[0-9a-f]{24,24}$/),
|
||||||
|
linkEnabled: true,
|
||||||
|
amount: expect.decimalEqual(5),
|
||||||
|
maxAmountPerMonth: expect.decimalEqual(200),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('user has pending contribution of 1000 GDD', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
jest.useFakeTimers()
|
|
||||||
setTimeout(jest.fn(), 1000 * 60 * 60 * 24)
|
|
||||||
jest.runAllTimers()
|
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: login,
|
mutation: login,
|
||||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
})
|
})
|
||||||
|
const result = await mutate({
|
||||||
|
mutation: createContribution,
|
||||||
|
variables: {
|
||||||
|
amount: new Decimal(1000),
|
||||||
|
memo: 'I was brewing potions for the community the whole month',
|
||||||
|
creationDate: now.toISOString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
contribution = result.data.createContribution
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
it('does not allow the user to redeem the contribution link', async () => {
|
||||||
jest.useRealTimers()
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: redeemTransactionLink,
|
||||||
|
variables: {
|
||||||
|
code: 'CL-' + (contributionLink ? contributionLink.code : ''),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows the user to redeem the contribution link again', async () => {
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error(
|
||||||
|
'The amount to be created exceeds the amount still available for this month',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('user has no pending contributions that would not allow to redeem the link', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: contribution ? contribution.id : -1,
|
||||||
|
amount: new Decimal(800),
|
||||||
|
memo: 'I was brewing potions for the community the whole month',
|
||||||
|
creationDate: now.toISOString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows the user to redeem the contribution link', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
@ -473,6 +452,59 @@ describe('TransactionLinkResolver', () => {
|
|||||||
new Error('Contribution link already redeemed today'),
|
new Error('Contribution link already redeemed today'),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('after one day', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
jest.useFakeTimers()
|
||||||
|
setTimeout(jest.fn(), 1000 * 60 * 60 * 24)
|
||||||
|
jest.runAllTimers()
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.useRealTimers()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows the user to redeem the contribution link again', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: redeemTransactionLink,
|
||||||
|
variables: {
|
||||||
|
code: 'CL-' + (contributionLink ? contributionLink.code : ''),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
data: {
|
||||||
|
redeemTransactionLink: true,
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not allow the user to redeem the contribution link a second time on the same day', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: redeemTransactionLink,
|
||||||
|
variables: {
|
||||||
|
code: 'CL-' + (contributionLink ? contributionLink.code : ''),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link already redeemed today'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user