Merge branch 'master' into fix_docker_file_descriptions

This commit is contained in:
Ulf Gebhardt 2022-11-09 10:41:10 +01:00 committed by GitHub
commit 316334bd45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 151 additions and 41 deletions

View File

@ -17,6 +17,7 @@
<p class="h2 ml-5">{{ $t('contributionLink.contributionLinks') }}</p>
<contribution-link-form
:contributionLinkData="contributionLinkData"
:editContributionLink="editContributionLink"
@get-contribution-links="$emit('get-contribution-links')"
/>
</b-card>
@ -58,12 +59,14 @@ export default {
return {
visible: false,
contributionLinkData: {},
editContributionLink: false,
}
},
methods: {
editContributionLinkData(data) {
if (!this.visible) this.$root.$emit('bv::toggle::collapse', 'newContribution')
this.contributionLinkData = data
this.editContributionLink = true
},
},
}

View File

@ -9,6 +9,7 @@ global.alert = jest.fn()
const propsData = {
contributionLinkData: {},
editContributionLink: false,
}
const apolloMutateMock = jest.fn().mockResolvedValue()
@ -108,6 +109,7 @@ describe('ContributionLinkForm', () => {
cycle: 'ONCE',
maxPerCycle: 1,
maxAmountPerMonth: '0',
id: null,
},
})
})

View File

@ -102,7 +102,11 @@
</b-form-group>
-->
<div class="mt-6">
<b-button type="submit" variant="primary">{{ $t('contributionLink.create') }}</b-button>
<b-button type="submit" variant="primary">
{{
editContributionLink ? $t('contributionLink.saveChange') : $t('contributionLink.create')
}}
</b-button>
<b-button type="reset" variant="danger" @click.prevent="onReset">
{{ $t('contributionLink.clear') }}
</b-button>
@ -112,6 +116,8 @@
</template>
<script>
import { createContributionLink } from '@/graphql/createContributionLink.js'
import { updateContributionLink } from '@/graphql/updateContributionLink.js'
export default {
name: 'ContributionLinkForm',
props: {
@ -121,6 +127,7 @@ export default {
return {}
},
},
editContributionLink: { type: Boolean, required: true },
},
data() {
return {
@ -157,23 +164,24 @@ export default {
if (this.form.validFrom === null)
return this.toastError(this.$t('contributionLink.noStartDate'))
if (this.form.validTo === null) return this.toastError(this.$t('contributionLink.noEndDate'))
const variables = {
...this.form,
id: this.contributionLinkData.id ? this.contributionLinkData.id : null,
}
this.$apollo
.mutate({
mutation: createContributionLink,
variables: {
validFrom: this.form.validFrom,
validTo: this.form.validTo,
name: this.form.name,
amount: this.form.amount,
memo: this.form.memo,
cycle: this.form.cycle,
maxPerCycle: this.form.maxPerCycle,
maxAmountPerMonth: this.form.maxAmountPerMonth,
},
mutation: this.editContributionLink ? updateContributionLink : createContributionLink,
variables: variables,
})
.then((result) => {
this.link = result.data.createContributionLink.link
this.toastSuccess(this.link)
const link = this.editContributionLink
? result.data.updateContributionLink.link
: result.data.createContributionLink.link
this.toastSuccess(
this.editContributionLink ? this.$t('contributionLink.changeSaved') : link,
)
this.onReset()
this.$root.$emit('bv::toggle::collapse', 'newContribution')
this.$emit('get-contribution-links')

View File

@ -0,0 +1,40 @@
import gql from 'graphql-tag'
export const updateContributionLink = gql`
mutation (
$amount: Decimal!
$name: String!
$memo: String!
$cycle: String!
$validFrom: String
$validTo: String
$maxAmountPerMonth: Decimal
$maxPerCycle: Int! = 1
$id: Int!
) {
updateContributionLink(
amount: $amount
name: $name
memo: $memo
cycle: $cycle
validFrom: $validFrom
validTo: $validTo
maxAmountPerMonth: $maxAmountPerMonth
maxPerCycle: $maxPerCycle
id: $id
) {
id
amount
name
memo
code
link
createdAt
validFrom
validTo
maxAmountPerMonth
cycle
maxPerCycle
}
}
`

View File

@ -3,6 +3,7 @@
"back": "zurück",
"contributionLink": {
"amount": "Betrag",
"changeSaved": "Änderungen gespeichert",
"clear": "Löschen",
"contributionLinks": "Beitragslinks",
"create": "Anlegen",
@ -23,6 +24,7 @@
"once": "einmalig"
}
},
"saveChange": "Änderungen speichern",
"validFrom": "Startdatum",
"validTo": "Enddatum"
},

View File

@ -3,6 +3,7 @@
"back": "back",
"contributionLink": {
"amount": "Amount",
"changeSaved": "Changes saved",
"clear": "Clear",
"contributionLinks": "Contribution Links",
"create": "Create",
@ -23,6 +24,7 @@
"once": "once"
}
},
"saveChange": "Save Changes",
"validFrom": "Start-date",
"validTo": "End-Date"
},

View File

@ -139,6 +139,7 @@ describe('AdminResolver', () => {
describe('user to get a new role does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: setUserRole, variables: { userId: admin.id + 1, isAdmin: true } }),
).resolves.toEqual(
@ -195,6 +196,7 @@ describe('AdminResolver', () => {
describe('change role with error', () => {
describe('is own role', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: setUserRole, variables: { userId: admin.id, isAdmin: false } }),
).resolves.toEqual(
@ -211,6 +213,7 @@ describe('AdminResolver', () => {
describe('user has already role to be set', () => {
describe('to admin', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: setUserRole,
variables: { userId: user.id, isAdmin: true },
@ -231,6 +234,7 @@ describe('AdminResolver', () => {
describe('to usual user', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: setUserRole,
variables: { userId: user.id, isAdmin: false },
@ -307,6 +311,7 @@ describe('AdminResolver', () => {
describe('user to be deleted does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: deleteUser, variables: { userId: admin.id + 1 } }),
).resolves.toEqual(
@ -323,6 +328,7 @@ describe('AdminResolver', () => {
describe('delete self', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: deleteUser, variables: { userId: admin.id } }),
).resolves.toEqual(
@ -356,6 +362,7 @@ describe('AdminResolver', () => {
describe('delete deleted user', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: deleteUser, variables: { userId: user.id } }),
).resolves.toEqual(
@ -427,6 +434,7 @@ describe('AdminResolver', () => {
describe('user to be undelete does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: unDeleteUser, variables: { userId: admin.id + 1 } }),
).resolves.toEqual(
@ -447,6 +455,7 @@ describe('AdminResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: unDeleteUser, variables: { userId: user.id } }),
).resolves.toEqual(
@ -939,6 +948,7 @@ describe('AdminResolver', () => {
describe('user to create for does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: adminCreateContribution, variables }),
).resolves.toEqual(
@ -962,6 +972,7 @@ describe('AdminResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: adminCreateContribution, variables }),
).resolves.toEqual(
@ -987,6 +998,7 @@ describe('AdminResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: adminCreateContribution, variables }),
).resolves.toEqual(
@ -1013,6 +1025,7 @@ describe('AdminResolver', () => {
describe('date of creation is not a date string', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({ mutation: adminCreateContribution, variables }),
).resolves.toEqual(
@ -1034,6 +1047,7 @@ describe('AdminResolver', () => {
describe('date of creation is four months ago', () => {
it('throws an error', async () => {
jest.clearAllMocks()
const now = new Date()
variables.creationDate = new Date(
now.getFullYear(),
@ -1061,6 +1075,7 @@ describe('AdminResolver', () => {
describe('date of creation is in the future', () => {
it('throws an error', async () => {
jest.clearAllMocks()
const now = new Date()
variables.creationDate = new Date(
now.getFullYear(),
@ -1088,6 +1103,7 @@ describe('AdminResolver', () => {
describe('amount of creation is too high', () => {
it('throws an error', async () => {
jest.clearAllMocks()
variables.creationDate = new Date().toString()
await expect(
mutate({ mutation: adminCreateContribution, variables }),
@ -1213,6 +1229,7 @@ describe('AdminResolver', () => {
describe('user for creation to update does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminUpdateContribution,
@ -1242,6 +1259,7 @@ describe('AdminResolver', () => {
describe('user for creation to update is deleted', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminUpdateContribution,
@ -1267,6 +1285,7 @@ describe('AdminResolver', () => {
describe('creation does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminUpdateContribution,
@ -1292,6 +1311,7 @@ describe('AdminResolver', () => {
describe('user email does not match creation user', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminUpdateContribution,
@ -1326,6 +1346,7 @@ describe('AdminResolver', () => {
describe('creation update is not valid', () => {
// as this test has not clearly defined that date, it is a false positive
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminUpdateContribution,
@ -1502,6 +1523,7 @@ describe('AdminResolver', () => {
describe('adminDeleteContribution', () => {
describe('creation id does not exist', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminDeleteContribution,
@ -1538,6 +1560,7 @@ describe('AdminResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminDeleteContribution,
@ -1583,6 +1606,7 @@ describe('AdminResolver', () => {
describe('confirmContribution', () => {
describe('creation does not exits', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: confirmContribution,

View File

@ -74,6 +74,7 @@ describe('ContributionResolver', () => {
describe('input not valid', () => {
it('throws error when memo length smaller than 5 chars', async () => {
jest.clearAllMocks()
const date = new Date()
await expect(
mutate({
@ -92,10 +93,11 @@ describe('ContributionResolver', () => {
})
it('logs the error found', () => {
expect(logger.error).toBeCalledWith(`memo text is too short: memo.length=4 < (5)`)
expect(logger.error).toBeCalledWith(`memo text is too short: memo.length=4 < 5`)
})
it('throws error when memo length greater than 255 chars', async () => {
jest.clearAllMocks()
const date = new Date()
await expect(
mutate({
@ -114,10 +116,11 @@ describe('ContributionResolver', () => {
})
it('logs the error found', () => {
expect(logger.error).toBeCalledWith(`memo text is too long: memo.length=259 > (255)`)
expect(logger.error).toBeCalledWith(`memo text is too long: memo.length=259 > 255`)
})
it('throws error when creationDate not-valid', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: createContribution,
@ -144,6 +147,7 @@ describe('ContributionResolver', () => {
})
it('throws error when creationDate 3 month behind', async () => {
jest.clearAllMocks()
const date = new Date()
await expect(
mutate({
@ -375,6 +379,7 @@ describe('ContributionResolver', () => {
describe('wrong contribution id', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: updateContribution,
@ -399,6 +404,7 @@ describe('ContributionResolver', () => {
describe('Memo length smaller than 5 chars', () => {
it('throws error', async () => {
jest.clearAllMocks()
const date = new Date()
await expect(
mutate({
@ -418,12 +424,13 @@ describe('ContributionResolver', () => {
})
it('logs the error found', () => {
expect(logger.error).toBeCalledWith('memo text is too short: memo.length=4 < (5)')
expect(logger.error).toBeCalledWith('memo text is too short: memo.length=4 < 5')
})
})
describe('Memo length greater than 255 chars', () => {
it('throws error', async () => {
jest.clearAllMocks()
const date = new Date()
await expect(
mutate({
@ -443,7 +450,7 @@ describe('ContributionResolver', () => {
})
it('logs the error found', () => {
expect(logger.error).toBeCalledWith('memo text is too long: memo.length=259 > (255)')
expect(logger.error).toBeCalledWith('memo text is too long: memo.length=259 > 255')
})
})
@ -456,6 +463,7 @@ describe('ContributionResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: updateContribution,
@ -486,6 +494,7 @@ describe('ContributionResolver', () => {
describe('admin tries to update a user contribution', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: adminUpdateContribution,
@ -516,6 +525,7 @@ describe('ContributionResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: updateContribution,
@ -546,6 +556,7 @@ describe('ContributionResolver', () => {
describe('update creation to a date that is older than 3 months', () => {
it('throws an error', async () => {
jest.clearAllMocks()
const date = new Date()
await expect(
mutate({
@ -564,7 +575,7 @@ describe('ContributionResolver', () => {
)
})
it('logs the error found', () => {
it.skip('logs the error found', () => {
expect(logger.error).toBeCalledWith(
'No information for available creations with the given creationDate=',
'Invalid Date',
@ -830,6 +841,7 @@ describe('ContributionResolver', () => {
describe('User deletes already confirmed contribution', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: login,
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },

View File

@ -32,12 +32,12 @@ export class ContributionResolver {
@Ctx() context: Context,
): Promise<UnconfirmedContribution> {
if (memo.length > MEMO_MAX_CHARS) {
logger.error(`memo text is too long: memo.length=${memo.length} > (${MEMO_MAX_CHARS})`)
logger.error(`memo text is too long: memo.length=${memo.length} > ${MEMO_MAX_CHARS}`)
throw new Error(`memo text is too long (${MEMO_MAX_CHARS} characters maximum)`)
}
if (memo.length < MEMO_MIN_CHARS) {
logger.error(`memo text is too short: memo.length=${memo.length} < (${MEMO_MIN_CHARS})`)
logger.error(`memo text is too short: memo.length=${memo.length} < ${MEMO_MIN_CHARS}`)
throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`)
}
@ -172,12 +172,12 @@ export class ContributionResolver {
@Ctx() context: Context,
): Promise<UnconfirmedContribution> {
if (memo.length > MEMO_MAX_CHARS) {
logger.error(`memo text is too long: memo.length=${memo.length} > (${MEMO_MAX_CHARS}`)
logger.error(`memo text is too long: memo.length=${memo.length} > ${MEMO_MAX_CHARS}`)
throw new Error(`memo text is too long (${MEMO_MAX_CHARS} characters maximum)`)
}
if (memo.length < MEMO_MIN_CHARS) {
logger.error(`memo text is too short: memo.length=${memo.length} < (${MEMO_MIN_CHARS}`)
logger.error(`memo text is too short: memo.length=${memo.length} < ${MEMO_MIN_CHARS}`)
throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`)
}

View File

@ -67,6 +67,7 @@ describe('send coins', () => {
describe('unknown recipient', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: login,
variables: bobData,
@ -93,6 +94,7 @@ describe('send coins', () => {
describe('deleted recipient', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: login,
variables: peterData,
@ -125,6 +127,7 @@ describe('send coins', () => {
describe('recipient account not activated', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await mutate({
mutation: login,
variables: peterData,
@ -166,6 +169,7 @@ describe('send coins', () => {
describe('sender and recipient are the same', () => {
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: sendCoins,
@ -189,6 +193,7 @@ describe('send coins', () => {
describe('memo text is too long', () => {
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: sendCoins,
@ -212,6 +217,7 @@ describe('send coins', () => {
describe('memo text is too short', () => {
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: sendCoins,
@ -235,6 +241,7 @@ describe('send coins', () => {
describe('user has not enough GDD', () => {
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: sendCoins,
@ -260,6 +267,7 @@ describe('send coins', () => {
describe('sending negative amount', () => {
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: sendCoins,

View File

@ -514,18 +514,20 @@ describe('UserResolver', () => {
await mutate({ mutation: createUser, variables: createUserVariables })
const emailContact = await UserContact.findOneOrFail({ email: createUserVariables.email })
emailVerificationCode = emailContact.emailVerificationCode.toString()
result = await mutate({
mutation: setPassword,
variables: { code: emailVerificationCode, password: 'not-valid' },
})
})
afterAll(async () => {
await cleanDB()
})
it('throws an error', () => {
expect(result).toEqual(
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: setPassword,
variables: { code: emailVerificationCode, password: 'not-valid' },
}),
).toEqual(
expect.objectContaining({
errors: [
new GraphQLError(
@ -544,18 +546,20 @@ describe('UserResolver', () => {
describe('no valid optin code', () => {
beforeAll(async () => {
await mutate({ mutation: createUser, variables: createUserVariables })
result = await mutate({
mutation: setPassword,
variables: { code: 'not valid', password: 'Aa12345_' },
})
})
afterAll(async () => {
await cleanDB()
})
it('throws an error', () => {
expect(result).toEqual(
it('throws an error', async () => {
jest.clearAllMocks()
expect(
await mutate({
mutation: setPassword,
variables: { code: 'not valid', password: 'Aa12345_' },
}),
).toEqual(
expect.objectContaining({
errors: [new GraphQLError('Could not login with emailVerificationCode')],
}),
@ -582,13 +586,9 @@ describe('UserResolver', () => {
})
describe('no users in database', () => {
beforeAll(async () => {
it('throws an error', async () => {
jest.clearAllMocks()
result = await mutate({ mutation: login, variables })
})
it('throws an error', () => {
expect(result).toEqual(
expect(await mutate({ mutation: login, variables })).toEqual(
expect.objectContaining({
errors: [new GraphQLError('No user with this credentials')],
}),
@ -666,6 +666,7 @@ describe('UserResolver', () => {
describe('logout', () => {
describe('unauthenticated', () => {
it('throws an error', async () => {
jest.clearAllMocks()
resetToken()
await expect(mutate({ mutation: logout })).resolves.toEqual(
expect.objectContaining({
@ -704,6 +705,7 @@ describe('UserResolver', () => {
describe('verifyLogin', () => {
describe('unauthenticated', () => {
it('throws an error', async () => {
jest.clearAllMocks()
resetToken()
await expect(query({ query: verifyLogin })).resolves.toEqual(
expect.objectContaining({
@ -723,6 +725,7 @@ describe('UserResolver', () => {
})
it('throws an error', async () => {
jest.clearAllMocks()
resetToken()
await expect(query({ query: verifyLogin })).resolves.toEqual(
expect.objectContaining({
@ -883,6 +886,7 @@ describe('UserResolver', () => {
describe('wrong optin code', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
query({ query: queryOptIn, variables: { optIn: 'not-valid' } }),
).resolves.toEqual(
@ -919,6 +923,7 @@ describe('UserResolver', () => {
describe('updateUserInfos', () => {
describe('unauthenticated', () => {
it('throws an error', async () => {
jest.clearAllMocks()
resetToken()
await expect(mutate({ mutation: updateUserInfos })).resolves.toEqual(
expect.objectContaining({
@ -976,6 +981,7 @@ describe('UserResolver', () => {
describe('language is not valid', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: updateUserInfos,
@ -998,6 +1004,7 @@ describe('UserResolver', () => {
describe('password', () => {
describe('wrong old password', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: updateUserInfos,
@ -1020,6 +1027,7 @@ describe('UserResolver', () => {
describe('invalid new password', () => {
it('throws an error', async () => {
jest.clearAllMocks()
await expect(
mutate({
mutation: updateUserInfos,
@ -1108,6 +1116,7 @@ describe('UserResolver', () => {
describe('searchAdminUsers', () => {
describe('unauthenticated', () => {
it('throws an error', async () => {
jest.clearAllMocks()
resetToken()
await expect(mutate({ mutation: searchAdminUsers })).resolves.toEqual(
expect.objectContaining({