mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
Merge branch 'master' into message-type-admin
This commit is contained in:
commit
4771d2a0ca
@ -73,8 +73,8 @@ describe('ContributionMessagesFormular', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('emitted "update-state" with data', async () => {
|
||||
expect(wrapper.emitted('update-state')).toEqual(
|
||||
it('emitted "update-status" with data', async () => {
|
||||
expect(wrapper.emitted('update-status')).toEqual(
|
||||
expect.arrayContaining([expect.arrayContaining([42])]),
|
||||
)
|
||||
})
|
||||
|
||||
@ -54,7 +54,7 @@ export default {
|
||||
})
|
||||
.then((result) => {
|
||||
this.$emit('get-list-contribution-messages', this.contributionId)
|
||||
this.$emit('update-state', this.contributionId)
|
||||
this.$emit('update-status', this.contributionId)
|
||||
this.form.text = ''
|
||||
this.toastSuccess(this.$t('message.request'))
|
||||
this.loading = false
|
||||
|
||||
@ -10,7 +10,7 @@ describe('ContributionMessagesList', () => {
|
||||
|
||||
const propsData = {
|
||||
contributionId: 42,
|
||||
contributionState: 'PENDING',
|
||||
contributionStatus: 'PENDING',
|
||||
}
|
||||
|
||||
const mocks = {
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
</div>
|
||||
</b-container>
|
||||
|
||||
<div v-if="contributionState === 'PENDING' || contributionState === 'IN_PROGRESS'">
|
||||
<div v-if="contributionStatus === 'PENDING' || contributionStatus === 'IN_PROGRESS'">
|
||||
<contribution-messages-formular
|
||||
:contributionId="contributionId"
|
||||
@get-list-contribution-messages="getListContributionMessages"
|
||||
@update-state="updateState"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -31,7 +31,7 @@ export default {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
contributionState: {
|
||||
contributionStatus: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
@ -58,8 +58,8 @@ export default {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
updateState(id) {
|
||||
this.$emit('update-state', id)
|
||||
updateStatus(id) {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
@ -18,7 +18,7 @@ describe('ContributionMessagesListItem', () => {
|
||||
describe('if message author has moderator role', () => {
|
||||
const propsData = {
|
||||
contributionId: 42,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
message: {
|
||||
id: 111,
|
||||
message: 'Lorem ipsum?',
|
||||
@ -79,7 +79,7 @@ describe('ContributionMessagesListItem', () => {
|
||||
describe('if message author does not have moderator role', () => {
|
||||
const propsData = {
|
||||
contributionId: 42,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
message: {
|
||||
id: 113,
|
||||
message: 'Asda sdad ad asdasd, das Ass das Das. ',
|
||||
|
||||
@ -28,7 +28,7 @@ const defaultData = () => {
|
||||
memo: 'Danke für alles',
|
||||
date: new Date(),
|
||||
moderator: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
deniedBy: null,
|
||||
@ -50,7 +50,7 @@ const defaultData = () => {
|
||||
memo: 'Gut Ergattert',
|
||||
date: new Date(),
|
||||
moderator: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
deniedBy: null,
|
||||
|
||||
@ -34,8 +34,8 @@
|
||||
{{ $t('help.transactionlist.confirmed') }}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t('transactionlist.state') }} {{ $t('math.equals') }}
|
||||
{{ $t('help.transactionlist.state') }}
|
||||
{{ $t('transactionlist.status') }} {{ $t('math.equals') }}
|
||||
{{ $t('help.transactionlist.status') }}
|
||||
</div>
|
||||
</b-collapse>
|
||||
</div>
|
||||
@ -78,8 +78,8 @@ export default {
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'state',
|
||||
label: this.$t('transactionlist.state'),
|
||||
key: 'status',
|
||||
label: this.$t('transactionlist.status'),
|
||||
},
|
||||
{
|
||||
key: 'amount',
|
||||
|
||||
@ -131,13 +131,13 @@ describe('OpenCreationsTable', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('call updateState', () => {
|
||||
describe('call updateStatus', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.vm.updateState(4)
|
||||
wrapper.vm.updateStatus(4)
|
||||
})
|
||||
|
||||
it('emits update-state', () => {
|
||||
expect(wrapper.vm.$root.$emit('update-state', 4)).toBeTruthy()
|
||||
it('emits update-status', () => {
|
||||
expect(wrapper.vm.$root.$emit('update-status', 4)).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
stacked="md"
|
||||
:tbody-tr-class="rowClass"
|
||||
>
|
||||
<template #cell(state)="row">
|
||||
<b-icon :icon="getStatusIcon(row.item.state)"></b-icon>
|
||||
<template #cell(status)="row">
|
||||
<b-icon :icon="getStatusIcon(row.item.status)"></b-icon>
|
||||
</template>
|
||||
<template #cell(bookmark)="row">
|
||||
<div v-if="!myself(row.item)">
|
||||
@ -39,12 +39,12 @@
|
||||
<b-button v-else @click="rowToggleDetails(row, 0)">
|
||||
<b-icon icon="chat-dots"></b-icon>
|
||||
<b-icon
|
||||
v-if="row.item.state === 'PENDING' && row.item.messagesCount > 0"
|
||||
v-if="row.item.status === 'PENDING' && row.item.messagesCount > 0"
|
||||
icon="exclamation-circle-fill"
|
||||
variant="warning"
|
||||
></b-icon>
|
||||
<b-icon
|
||||
v-if="row.item.state === 'IN_PROGRESS' && row.item.messagesCount > 0"
|
||||
v-if="row.item.status === 'IN_PROGRESS' && row.item.messagesCount > 0"
|
||||
icon="question-diamond"
|
||||
variant="warning"
|
||||
class="pl-1"
|
||||
@ -102,8 +102,8 @@
|
||||
<div v-else>
|
||||
<contribution-messages-list
|
||||
:contributionId="row.item.id"
|
||||
:contributionState="row.item.state"
|
||||
@update-state="updateState"
|
||||
:contributionStatus="row.item.status"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -154,15 +154,21 @@ export default {
|
||||
},
|
||||
rowClass(item, type) {
|
||||
if (!item || type !== 'row') return
|
||||
if (item.state === 'CONFIRMED') return 'table-success'
|
||||
if (item.state === 'DENIED') return 'table-warning'
|
||||
if (item.state === 'DELETED') return 'table-danger'
|
||||
if (item.state === 'IN_PROGRESS') return 'table-primary'
|
||||
if (item.state === 'PENDING') return 'table-primary'
|
||||
if (item.status === 'CONFIRMED') return 'table-success'
|
||||
if (item.status === 'DENIED') return 'table-warning'
|
||||
if (item.status === 'DELETED') return 'table-danger'
|
||||
if (item.status === 'IN_PROGRESS') return 'table-primary'
|
||||
if (item.status === 'PENDING') return 'table-primary'
|
||||
},
|
||||
updateState(id) {
|
||||
this.$emit('update-state', id)
|
||||
updateStatus(id) {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.btn-warning {
|
||||
background-color: #e1a908;
|
||||
border-color: #e1a908;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -26,7 +26,7 @@ export const adminListContributions = gql`
|
||||
contributionDate
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
state
|
||||
status
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
"transactionlist": {
|
||||
"confirmed": "Wann wurde es von einem Moderator / Admin bestätigt.",
|
||||
"periods": "Für welchen Zeitraum wurde vom Mitglied eingereicht.",
|
||||
"state": "[PENDING = eingereicht, DELETED = gelöscht, IN_PROGRESS = im Dialog mit Moderator, DENIED = abgelehnt, CONFIRMED = bestätigt]",
|
||||
"status": "[PENDING = eingereicht, DELETED = gelöscht, IN_PROGRESS = im Dialog mit Moderator, DENIED = abgelehnt, CONFIRMED = bestätigt]",
|
||||
"submitted": "Wann wurde es vom Mitglied eingereicht"
|
||||
}
|
||||
},
|
||||
@ -184,7 +184,7 @@
|
||||
"confirmed": "Bestätigt",
|
||||
"memo": "Nachricht",
|
||||
"period": "Zeitraum",
|
||||
"state": "Status",
|
||||
"status": "Status",
|
||||
"submitted": "Eingereicht",
|
||||
"title": "Alle geschöpften Transaktionen für den Nutzer"
|
||||
},
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
"transactionlist": {
|
||||
"confirmed": "When was it confirmed by a moderator / admin.",
|
||||
"periods": "For what period was it submitted by the member.",
|
||||
"state": "[PENDING = submitted, DELETED = deleted, IN_PROGRESS = in dialogue with moderator, DENIED = rejected, CONFIRMED = confirmed]",
|
||||
"status": "[PENDING = submitted, DELETED = deleted, IN_PROGRESS = in dialogue with moderator, DENIED = rejected, CONFIRMED = confirmed]",
|
||||
"submitted": "When was it submitted by the member"
|
||||
}
|
||||
},
|
||||
@ -184,7 +184,7 @@
|
||||
"confirmed": "Confirmed",
|
||||
"memo": "Message",
|
||||
"period": "Period",
|
||||
"state": "State",
|
||||
"status": "State",
|
||||
"submitted": "Submitted",
|
||||
"title": "All creation-transactions for the user"
|
||||
},
|
||||
|
||||
@ -51,7 +51,7 @@ const defaultData = () => {
|
||||
memo: 'Danke für alles',
|
||||
date: new Date(),
|
||||
moderator: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
deniedBy: null,
|
||||
@ -73,7 +73,7 @@ const defaultData = () => {
|
||||
memo: 'Gut Ergattert',
|
||||
date: new Date(),
|
||||
moderator: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
deniedBy: null,
|
||||
@ -451,12 +451,12 @@ describe('CreationConfirm', () => {
|
||||
|
||||
describe('update status', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.findComponent({ name: 'OpenCreationsTable' }).vm.$emit('update-state', 2)
|
||||
await wrapper.findComponent({ name: 'OpenCreationsTable' }).vm.$emit('update-status', 2)
|
||||
})
|
||||
|
||||
it('updates the status', () => {
|
||||
expect(wrapper.vm.items.find((obj) => obj.id === 2).messagesCount).toBe(1)
|
||||
expect(wrapper.vm.items.find((obj) => obj.id === 2).state).toBe('IN_PROGRESS')
|
||||
expect(wrapper.vm.items.find((obj) => obj.id === 2).status).toBe('IN_PROGRESS')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
:items="items"
|
||||
:fields="fields"
|
||||
@show-overlay="showOverlay"
|
||||
@update-state="updateStatus"
|
||||
@update-status="updateStatus"
|
||||
@update-contributions="$apollo.queries.ListAllContributions.refetch()"
|
||||
/>
|
||||
|
||||
@ -187,7 +187,7 @@ export default {
|
||||
},
|
||||
updateStatus(id) {
|
||||
this.items.find((obj) => obj.id === id).messagesCount++
|
||||
this.items.find((obj) => obj.id === id).state = 'IN_PROGRESS'
|
||||
this.items.find((obj) => obj.id === id).status = 'IN_PROGRESS'
|
||||
},
|
||||
formatDateOrDash(value) {
|
||||
return value ? this.$d(new Date(value), 'short') : '—'
|
||||
@ -331,7 +331,7 @@ export default {
|
||||
],
|
||||
[
|
||||
// all contributions
|
||||
{ key: 'state', label: this.$t('status') },
|
||||
{ key: 'status', label: this.$t('status') },
|
||||
{ key: 'firstName', label: this.$t('firstname') },
|
||||
{ key: 'lastName', label: this.$t('lastname') },
|
||||
{
|
||||
|
||||
@ -43,7 +43,7 @@ const defaultData = () => {
|
||||
memo: 'Danke für alles',
|
||||
date: new Date(),
|
||||
moderatorId: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
deniedBy: null,
|
||||
@ -65,7 +65,7 @@ const defaultData = () => {
|
||||
memo: 'Gut Ergattert',
|
||||
date: new Date(),
|
||||
moderatorId: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
deniedBy: null,
|
||||
|
||||
@ -21,6 +21,11 @@ KLICKTIPP_PASSWORD=secret321
|
||||
KLICKTIPP_APIKEY_DE=SomeFakeKeyDE
|
||||
KLICKTIPP_APIKEY_EN=SomeFakeKeyEN
|
||||
|
||||
# IOTA
|
||||
IOTA=false
|
||||
IOTA_API_URL=https://chrysalis-nodes.iota.org
|
||||
IOTA_COMMUNITY_ALIAS=GRADIDO: TestHelloWelt1
|
||||
|
||||
# Community
|
||||
COMMUNITY_NAME=Gradido Entwicklung
|
||||
COMMUNITY_URL=http://localhost/
|
||||
|
||||
@ -22,6 +22,11 @@ KLICKTIPP_PASSWORD=$KLICKTIPP_PASSWORD
|
||||
KLICKTIPP_APIKEY_DE=$KLICKTIPP_APIKEY_DE
|
||||
KLICKTIPP_APIKEY_EN=$KLICKTIPP_APIKEY_EN
|
||||
|
||||
# IOTA
|
||||
IOTA=$IOTA
|
||||
IOTA_API_URL=https://chrysalis-nodes.iota.org
|
||||
IOTA_COMMUNITY_ALIAS=GRADIDO: TestHelloWelt1
|
||||
|
||||
# Community
|
||||
COMMUNITY_NAME=$COMMUNITY_NAME
|
||||
COMMUNITY_URL=$COMMUNITY_URL
|
||||
|
||||
@ -197,6 +197,9 @@ module.exports = {
|
||||
{
|
||||
files: ['*.test.ts'],
|
||||
plugins: ['jest'],
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
rules: {
|
||||
'jest/no-disabled-tests': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
|
||||
@ -33,6 +33,8 @@ LABEL maintainer="support@gradido.net"
|
||||
# Install Additional Software
|
||||
## install: git
|
||||
#RUN apk --no-cache add git
|
||||
# Install Build Tool for Rust for @iota/client
|
||||
RUN apk add --no-cache rust cargo python3 make g++
|
||||
|
||||
# Settings
|
||||
## Expose Container Port
|
||||
@ -92,6 +94,9 @@ CMD /bin/sh -c "yarn run start"
|
||||
##################################################################################
|
||||
FROM base as production
|
||||
|
||||
# Remove Build Tool for Rust else they would bloat the image unneccessary
|
||||
RUN apk del rust cargo python3 make g++
|
||||
|
||||
# Copy "binary"-files from build image
|
||||
COPY --from=build ${DOCKER_WORKDIR}/build ./build
|
||||
COPY --from=build ${DOCKER_WORKDIR}/../database/build ../database/build
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
"locales": "scripts/sort.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iota/client": "^2",
|
||||
"apollo-server-express": "^2.25.2",
|
||||
"await-semaphore": "^0.1.3",
|
||||
"axios": "^0.21.1",
|
||||
|
||||
43
backend/src/apis/IotaConnector.test.ts
Normal file
43
backend/src/apis/IotaConnector.test.ts
Normal file
@ -0,0 +1,43 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { IotaClientSingleton } from '@/apis/IotaConnector'
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
CONFIG.IOTA = true
|
||||
CONFIG.IOTA_COMMUNITY_ALIAS = 'GRADIDO: TestHelloWelt1'
|
||||
CONFIG.IOTA_API_URL = 'https://chrysalis-nodes.iota.org'
|
||||
|
||||
describe('apis/IotaConnector/enabled', () => {
|
||||
describe('Hello World', () => {
|
||||
const now = new Date()
|
||||
let messageId: string
|
||||
const messageString = 'Hello World - ' + now.toString()
|
||||
const messageHexString = Buffer.from(messageString, 'utf8').toString('hex')
|
||||
const indexHexString = Buffer.from(CONFIG.IOTA_COMMUNITY_ALIAS, 'utf8').toString('hex')
|
||||
it('sends hello world message to iota tangle', async () => {
|
||||
const iotaMessage = await IotaClientSingleton.getInstance()?.sendDataMessage(messageString)
|
||||
expect(iotaMessage).toMatchObject({
|
||||
message: {
|
||||
payload: {
|
||||
data: messageHexString,
|
||||
index: indexHexString,
|
||||
},
|
||||
},
|
||||
messageId: expect.any(String),
|
||||
})
|
||||
messageId =
|
||||
iotaMessage?.messageId ?? '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710'
|
||||
})
|
||||
it('receives hello world message from iota tangle by message id', async () => {
|
||||
const iotaMessage = await IotaClientSingleton.getInstance()?.getMessage(messageId)
|
||||
expect(iotaMessage).toMatchObject({
|
||||
message: {
|
||||
payload: {
|
||||
data: messageHexString,
|
||||
index: indexHexString,
|
||||
},
|
||||
},
|
||||
messageId,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
93
backend/src/apis/IotaConnector.ts
Normal file
93
backend/src/apis/IotaConnector.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import { Client, ClientBuilder } from '@iota/client'
|
||||
import { MessageWrapper } from '@iota/client/lib/types'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
// Source: https://refactoring.guru/design-patterns/singleton/typescript/example
|
||||
// and ../federation/client/FederationClientFactory.ts
|
||||
/**
|
||||
* A Singleton class defines the `getInstance` method that lets clients access
|
||||
* the unique singleton instance.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||
class IotaClientSingleton {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
private static instance: IotaClientSingleton
|
||||
private client: Client
|
||||
/**
|
||||
* The Singleton's constructor should always be private to prevent direct
|
||||
* construction calls with the `new` operator.
|
||||
*/
|
||||
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
/**
|
||||
* The static method that controls the access to the singleton instance.
|
||||
*
|
||||
* This implementation let you subclass the Singleton class while keeping
|
||||
* just one instance of each subclass around.
|
||||
*/
|
||||
public static getInstance(): IotaClientSingleton | undefined {
|
||||
if (!CONFIG.IOTA || !CONFIG.IOTA_API_URL) {
|
||||
logger.info(`Iota are disabled via config...`)
|
||||
return
|
||||
}
|
||||
if (!IotaClientSingleton.instance) {
|
||||
IotaClientSingleton.instance = new IotaClientSingleton()
|
||||
try {
|
||||
IotaClientSingleton.instance.client = new ClientBuilder().node(CONFIG.IOTA_API_URL).build()
|
||||
} catch (e) {
|
||||
logger.error("couldn't connect to iota")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return IotaClientSingleton.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* send data message onto iota tangle
|
||||
* use CONFIG.IOTA_COMMUNITY_ALIAS for index
|
||||
* @param {string} message - the message as utf based string, will be converted to hex automatically from @iota/client
|
||||
* @return {Promise<MessageWrapper>} the iota message typed
|
||||
*/
|
||||
public sendDataMessage(message: string): Promise<MessageWrapper> {
|
||||
return this.client.message().index(CONFIG.IOTA_COMMUNITY_ALIAS).data(message).submit()
|
||||
}
|
||||
|
||||
/**
|
||||
* receive message for known message id from iota tangle
|
||||
* @param {string} messageId - as hex string
|
||||
* @return {Promise<MessageWrapper>} the iota message typed
|
||||
*/
|
||||
public getMessage(messageId: string): Promise<MessageWrapper> {
|
||||
return this.client.getMessage().data(messageId)
|
||||
}
|
||||
}
|
||||
|
||||
export { IotaClientSingleton }
|
||||
|
||||
/**
|
||||
* example for message:
|
||||
```json
|
||||
{
|
||||
message: {
|
||||
networkId: '1454675179895816119',
|
||||
parentMessageIds: [
|
||||
'5f30efecca59fdfef7c103e85ef691b2b1dc474e9eae9056888a6d58605083e7',
|
||||
'77cef2fb405daedcd7469e009bb87a6d9a4840e618cdb599cd21a30a9fec88dc',
|
||||
'7d2cfb39f40585ba568a29ad7e85c1478b2584496eb736d4001ac344f6a6cacf',
|
||||
'c66da602874220dfa26925f6be540d37c0084d37cd04726fcc5be9d80b36f850'
|
||||
],
|
||||
payload: {
|
||||
type: 2,
|
||||
index: '4752414449444f3a205465737448656c6c6f57656c7431',
|
||||
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429'
|
||||
},
|
||||
nonce: '13835058055282465157'
|
||||
},
|
||||
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710'
|
||||
}
|
||||
```
|
||||
*/
|
||||
26
backend/src/apis/IotaConnector_disabled.test.ts
Normal file
26
backend/src/apis/IotaConnector_disabled.test.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { IotaClientSingleton } from '@/apis/IotaConnector'
|
||||
import { CONFIG } from '@/config'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
describe('apis/IotaConnector/disabled', () => {
|
||||
beforeEach(() => {
|
||||
CONFIG.IOTA = false
|
||||
})
|
||||
it('getInstance return undefined if iota is disabled', () => {
|
||||
const spyLog = jest.spyOn(logger, 'info')
|
||||
expect(IotaClientSingleton.getInstance()).toBeUndefined()
|
||||
expect(spyLog).toHaveBeenCalledWith('Iota are disabled via config...')
|
||||
})
|
||||
})
|
||||
|
||||
describe('apis/IotaConnector/invalidIotaUrl', () => {
|
||||
beforeEach(() => {
|
||||
CONFIG.IOTA = true
|
||||
CONFIG.IOTA_API_URL = 'invalidUrl'
|
||||
})
|
||||
it('log "couldn\'t connect to iota"', () => {
|
||||
const spyLog = jest.spyOn(logger, 'error')
|
||||
expect(IotaClientSingleton.getInstance()).toBeUndefined()
|
||||
expect(spyLog).toHaveBeenCalledWith("couldn't connect to iota")
|
||||
})
|
||||
})
|
||||
@ -19,7 +19,7 @@ const constants = {
|
||||
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
|
||||
CONFIG_VERSION: {
|
||||
DEFAULT: 'DEFAULT',
|
||||
EXPECTED: 'v15.2023-02-07',
|
||||
EXPECTED: 'v16.2023-06-08',
|
||||
CURRENT: '',
|
||||
},
|
||||
}
|
||||
@ -51,6 +51,12 @@ const klicktipp = {
|
||||
KLICKTIPP_APIKEY_EN: process.env.KLICKTIPP_APIKEY_EN ?? 'SomeFakeKeyEN',
|
||||
}
|
||||
|
||||
const iota = {
|
||||
IOTA: process.env.IOTA === 'true' || false,
|
||||
IOTA_API_URL: process.env.IOTA_API_URL ?? 'https://chrysalis-nodes.iota.org',
|
||||
IOTA_COMMUNITY_ALIAS: process.env.IOTA_COMMUNITY_ALIAS ?? 'GRADIDO: TestHelloWelt1',
|
||||
}
|
||||
|
||||
const community = {
|
||||
COMMUNITY_NAME: process.env.COMMUNITY_NAME ?? 'Gradido Entwicklung',
|
||||
COMMUNITY_URL: process.env.COMMUNITY_URL ?? 'http://localhost/',
|
||||
@ -126,6 +132,7 @@ export const CONFIG = {
|
||||
...server,
|
||||
...database,
|
||||
...klicktipp,
|
||||
...iota,
|
||||
...community,
|
||||
...email,
|
||||
...loginServer,
|
||||
|
||||
@ -15,7 +15,7 @@ export class Contribution {
|
||||
this.confirmedAt = contribution.confirmedAt
|
||||
this.confirmedBy = contribution.confirmedBy
|
||||
this.contributionDate = contribution.contributionDate
|
||||
this.state = contribution.contributionStatus
|
||||
this.status = contribution.contributionStatus
|
||||
this.messagesCount = contribution.messages ? contribution.messages.length : 0
|
||||
this.deniedAt = contribution.deniedAt
|
||||
this.deniedBy = contribution.deniedBy
|
||||
@ -68,7 +68,7 @@ export class Contribution {
|
||||
messagesCount: number
|
||||
|
||||
@Field(() => String)
|
||||
state: string
|
||||
status: string
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
moderatorId: number | null
|
||||
|
||||
@ -10,7 +10,7 @@ import { GdtEntry } from './GdtEntry'
|
||||
@ObjectType()
|
||||
export class GdtEntryList {
|
||||
constructor(json: any) {
|
||||
this.state = json.state
|
||||
this.status = json.state
|
||||
this.count = json.count
|
||||
this.gdtEntries = json.gdtEntries ? json.gdtEntries.map((json: any) => new GdtEntry(json)) : []
|
||||
this.gdtSum = json.gdtSum
|
||||
@ -18,7 +18,7 @@ export class GdtEntryList {
|
||||
}
|
||||
|
||||
@Field(() => String)
|
||||
state: string
|
||||
status: string
|
||||
|
||||
@Field(() => Int)
|
||||
count: number
|
||||
|
||||
@ -16,7 +16,7 @@ export class UnconfirmedContribution {
|
||||
this.email = user ? user.emailContact.email : ''
|
||||
this.moderator = contribution.moderatorId
|
||||
this.creation = creations
|
||||
this.state = contribution.contributionStatus
|
||||
this.status = contribution.contributionStatus
|
||||
this.messageCount = contribution.messages ? contribution.messages.length : 0
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ export class UnconfirmedContribution {
|
||||
creation: Decimal[]
|
||||
|
||||
@Field(() => String)
|
||||
state: string
|
||||
status: string
|
||||
|
||||
@Field(() => Int)
|
||||
messageCount: number
|
||||
|
||||
@ -1092,29 +1092,29 @@ describe('ContributionResolver', () => {
|
||||
contributionCount: 4,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.not.objectContaining({
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: pendingContribution.data.createContribution.id,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
memo: 'Test PENDING contribution update',
|
||||
amount: '10',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: contributionToDeny.data.createContribution.id,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Test contribution to deny',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: contributionToDelete.data.createContribution.id,
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
memo: 'Test contribution to delete',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: inProgressContribution.data.createContribution.id,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
memo: 'Test IN_PROGRESS contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
@ -1223,47 +1223,47 @@ describe('ContributionResolver', () => {
|
||||
contributionCount: 7,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: '100',
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
id: contributionToConfirm.data.createContribution.id,
|
||||
memo: 'Test contribution to confirm',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: pendingContribution.data.createContribution.id,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
memo: 'Test PENDING contribution update',
|
||||
amount: '10',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: contributionToDeny.data.createContribution.id,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Test contribution to deny',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: inProgressContribution.data.createContribution.id,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
memo: 'Test IN_PROGRESS contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: bibiCreatedContribution.id,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
@ -1288,47 +1288,47 @@ describe('ContributionResolver', () => {
|
||||
contributionCount: 7,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: '100',
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
id: contributionToConfirm.data.createContribution.id,
|
||||
memo: 'Test contribution to confirm',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: pendingContribution.data.createContribution.id,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
memo: 'Test PENDING contribution update',
|
||||
amount: '10',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: contributionToDeny.data.createContribution.id,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Test contribution to deny',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: inProgressContribution.data.createContribution.id,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
memo: 'Test IN_PROGRESS contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: bibiCreatedContribution.id,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
@ -1353,47 +1353,47 @@ describe('ContributionResolver', () => {
|
||||
contributionCount: 7,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: '100',
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
id: contributionToConfirm.data.createContribution.id,
|
||||
memo: 'Test contribution to confirm',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: pendingContribution.data.createContribution.id,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
memo: 'Test PENDING contribution update',
|
||||
amount: '10',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: contributionToDeny.data.createContribution.id,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Test contribution to deny',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: inProgressContribution.data.createContribution.id,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
memo: 'Test IN_PROGRESS contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: bibiCreatedContribution.id,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
@ -1419,33 +1419,33 @@ describe('ContributionResolver', () => {
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: '100',
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
id: contributionToConfirm.data.createContribution.id,
|
||||
memo: 'Test contribution to confirm',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: bibiCreatedContribution.id,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
@ -1468,20 +1468,20 @@ describe('ContributionResolver', () => {
|
||||
contributionCount: 1,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.not.objectContaining({
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: pendingContribution.data.createContribution.id,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
memo: 'Test PENDING contribution update',
|
||||
amount: '10',
|
||||
}),
|
||||
@ -1506,20 +1506,20 @@ describe('ContributionResolver', () => {
|
||||
contributionCount: 1,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.not.objectContaining({
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: inProgressContribution.data.createContribution.id,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
memo: 'Test IN_PROGRESS contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
@ -1545,27 +1545,27 @@ describe('ContributionResolver', () => {
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: contributionToDeny.data.createContribution.id,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Test contribution to deny',
|
||||
amount: '100',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
@ -1608,36 +1608,36 @@ describe('ContributionResolver', () => {
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: '100',
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
id: contributionToConfirm.data.createContribution.id,
|
||||
memo: 'Test contribution to confirm',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: pendingContribution.data.createContribution.id,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
memo: 'Test PENDING contribution update',
|
||||
amount: '10',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: bibiCreatedContribution.id,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
memo: 'Whatever contribution',
|
||||
amount: '166',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
@ -2691,7 +2691,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Herzlich Willkommen bei Gradido liebe Bibi!',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(50),
|
||||
@ -2700,7 +2700,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Herzlich Willkommen bei Gradido liebe Bibi!',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(450),
|
||||
@ -2709,7 +2709,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Herzlich Willkommen bei Gradido liebe Bibi!',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(400),
|
||||
@ -2718,7 +2718,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Lustig',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
messagesCount: 0,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(100),
|
||||
@ -2727,7 +2727,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'der Baumeister',
|
||||
memo: 'Confirmed Contribution',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(100),
|
||||
@ -2736,7 +2736,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Lustig',
|
||||
memo: 'Test env contribution',
|
||||
messagesCount: 0,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(200),
|
||||
@ -2745,7 +2745,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Aktives Grundeinkommen',
|
||||
messagesCount: 0,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(200),
|
||||
@ -2754,7 +2754,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Lustig',
|
||||
memo: 'Das war leider zu Viel!',
|
||||
messagesCount: 0,
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(166),
|
||||
@ -2763,7 +2763,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Hotzenplotz',
|
||||
memo: 'Whatever contribution',
|
||||
messagesCount: 0,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(166),
|
||||
@ -2772,7 +2772,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Hotzenplotz',
|
||||
memo: 'Whatever contribution',
|
||||
messagesCount: 0,
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(166),
|
||||
@ -2781,7 +2781,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Hotzenplotz',
|
||||
memo: 'Whatever contribution',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(100),
|
||||
@ -2790,7 +2790,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Test contribution to delete',
|
||||
messagesCount: 0,
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(100),
|
||||
@ -2799,7 +2799,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Test contribution to deny',
|
||||
messagesCount: 0,
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(100),
|
||||
@ -2808,7 +2808,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Test contribution to confirm',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(100),
|
||||
@ -2817,7 +2817,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Test IN_PROGRESS contribution',
|
||||
messagesCount: 1,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(10),
|
||||
@ -2826,7 +2826,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Test PENDING contribution update',
|
||||
messagesCount: 1,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(1000),
|
||||
@ -2835,7 +2835,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Bloxberg',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
messagesCount: 0,
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
@ -2864,7 +2864,7 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Lustig',
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
messagesCount: 0,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: '100',
|
||||
@ -2873,19 +2873,19 @@ describe('ContributionResolver', () => {
|
||||
lastName: 'Lustig',
|
||||
memo: 'Test env contribution',
|
||||
messagesCount: 0,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DENIED',
|
||||
status: 'DENIED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'DELETED',
|
||||
status: 'DELETED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
}),
|
||||
expect.not.objectContaining({
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
|
||||
@ -195,7 +195,7 @@ export const listContributions = gql`
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
deletedAt
|
||||
state
|
||||
status
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
@ -218,7 +218,7 @@ query ($currentPage: Int = 1, $pageSize: Int = 5, $order: Order = DESC, $statusF
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
contributionDate
|
||||
state
|
||||
status
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
@ -254,7 +254,7 @@ export const adminListContributions = gql`
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
contributionDate
|
||||
state
|
||||
status
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@ COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community"
|
||||
COMMUNITY_SUPPORT_MAIL=support@supportmail.com
|
||||
|
||||
# backend
|
||||
BACKEND_CONFIG_VERSION=v15.2023-02-07
|
||||
BACKEND_CONFIG_VERSION=v16.2023-06-08
|
||||
|
||||
JWT_EXPIRES_IN=10m
|
||||
GDT_API_URL=https://gdt.gradido.net
|
||||
@ -40,6 +40,9 @@ KLICKTIPP_PASSWORD=
|
||||
KLICKTIPP_APIKEY_DE=
|
||||
KLICKTIPP_APIKEY_EN=
|
||||
|
||||
# IOTA
|
||||
IOTA=false
|
||||
|
||||
EMAIL=true
|
||||
EMAIL_TEST_MODUS=false
|
||||
EMAIL_TEST_RECEIVER=test_team@gradido.net
|
||||
|
||||
@ -21,9 +21,7 @@
|
||||
"dotenv": "10.0.0",
|
||||
"log4js": "^6.7.1",
|
||||
"nodemon": "^2.0.20",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.1.2",
|
||||
"typescript": "^4.9.4",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -46,7 +44,9 @@
|
||||
"eslint-plugin-security": "^1.7.1",
|
||||
"prettier": "^2.8.7",
|
||||
"jest": "^27.2.4",
|
||||
"ts-jest": "^27.0.5"
|
||||
"ts-jest": "^27.0.5",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
||||
@ -1 +1,2 @@
|
||||
node_modules
|
||||
playwright
|
||||
|
||||
@ -2,13 +2,13 @@ module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
cypress: true,
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['cypress', 'prettier', '@typescript-eslint' /*, 'jest' */],
|
||||
extends: [
|
||||
'standard',
|
||||
'eslint:recommended',
|
||||
'plugin:cypress/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
|
||||
@ -6,7 +6,7 @@ let emailLink: string
|
||||
|
||||
async function setupNodeEvents(
|
||||
on: Cypress.PluginEvents,
|
||||
config: Cypress.PluginConfigOptions
|
||||
config: Cypress.PluginConfigOptions,
|
||||
): Promise<Cypress.PluginConfigOptions> {
|
||||
await addCucumberPreprocessorPlugin(on, config)
|
||||
|
||||
@ -14,7 +14,7 @@ async function setupNodeEvents(
|
||||
'file:preprocessor',
|
||||
browserify(config, {
|
||||
typescript: require.resolve('typescript'),
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
on('task', {
|
||||
|
||||
38
e2e-tests/cypress/e2e/SendCoins.feature
Normal file
38
e2e-tests/cypress/e2e/SendCoins.feature
Normal file
@ -0,0 +1,38 @@
|
||||
Feature: Send coins
|
||||
As a user
|
||||
I want to send and receive GDD
|
||||
I want to see transaction details on overview and transactions pages
|
||||
|
||||
# Background:
|
||||
# Given the following "users" are in the database:
|
||||
# | email | password | name |
|
||||
# | bob@baumeister.de | Aa12345_ | Bob Baumeister |
|
||||
# | raeuber@hotzenplotz.de | Aa12345_ | Räuber Hotzenplotz |
|
||||
|
||||
Scenario: Send GDD to other user
|
||||
Given the user is logged in as "bob@baumeister.de" "Aa12345_"
|
||||
And the user navigates to page "/send"
|
||||
When the user fills the send form with "<receiverEmail>" "<amount>" "<memoText>"
|
||||
And the user submits the send form
|
||||
Then the transaction details are presented for confirmation "<receiverEmail>" "<amount>" "<memoText>" "<senderBalance>" "<newSenderBalance>"
|
||||
When the user submits the transaction by confirming
|
||||
Then the "<receiverName>" and "<amount>" are displayed on the "send" page
|
||||
When the user navigates to page "/transactions"
|
||||
Then the "<receiverName>" and "<amount>" are displayed on the "transactions" page
|
||||
|
||||
Examples:
|
||||
| receiverName | receiverEmail | amount | memoText | senderBalance | newSenderBalance |
|
||||
| Räuber Hotzenplotz | raeuber@hotzenplotz.de | 120.50 | Some memo text | 515.11 | 394.61 |
|
||||
|
||||
Scenario: Receive GDD from other user
|
||||
Given the user is logged in as "raeuber@hotzenplotz.de" "Aa12345_"
|
||||
And the user receives the transaction e-mail about "<amount>" GDD from "<senderName>"
|
||||
When the user opens the "transaction" link in the browser
|
||||
Then the "<senderName>" and "120.50" are displayed on the "overview" page
|
||||
When the user navigates to page "/transactions"
|
||||
Then the "<senderName>" and "120.50" are displayed on the "transactions" page
|
||||
|
||||
Examples:
|
||||
| senderName | amount |
|
||||
| Bob der Baumeister | 120,50 |
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
export class OverviewPage {
|
||||
navbarName = '[data-test="navbar-item-username"]'
|
||||
rightLastTransactionsList = '.rightside-last-transactions'
|
||||
|
||||
goto() {
|
||||
cy.visit('/overview')
|
||||
|
||||
@ -14,9 +14,7 @@ export class ResetPasswordPage {
|
||||
}
|
||||
|
||||
repeatNewPassword(password: string) {
|
||||
cy.get(this.newPasswordRepeatInput)
|
||||
.find('input[type=password]')
|
||||
.type(password)
|
||||
cy.get(this.newPasswordRepeatInput).find('input[type=password]').type(password)
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
25
e2e-tests/cypress/e2e/models/SendPage.ts
Normal file
25
e2e-tests/cypress/e2e/models/SendPage.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/// <reference types='cypress' />
|
||||
|
||||
export class SendPage {
|
||||
confirmationBox = '.transaction-confirm-send'
|
||||
submitBtn = '.btn-gradido'
|
||||
|
||||
enterReceiverEmail(email: string) {
|
||||
cy.get('[data-test="input-identifier"]').find('input').clear().type(email)
|
||||
return this
|
||||
}
|
||||
|
||||
enterAmount(amount: string) {
|
||||
cy.get('[data-test="input-amount"]').find('input').clear().type(amount)
|
||||
return this
|
||||
}
|
||||
|
||||
enterMemoText(text: string) {
|
||||
cy.get('[data-test="input-textarea"]').find('textarea').clear().type(text)
|
||||
return this
|
||||
}
|
||||
|
||||
submit() {
|
||||
cy.get(this.submitBtn).click()
|
||||
}
|
||||
}
|
||||
@ -8,10 +8,7 @@ export class UserEMailSite {
|
||||
emailSubject = '.subject'
|
||||
|
||||
openRecentPasswordResetEMail() {
|
||||
cy.get(this.emailList)
|
||||
.find('email-item')
|
||||
.filter(':contains(asswor)')
|
||||
.click()
|
||||
cy.get(this.emailList).find('email-item').filter(':contains(asswor)').click()
|
||||
expect(cy.get(this.emailSubject)).to('contain', 'asswor')
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import './e2e'
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
login(email: string, password: string): Chainable<any>
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
||||
import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
||||
import { OverviewPage } from '../../e2e/models/OverviewPage'
|
||||
import { SideNavMenu } from '../../e2e/models/SideNavMenu'
|
||||
import { Toasts } from '../../e2e/models/Toasts'
|
||||
@ -9,12 +9,9 @@ Given('the user navigates to page {string}', (page: string) => {
|
||||
|
||||
// login related
|
||||
|
||||
Given(
|
||||
'the user is logged in as {string} {string}',
|
||||
(email: string, password: string) => {
|
||||
cy.login(email, password)
|
||||
}
|
||||
)
|
||||
Given('the user is logged in as {string} {string}', (email: string, password: string) => {
|
||||
cy.login(email, password)
|
||||
})
|
||||
|
||||
Then('the user is logged in with username {string}', (username: string) => {
|
||||
const overviewPage = new OverviewPage()
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
||||
import { OverviewPage } from '../../e2e/models/OverviewPage'
|
||||
import { ResetPasswordPage } from '../../e2e/models/ResetPasswordPage'
|
||||
import { UserEMailSite } from '../../e2e/models/UserEMailSite'
|
||||
|
||||
const userEMailSite = new UserEMailSite()
|
||||
const resetPasswordPage = new ResetPasswordPage()
|
||||
|
||||
Then('the user receives an e-mail containing the {string} link', (linkName: string) => {
|
||||
let emailSubject: string
|
||||
@ -18,14 +18,20 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri
|
||||
emailSubject = 'asswor'
|
||||
linkPattern = /\/reset-password\/[0-9]+\d/
|
||||
break
|
||||
case 'transaction':
|
||||
emailSubject = 'Gradido gesendet'
|
||||
linkPattern = /\/overview/
|
||||
break
|
||||
default:
|
||||
throw new Error(`Error in "Then the user receives an e-mail containing the {string} link" step: incorrect linkname string "${linkName}"`)
|
||||
throw new Error(
|
||||
`Error in "Then the user receives an e-mail containing the {string} link" step: incorrect linkname string "${linkName}"`,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
cy.origin(
|
||||
Cypress.env('mailserverURL'),
|
||||
{ args: { emailSubject, linkPattern, userEMailSite } },
|
||||
({ emailSubject, linkPattern, userEMailSite }) => {
|
||||
({ emailSubject, linkPattern, userEMailSite }) => {
|
||||
cy.visit('/') // navigate to user's e-mail site (on fake mail server)
|
||||
cy.get(userEMailSite.emailInbox).should('be.visible')
|
||||
|
||||
@ -35,11 +41,9 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri
|
||||
.first()
|
||||
.click()
|
||||
|
||||
cy.get(userEMailSite.emailMeta)
|
||||
.find(userEMailSite.emailSubject)
|
||||
.contains(emailSubject)
|
||||
cy.get(userEMailSite.emailMeta).find(userEMailSite.emailSubject).contains(emailSubject)
|
||||
|
||||
cy.get('.email-content', { timeout: 2000})
|
||||
cy.get('.email-content', { timeout: 2000 })
|
||||
.find('.plain-text')
|
||||
.contains(linkPattern)
|
||||
.invoke('text')
|
||||
@ -47,13 +51,64 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri
|
||||
const emailLink = text.match(linkPattern)[0]
|
||||
cy.task('setEmailLink', emailLink)
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
When(
|
||||
'the user receives the transaction e-mail about {string} GDD from {string}',
|
||||
(amount: string, senderName: string) => {
|
||||
cy.origin(
|
||||
Cypress.env('mailserverURL'),
|
||||
{ args: { amount, senderName, userEMailSite } },
|
||||
({ amount, senderName, userEMailSite }) => {
|
||||
const subject = `${senderName} hat dir ${amount} Gradido gesendet`
|
||||
const linkPattern = /\/transactions/
|
||||
cy.visit('/')
|
||||
cy.get(userEMailSite.emailInbox).should('be.visible')
|
||||
|
||||
cy.get(userEMailSite.emailList)
|
||||
.find('.email-item')
|
||||
.filter(`:contains(${subject})`)
|
||||
.first()
|
||||
.click()
|
||||
|
||||
cy.get(userEMailSite.emailMeta).find(userEMailSite.emailSubject).contains(subject)
|
||||
|
||||
cy.get('.email-content', { timeout: 2000 })
|
||||
.find('.plain-text')
|
||||
.contains(linkPattern)
|
||||
.invoke('text')
|
||||
.then((text) => {
|
||||
const emailLink = text.match(linkPattern)[0]
|
||||
cy.task('setEmailLink', emailLink)
|
||||
})
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
When('the user opens the {string} link in the browser', (linkName: string) => {
|
||||
const resetPasswordPage = new ResetPasswordPage()
|
||||
cy.task('getEmailLink').then((emailLink) => {
|
||||
cy.visit(emailLink)
|
||||
})
|
||||
cy.get(resetPasswordPage.newPasswordInput).should('be.visible')
|
||||
|
||||
switch (linkName) {
|
||||
case 'activation':
|
||||
cy.get(resetPasswordPage.newPasswordInput).should('be.visible')
|
||||
break
|
||||
case 'password reset':
|
||||
cy.get(resetPasswordPage.newPasswordInput).should('be.visible')
|
||||
break
|
||||
case 'transaction':
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const overviewPage = new OverviewPage()
|
||||
cy.get(overviewPage.rightLastTransactionsList).should('be.visible')
|
||||
break
|
||||
default:
|
||||
throw new Error(
|
||||
`Error in "Then the user receives an e-mail containing the {string} link" step: incorrect link name string "${linkName}"`,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
import { And, Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
||||
import { SendPage } from '../../e2e/models/SendPage'
|
||||
|
||||
const sendPage = new SendPage()
|
||||
|
||||
When(
|
||||
'the user fills the send form with {string} {string} {string}',
|
||||
(email: string, amount: string, memoText: string) => {
|
||||
sendPage.enterReceiverEmail(email)
|
||||
sendPage.enterAmount(amount)
|
||||
sendPage.enterMemoText(memoText)
|
||||
},
|
||||
)
|
||||
|
||||
And('the user submits the send form', () => {
|
||||
sendPage.submit()
|
||||
cy.get(sendPage.confirmationBox).should('be.visible')
|
||||
})
|
||||
|
||||
Then(
|
||||
'the transaction details are presented for confirmation {string} {string} {string} {string} {string}',
|
||||
(
|
||||
receiverEmail: string,
|
||||
sendAmount: string,
|
||||
memoText: string,
|
||||
senderBalance: string,
|
||||
newSenderBalance: string,
|
||||
) => {
|
||||
cy.get('.transaction-confirm-send').contains(receiverEmail)
|
||||
cy.get('.transaction-confirm-send').contains(`+ ${sendAmount} GDD`)
|
||||
cy.get('.transaction-confirm-send').contains(memoText)
|
||||
cy.get('.transaction-confirm-send').contains(`+ ${senderBalance} GDD`)
|
||||
cy.get('.transaction-confirm-send').contains(`− ${sendAmount} GDD`)
|
||||
cy.get('.transaction-confirm-send').contains(`+ ${newSenderBalance} GDD`)
|
||||
},
|
||||
)
|
||||
|
||||
When('the user submits the transaction by confirming', () => {
|
||||
cy.intercept({
|
||||
method: 'POST',
|
||||
url: '/graphql',
|
||||
hostname: 'localhost',
|
||||
}).as('sendCoins')
|
||||
|
||||
sendPage.submit()
|
||||
|
||||
cy.wait('@sendCoins').then((interception) => {
|
||||
cy.wrap(interception.response?.statusCode).should('eq', 200)
|
||||
cy.wrap(interception.request.body).should(
|
||||
'have.property',
|
||||
'query',
|
||||
`mutation ($identifier: String!, $amount: Decimal!, $memo: String!) {
|
||||
sendCoins(identifier: $identifier, amount: $amount, memo: $memo)
|
||||
}
|
||||
`,
|
||||
)
|
||||
cy.wrap(interception.response?.body)
|
||||
.should('have.nested.property', 'data.sendCoins')
|
||||
.and('equal', true)
|
||||
})
|
||||
cy.get('[data-test="send-transaction-success-text"]').should('be.visible')
|
||||
})
|
||||
|
||||
Then(
|
||||
'the {string} and {string} are displayed on the {string} page',
|
||||
(name: string, amount: string, page: string) => {
|
||||
switch (page) {
|
||||
case 'overview':
|
||||
cy.get('.align-items-center').contains(`${name}`)
|
||||
cy.get('.align-items-center').contains(`${amount} GDD`)
|
||||
break
|
||||
case 'send':
|
||||
cy.get('.align-items-center').contains(`${name}`)
|
||||
cy.get('.align-items-center').contains(`${amount} GDD`)
|
||||
break
|
||||
case 'transactions':
|
||||
cy.get('div.mt-3 > div > div.test-list-group-item')
|
||||
.eq(0)
|
||||
.contains('div.gdd-transaction-list-item-name', `${name}`)
|
||||
cy.get('div.mt-3 > div > div.test-list-group-item')
|
||||
.eq(0)
|
||||
.contains('[data-test="transaction-amount"]', `${amount} GDD`)
|
||||
break
|
||||
default:
|
||||
throw new Error(
|
||||
`Error in "Then the {string} and {string} are displayed on the {string}} page" step: incorrect page name string "${page}"`,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -13,26 +13,21 @@ When('the user submits no credentials', () => {
|
||||
loginPage.submitLogin()
|
||||
})
|
||||
|
||||
When(
|
||||
'the user submits the credentials {string} {string}',
|
||||
(email: string, password: string) => {
|
||||
cy.intercept('POST', '/graphql', (req) => {
|
||||
if (
|
||||
req.body.hasOwnProperty('query') &&
|
||||
req.body.query.includes('mutation')
|
||||
) {
|
||||
req.alias = 'login'
|
||||
}
|
||||
})
|
||||
When('the user submits the credentials {string} {string}', (email: string, password: string) => {
|
||||
cy.intercept('POST', '/graphql', (req) => {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (req.body.hasOwnProperty('query') && req.body.query.includes('mutation')) {
|
||||
req.alias = 'login'
|
||||
}
|
||||
})
|
||||
|
||||
loginPage.enterEmail(email)
|
||||
loginPage.enterPassword(password)
|
||||
loginPage.submitLogin()
|
||||
cy.wait('@login').then((interception) => {
|
||||
expect(interception.response.statusCode).equals(200)
|
||||
})
|
||||
}
|
||||
)
|
||||
loginPage.enterEmail(email)
|
||||
loginPage.enterPassword(password)
|
||||
loginPage.submitLogin()
|
||||
cy.wait('@login').then((interception) => {
|
||||
expect(interception.response.statusCode).equals(200)
|
||||
})
|
||||
})
|
||||
|
||||
// password reset related
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { And, When } from '@badeball/cypress-cucumber-preprocessor'
|
||||
import { And, DataTable, When } from '@badeball/cypress-cucumber-preprocessor'
|
||||
import { ProfilePage } from '../../e2e/models/ProfilePage'
|
||||
import { Toasts } from '../../e2e/models/Toasts'
|
||||
|
||||
@ -10,8 +10,8 @@ And('the user opens the change password menu', () => {
|
||||
cy.get(profilePage.submitNewPasswordBtn).should('be.disabled')
|
||||
})
|
||||
|
||||
When('the user fills the password form with:', (table) => {
|
||||
let hashedTableRows = table.rowsHash()
|
||||
When('the user fills the password form with:', (table: DataTable) => {
|
||||
const hashedTableRows = table.rowsHash()
|
||||
profilePage.enterOldPassword(hashedTableRows['Old password'])
|
||||
profilePage.enterNewPassword(hashedTableRows['New password'])
|
||||
profilePage.enterRepeatPassword(hashedTableRows['Repeat new password'])
|
||||
@ -22,7 +22,7 @@ And('the user submits the password form', () => {
|
||||
profilePage.submitPasswordForm()
|
||||
})
|
||||
|
||||
When('the user is presented a {string} message', (type: string) => {
|
||||
When('the user is presented a {string} message', () => {
|
||||
const toast = new Toasts()
|
||||
cy.get(toast.toastSlot).within(() => {
|
||||
cy.get(toast.toastTypeSuccess)
|
||||
|
||||
@ -10,7 +10,7 @@ When(
|
||||
registrationPage.enterFirstname(firstname)
|
||||
registrationPage.enterLastname(lastname)
|
||||
registrationPage.enterEmail(email)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
And('the user agrees to the privacy policy', () => {
|
||||
|
||||
@ -73,8 +73,8 @@ describe('ContributionMessagesFormular', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('emitted "update-state" with data', async () => {
|
||||
expect(wrapper.emitted('update-state')).toEqual(
|
||||
it('emitted "update-status" with data', async () => {
|
||||
expect(wrapper.emitted('update-status')).toEqual(
|
||||
expect.arrayContaining([expect.arrayContaining([42])]),
|
||||
)
|
||||
})
|
||||
|
||||
@ -55,7 +55,7 @@ export default {
|
||||
})
|
||||
.then((result) => {
|
||||
this.$emit('get-list-contribution-messages', false)
|
||||
this.$emit('update-state', this.contributionId)
|
||||
this.$emit('update-status', this.contributionId)
|
||||
this.form.text = ''
|
||||
this.toastSuccess(this.$t('message.reply'))
|
||||
this.isSubmitting = false
|
||||
|
||||
@ -8,7 +8,7 @@ describe('ContributionMessagesList', () => {
|
||||
|
||||
const propsData = {
|
||||
contributionId: 42,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
messages: [],
|
||||
}
|
||||
|
||||
@ -40,13 +40,13 @@ describe('ContributionMessagesList', () => {
|
||||
expect(wrapper.findComponent({ name: 'ContributionMessagesFormular' }).exists()).toBe(true)
|
||||
})
|
||||
|
||||
describe('update State', () => {
|
||||
describe('update Status', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.vm.updateState()
|
||||
wrapper.vm.updateStatus()
|
||||
})
|
||||
|
||||
it('emits getListContributionMessages', async () => {
|
||||
expect(wrapper.vm.$emit('update-state')).toBeTruthy()
|
||||
expect(wrapper.vm.$emit('update-status')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -7,10 +7,10 @@
|
||||
</div>
|
||||
<div>
|
||||
<contribution-messages-formular
|
||||
v-if="['PENDING', 'IN_PROGRESS'].includes(state)"
|
||||
v-if="['PENDING', 'IN_PROGRESS'].includes(status)"
|
||||
:contributionId="contributionId"
|
||||
v-on="$listeners"
|
||||
@update-state="updateState"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -37,7 +37,7 @@ export default {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
state: {
|
||||
status: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
@ -47,8 +47,8 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateState(id) {
|
||||
this.$emit('update-state', id)
|
||||
updateStatus(id) {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ const mocks = {
|
||||
describe('ContributionMessagesList', () => {
|
||||
const propsData = {
|
||||
contributionId: 42,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
messages: [
|
||||
{
|
||||
id: 111,
|
||||
|
||||
@ -119,11 +119,11 @@ describe('ContributionList', () => {
|
||||
|
||||
describe('update status', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.findComponent({ name: 'ContributionListItem' }).vm.$emit('update-state', { id: 2 })
|
||||
wrapper.findComponent({ name: 'ContributionListItem' }).vm.$emit('update-status', { id: 2 })
|
||||
})
|
||||
|
||||
it('emits update status', () => {
|
||||
expect(wrapper.emitted('update-state')).toEqual([[{ id: 2 }]])
|
||||
expect(wrapper.emitted('update-status')).toEqual([[{ id: 2 }]])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,26 +2,26 @@
|
||||
<div class="contribution-list">
|
||||
<div class="mb-3" v-for="item in items" :key="item.id + 'a'">
|
||||
<contribution-list-item
|
||||
v-if="item.state === 'IN_PROGRESS'"
|
||||
v-if="item.status === 'IN_PROGRESS'"
|
||||
v-bind="item"
|
||||
@closeAllOpenCollapse="$emit('closeAllOpenCollapse')"
|
||||
:contributionId="item.id"
|
||||
:allContribution="allContribution"
|
||||
@update-contribution-form="updateContributionForm"
|
||||
@delete-contribution="deleteContribution"
|
||||
@update-state="updateState"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3" v-for="item2 in items" :key="item2.id">
|
||||
<contribution-list-item
|
||||
v-if="item2.state !== 'IN_PROGRESS'"
|
||||
v-if="item2.status !== 'IN_PROGRESS'"
|
||||
v-bind="item2"
|
||||
@closeAllOpenCollapse="$emit('closeAllOpenCollapse')"
|
||||
:contributionId="item2.id"
|
||||
:allContribution="allContribution"
|
||||
@update-contribution-form="updateContributionForm"
|
||||
@delete-contribution="deleteContribution"
|
||||
@update-state="updateState"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
<b-pagination
|
||||
@ -85,8 +85,8 @@ export default {
|
||||
deleteContribution(item) {
|
||||
this.$emit('delete-contribution', item)
|
||||
},
|
||||
updateState(id) {
|
||||
this.$emit('update-state', id)
|
||||
updateStatus(id) {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
@ -14,7 +14,7 @@ describe('ContributionListItem', () => {
|
||||
|
||||
const propsData = {
|
||||
contributionId: 42,
|
||||
state: 'PENDING',
|
||||
status: 'PENDING',
|
||||
messagesCount: 2,
|
||||
id: 1,
|
||||
createdAt: '26/07/2022',
|
||||
@ -72,8 +72,8 @@ describe('ContributionListItem', () => {
|
||||
expect(wrapper.vm.variant).toBe('success')
|
||||
})
|
||||
|
||||
it('is warning at when state is IN_PROGRESS', async () => {
|
||||
await wrapper.setProps({ state: 'IN_PROGRESS' })
|
||||
it('is warning at when status is IN_PROGRESS', async () => {
|
||||
await wrapper.setProps({ status: 'IN_PROGRESS' })
|
||||
expect(wrapper.vm.variant).toBe('205')
|
||||
})
|
||||
})
|
||||
@ -134,13 +134,13 @@ describe('ContributionListItem', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateState', () => {
|
||||
describe('updateStatus', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.vm.updateState()
|
||||
await wrapper.vm.updateStatus()
|
||||
})
|
||||
|
||||
it('emit update-state', () => {
|
||||
expect(wrapper.vm.$emit('update-state')).toBeTruthy()
|
||||
it('emit update-status', () => {
|
||||
expect(wrapper.vm.$emit('update-status')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div
|
||||
class="contribution-list-item bg-white appBoxShadow gradido-border-radius pt-3 px-3"
|
||||
:class="state === 'IN_PROGRESS' && !allContribution ? 'pulse border border-205' : ''"
|
||||
:class="status === 'IN_PROGRESS' && !allContribution ? 'pulse border border-205' : ''"
|
||||
>
|
||||
<b-row>
|
||||
<b-col cols="3" lg="2" md="2">
|
||||
@ -26,7 +26,7 @@
|
||||
<div class="mt-3 font-weight-bold">{{ $t('contributionText') }}</div>
|
||||
<div class="mb-3 text-break word-break">{{ memo }}</div>
|
||||
<div
|
||||
v-if="state === 'IN_PROGRESS'"
|
||||
v-if="status === 'IN_PROGRESS'"
|
||||
class="text-205 pointer hover-font-bold"
|
||||
@click="visible = !visible"
|
||||
>
|
||||
@ -37,11 +37,11 @@
|
||||
<div class="small">
|
||||
{{ $t('creation') }} {{ $t('(') }}{{ amount / 20 }} {{ $t('h') }}{{ $t(')') }}
|
||||
</div>
|
||||
<div v-if="state === 'DENIED' && allContribution" class="font-weight-bold">
|
||||
<div v-if="status === 'DENIED' && allContribution" class="font-weight-bold">
|
||||
<b-icon icon="x-circle" variant="danger"></b-icon>
|
||||
{{ $t('contribution.alert.denied') }}
|
||||
</div>
|
||||
<div v-if="state === 'DELETED'" class="small">
|
||||
<div v-if="status === 'DELETED'" class="small">
|
||||
{{ $t('contribution.deleted') }}
|
||||
</div>
|
||||
<div v-else class="font-weight-bold">{{ amount | GDD }}</div>
|
||||
@ -53,12 +53,12 @@
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row
|
||||
v-if="(!['CONFIRMED', 'DELETED'].includes(state) && !allContribution) || messagesCount > 0"
|
||||
v-if="(!['CONFIRMED', 'DELETED'].includes(status) && !allContribution) || messagesCount > 0"
|
||||
class="p-2"
|
||||
>
|
||||
<b-col cols="3" class="mr-auto text-center">
|
||||
<div
|
||||
v-if="!['CONFIRMED', 'DELETED'].includes(state) && !allContribution && !moderatorId"
|
||||
v-if="!['CONFIRMED', 'DELETED'].includes(status) && !allContribution && !moderatorId"
|
||||
class="test-delete-contribution pointer mr-3"
|
||||
@click="deleteContribution({ id })"
|
||||
>
|
||||
@ -69,7 +69,7 @@
|
||||
</b-col>
|
||||
<b-col cols="3" class="text-center">
|
||||
<div
|
||||
v-if="!['CONFIRMED', 'DELETED'].includes(state) && !allContribution && !moderatorId"
|
||||
v-if="!['CONFIRMED', 'DELETED'].includes(status) && !allContribution && !moderatorId"
|
||||
class="test-edit-contribution pointer mr-3"
|
||||
@click="
|
||||
$emit('update-contribution-form', {
|
||||
@ -95,10 +95,10 @@
|
||||
<b-collapse :id="collapsId" class="mt-2" v-model="visible">
|
||||
<contribution-messages-list
|
||||
:messages="messages_get"
|
||||
:state="state"
|
||||
:status="status"
|
||||
:contributionId="contributionId"
|
||||
@get-list-contribution-messages="getListContributionMessages"
|
||||
@update-state="updateState"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</b-collapse>
|
||||
</div>
|
||||
@ -161,7 +161,7 @@ export default {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
state: {
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
@ -197,14 +197,14 @@ export default {
|
||||
if (this.deletedAt) return 'trash'
|
||||
if (this.deniedAt) return 'x-circle'
|
||||
if (this.confirmedAt) return 'check'
|
||||
if (this.state === 'IN_PROGRESS') return 'question'
|
||||
if (this.status === 'IN_PROGRESS') return 'question'
|
||||
return 'bell-fill'
|
||||
},
|
||||
variant() {
|
||||
if (this.deletedAt) return 'danger'
|
||||
if (this.deniedAt) return 'warning'
|
||||
if (this.confirmedAt) return 'success'
|
||||
if (this.state === 'IN_PROGRESS') return '205'
|
||||
if (this.status === 'IN_PROGRESS') return '205'
|
||||
return 'primary'
|
||||
},
|
||||
date() {
|
||||
@ -245,8 +245,8 @@ export default {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
updateState(id) {
|
||||
this.$emit('update-state', id)
|
||||
updateStatus(id) {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="decayinformation-long px-2">
|
||||
<div class="decayinformation-long px-1">
|
||||
<div class="word-break mb-5 mt-lg-3">
|
||||
<div class="font-weight-bold pb-2">{{ $t('form.memo') }}</div>
|
||||
<div class="">{{ memo }}</div>
|
||||
@ -11,10 +11,10 @@
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-row>
|
||||
<b-col cols="12" lg="4" md="4">
|
||||
<b-col cols="6" lg="4" md="6" sm="6">
|
||||
<div>{{ $t('decay.last_transaction') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0" class="text-right mr-5">
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
<div>
|
||||
<span>
|
||||
{{ $d(new Date(decay.start), 'long') }}
|
||||
@ -26,20 +26,20 @@
|
||||
|
||||
<!-- Previous Balance -->
|
||||
<b-row class="mt-2">
|
||||
<b-col cols="12" lg="6" md="3">
|
||||
<b-col cols="6" lg="4" md="6" sm="6">
|
||||
<div>{{ $t('decay.old_balance') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0" class="text-right mr-5">
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
{{ previousBalance | GDD }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<!-- Decay-->
|
||||
<b-row class="mt-0">
|
||||
<b-col cols="12" lg="3" md="3">
|
||||
<b-col cols="6" lg="3" md="6" sm="6">
|
||||
<div>{{ $t('decay.decay') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0" class="text-right mr-5">
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
{{ decay.decay | GDD }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -49,18 +49,21 @@
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-row class="mb-2">
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
|
||||
<b-col cols="12" lg="3" md="3">{{ $t(`decay.types.${typeId.toLowerCase()}`) }}</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0" class="text-right mr-5">
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-dynamic-keys-->
|
||||
<b-col cols="6" lg="3" md="6" sm="6">
|
||||
{{ $t(`decay.types.${typeId.toLowerCase()}`) }}
|
||||
</b-col>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-dynamic-keys-->
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
{{ amount | GDD }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
<!-- Total-->
|
||||
<b-row class="border-top pt-2">
|
||||
<b-col cols="12" lg="3" md="3">
|
||||
<b-col cols="6" lg="3" md="6" sm="6">
|
||||
<div>{{ $t('decay.new_balance') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0" class="text-right mr-5">
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
<b>{{ balance | GDD }}</b>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="duration-row">
|
||||
<b-row>
|
||||
<b-col cols="12" lg="4" md="4">
|
||||
<b-col cols="6" lg="4" md="6" sm="6">
|
||||
<div>{{ $t('decay.past_time') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0" class="text-right mr-5">
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
<span v-if="duration">{{ duration }}</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
@ -26,7 +26,9 @@
|
||||
<div class="small mb-2">
|
||||
{{ $t('decay.types.receive') }}
|
||||
</div>
|
||||
<div class="font-weight-bold gradido-global-color-accent">{{ amount | GDD }}</div>
|
||||
<div class="font-weight-bold gradido-global-color-accent" data-test="transaction-amount">
|
||||
{{ amount | GDD }}
|
||||
</div>
|
||||
<div v-if="linkId" class="small">
|
||||
{{ $t('via_link') }}
|
||||
<b-icon
|
||||
|
||||
@ -25,7 +25,9 @@
|
||||
<div class="small mb-2">
|
||||
{{ $t('decay.types.send') }}
|
||||
</div>
|
||||
<div class="font-weight-bold text-140">{{ amount | GDD }}</div>
|
||||
<div class="font-weight-bold text-140" data-test="transaction-amount">
|
||||
{{ amount | GDD }}
|
||||
</div>
|
||||
<div v-if="linkId" class="small">
|
||||
{{ $t('via_link') }}
|
||||
<b-icon
|
||||
|
||||
@ -190,7 +190,7 @@ export const listContributions = gql`
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
deletedAt
|
||||
state
|
||||
status
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
@ -214,7 +214,7 @@ export const listAllContributions = gql`
|
||||
contributionDate
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
state
|
||||
status
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
|
||||
@ -68,7 +68,7 @@ describe('Community', () => {
|
||||
firstName: 'Bibi',
|
||||
contributionDate: '2022-07-15T08:47:06.000Z',
|
||||
lastName: 'Bloxberg',
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
messagesCount: 0,
|
||||
deniedAt: null,
|
||||
deniedBy: null,
|
||||
@ -85,7 +85,7 @@ describe('Community', () => {
|
||||
firstName: 'Bibi',
|
||||
contributionDate: '2022-06-15T08:47:06.000Z',
|
||||
lastName: 'Bloxberg',
|
||||
state: 'CONFIRMED',
|
||||
status: 'CONFIRMED',
|
||||
messagesCount: 0,
|
||||
deniedAt: null,
|
||||
deniedBy: null,
|
||||
@ -121,7 +121,7 @@ describe('Community', () => {
|
||||
deniedAt: null,
|
||||
deniedBy: null,
|
||||
messagesCount: 0,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
},
|
||||
{
|
||||
id: 1550,
|
||||
@ -137,7 +137,7 @@ describe('Community', () => {
|
||||
deniedAt: null,
|
||||
deniedBy: null,
|
||||
messagesCount: 0,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
},
|
||||
{
|
||||
id: 1556,
|
||||
@ -153,7 +153,7 @@ describe('Community', () => {
|
||||
deniedAt: null,
|
||||
deniedBy: null,
|
||||
messagesCount: 0,
|
||||
state: 'IN_PROGRESS',
|
||||
status: 'IN_PROGRESS',
|
||||
},
|
||||
],
|
||||
contributionCount: 3,
|
||||
@ -263,7 +263,7 @@ describe('Community', () => {
|
||||
expect(wrapper.findAll('div[role="tabpanel"]')).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('check for correct tabIndex if state is "IN_PROGRESS" or not', () => {
|
||||
it('check for correct tabIndex if status is "IN_PROGRESS" or not', () => {
|
||||
expect(routerPushMock).toBeCalledWith({ params: { tab: 'contributions' } })
|
||||
})
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
@update-list-contributions="updateListContributions"
|
||||
@update-contribution-form="updateContributionForm"
|
||||
@delete-contribution="deleteContribution"
|
||||
@update-state="updateState"
|
||||
@update-status="updateStatus"
|
||||
:contributionCount="contributionCount"
|
||||
:showPagination="true"
|
||||
:pageSize="pageSize"
|
||||
@ -148,7 +148,7 @@ export default {
|
||||
update({ listContributions }) {
|
||||
this.contributionCount = listContributions.contributionCount
|
||||
this.items = listContributions.contributionList
|
||||
if (this.items.find((item) => item.state === 'IN_PROGRESS')) {
|
||||
if (this.items.find((item) => item.status === 'IN_PROGRESS')) {
|
||||
this.tabIndex = 1
|
||||
if (this.$route.params.tab !== 'contributions')
|
||||
this.$router.push({ params: { tab: 'contributions' } })
|
||||
@ -290,8 +290,8 @@ export default {
|
||||
updateTransactions(pagination) {
|
||||
this.$emit('update-transactions', pagination)
|
||||
},
|
||||
updateState(id) {
|
||||
this.items.find((item) => item.id === id).state = 'PENDING'
|
||||
updateStatus(id) {
|
||||
this.items.find((item) => item.id === id).status = 'PENDING'
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user