From 98b3a526ef44ad39fbf4be53426313a5c8b8867f Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 8 Nov 2025 13:16:51 +0100 Subject: [PATCH 1/4] fix seed algorithmus to get correct data --- backend/src/seeds/factory/user.ts | 6 +++++- backend/src/seeds/transactionLink/index.ts | 3 +-- backend/src/seeds/users/bibi-bloxberg.ts | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/src/seeds/factory/user.ts b/backend/src/seeds/factory/user.ts index 3cae22f71..44db02c8f 100644 --- a/backend/src/seeds/factory/user.ts +++ b/backend/src/seeds/factory/user.ts @@ -40,11 +40,15 @@ export const userFactory = async ( } // get last changes of user from database - dbUser = await User.findOneOrFail({ where: { id }, relations: ['userRoles'] }) + dbUser = await User.findOneOrFail({ where: { id }, relations: { userRoles: true, emailContact: true } }) if (user.createdAt || user.deletedAt || user.role) { if (user.createdAt) { dbUser.createdAt = user.createdAt + // make sure emailContact is also updated for e2e test, prevent failing when time between seeding and test run is < 1 minute + dbUser.emailContact.createdAt = user.createdAt + dbUser.emailContact.updatedAt = user.createdAt + await dbUser.emailContact.save() } if (user.deletedAt) { dbUser.deletedAt = user.deletedAt diff --git a/backend/src/seeds/transactionLink/index.ts b/backend/src/seeds/transactionLink/index.ts index c3245c2b6..17683b580 100644 --- a/backend/src/seeds/transactionLink/index.ts +++ b/backend/src/seeds/transactionLink/index.ts @@ -4,8 +4,7 @@ export const transactionLinks: TransactionLinkInterface[] = [ { email: 'bibi@bloxberg.de', amount: 19.99, - memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', - createdAt: new Date(2022, 0, 1), + memo: 'Leider wollte niemand meine Gradidos haben :(', }, { email: 'bibi@bloxberg.de', diff --git a/backend/src/seeds/users/bibi-bloxberg.ts b/backend/src/seeds/users/bibi-bloxberg.ts index 9a40e922b..f78a3af1c 100644 --- a/backend/src/seeds/users/bibi-bloxberg.ts +++ b/backend/src/seeds/users/bibi-bloxberg.ts @@ -9,4 +9,6 @@ export const bibiBloxberg: UserInterface = { emailChecked: true, language: 'de', publisherId: 1234, + // move user createdAt before transaction link + createdAt: new Date(2021, 9, 17), } From a8e7a26f8d5b817c69ea21c7cbed01d81216bbf1 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Thu, 13 Nov 2025 11:13:39 +0100 Subject: [PATCH 2/4] make sure seeded links delete one second after createdAt --- backend/src/seeds/factory/transactionLink.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/seeds/factory/transactionLink.ts b/backend/src/seeds/factory/transactionLink.ts index a71a20955..80384025f 100644 --- a/backend/src/seeds/factory/transactionLink.ts +++ b/backend/src/seeds/factory/transactionLink.ts @@ -39,7 +39,7 @@ export const transactionLinkFactory = async ( } if (transactionLink.deletedAt) { - dbTransactionLink.deletedAt = new Date() + dbTransactionLink.deletedAt = new Date(dbTransactionLink.createdAt.getTime() + 1000) await dbTransactionLink.save() } } From 92ad6b68bf31ee1ef2aabbb87d1a9ceb1e28ffce Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 14 Nov 2025 13:20:55 +0100 Subject: [PATCH 3/4] adapt backend tests to change seeding data --- .../resolver/TransactionLinkResolver.test.ts | 30 +++++++++---------- .../src/graphql/resolver/UserResolver.test.ts | 24 +++++++-------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index b6abcb0b2..95aa03993 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -947,7 +947,7 @@ describe('TransactionLinkResolver', () => { }) describe('without any filters', () => { - it('finds 6 open transaction links and no deleted or redeemed', async () => { + it('finds 7 open transaction links and no deleted or redeemed', async () => { await expect( query({ query: listTransactionLinksAdmin, @@ -957,14 +957,14 @@ describe('TransactionLinkResolver', () => { expect.objectContaining({ data: { listTransactionLinksAdmin: { - count: 6, + count: 7, links: expect.not.arrayContaining([ expect.objectContaining({ - memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', + memo: 'Leider wollte niemand meine Gradidos haben :(', createdAt: expect.any(String), }), expect.objectContaining({ - memo: 'Da habe ich mich wohl etwas übernommen.', + memo: "Kein Trick, keine Zauberrei,\n bei Gradidio sei dabei!", deletedAt: expect.any(String), }), ]), @@ -976,7 +976,7 @@ describe('TransactionLinkResolver', () => { }) describe('all filters are null', () => { - it('finds 6 open transaction links and no deleted or redeemed', async () => { + it('finds 7 open transaction links and no deleted or redeemed', async () => { await expect( query({ query: listTransactionLinksAdmin, @@ -993,10 +993,10 @@ describe('TransactionLinkResolver', () => { expect.objectContaining({ data: { listTransactionLinksAdmin: { - count: 6, + count: 7, links: expect.not.arrayContaining([ expect.objectContaining({ - memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', + memo: 'Leider wollte niemand meine Gradidos haben :(', createdAt: expect.any(String), }), expect.objectContaining({ @@ -1012,7 +1012,7 @@ describe('TransactionLinkResolver', () => { }) describe('filter with deleted', () => { - it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => { + it('finds 7 open transaction links, 1 deleted, and no redeemed', async () => { await expect( query({ query: listTransactionLinksAdmin, @@ -1027,10 +1027,10 @@ describe('TransactionLinkResolver', () => { expect.objectContaining({ data: { listTransactionLinksAdmin: { - count: 7, + count: 8, links: expect.arrayContaining([ expect.not.objectContaining({ - memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', + memo: 'Leider wollte niemand meine Gradidos haben :(', createdAt: expect.any(String), }), expect.objectContaining({ @@ -1046,7 +1046,7 @@ describe('TransactionLinkResolver', () => { }) describe('filter by expired', () => { - it('finds 5 open transaction links, 1 expired, and no redeemed', async () => { + it('finds 6 open transaction links, 1 expired, and no redeemed', async () => { await expect( query({ query: listTransactionLinksAdmin, @@ -1064,7 +1064,7 @@ describe('TransactionLinkResolver', () => { count: 7, links: expect.arrayContaining([ expect.objectContaining({ - memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', + memo: 'Leider wollte niemand meine Gradidos haben :(', createdAt: expect.any(String), }), expect.not.objectContaining({ @@ -1082,7 +1082,7 @@ describe('TransactionLinkResolver', () => { // TODO: works not as expected, because 'redeemedAt' and 'redeemedBy' have to be added to the transaktion link factory describe.skip('filter by redeemed', () => { - it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => { + it('finds 7 open transaction links, 1 deleted, and no redeemed', async () => { await expect( query({ query: listTransactionLinksAdmin, @@ -1099,10 +1099,10 @@ describe('TransactionLinkResolver', () => { expect.objectContaining({ data: { listTransactionLinksAdmin: { - count: 6, + count: 7, links: expect.arrayContaining([ expect.not.objectContaining({ - memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(', + memo: 'Leider wollte niemand meine Gradidos haben :(', createdAt: expect.any(String), }), expect.objectContaining({ diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index cee570c94..8b4faa443 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -1040,7 +1040,7 @@ describe('UserResolver', () => { describe('user exists in DB', () => { beforeAll(async () => { - await userFactory(testEnv, bibiBloxberg) + await userFactory(testEnv, bobBaumeister) }) afterAll(async () => { @@ -1050,7 +1050,7 @@ describe('UserResolver', () => { describe('duration not expired', () => { it('throws an error', async () => { - await expect(mutate({ mutation: forgotPassword, variables })).resolves.toEqual( + await expect(mutate({ mutation: forgotPassword, variables: { email: 'bob@baumeister.de' } })).resolves.toEqual( expect.objectContaining({ errors: [ new GraphQLError( @@ -1067,7 +1067,7 @@ describe('UserResolver', () => { describe('duration reset to 0', () => { it('returns true', async () => { CONFIG.EMAIL_CODE_REQUEST_TIME = 0 - await expect(mutate({ mutation: forgotPassword, variables })).resolves.toEqual( + await expect(mutate({ mutation: forgotPassword, variables: { email: 'bob@baumeister.de' } })).resolves.toEqual( expect.objectContaining({ data: { forgotPassword: true, @@ -1078,9 +1078,9 @@ describe('UserResolver', () => { it('sends reset password email', () => { expect(sendResetPasswordEmail).toBeCalledWith({ - firstName: 'Bibi', - lastName: 'Bloxberg', - email: 'bibi@bloxberg.de', + firstName: 'Bob', + lastName: 'der Baumeister', + email: 'bob@baumeister.de', language: 'de', resetLink: expect.any(String), timeDurationObject: expect.objectContaining({ @@ -1092,7 +1092,7 @@ describe('UserResolver', () => { it('stores the EMAIL_FORGOT_PASSWORD event in the database', async () => { const userConatct = await UserContact.findOneOrFail({ - where: { email: 'bibi@bloxberg.de' }, + where: { email: 'bob@baumeister.de' }, relations: ['user'], }) await expect(DbEvent.find()).resolves.toContainEqual( @@ -1108,7 +1108,7 @@ describe('UserResolver', () => { describe('request reset password again', () => { it('throws an error', async () => { CONFIG.EMAIL_CODE_REQUEST_TIME = emailCodeRequestTime - await expect(mutate({ mutation: forgotPassword, variables })).resolves.toEqual( + await expect(mutate({ mutation: forgotPassword, variables: { email: 'bob@baumeister.de' } })).resolves.toEqual( expect.objectContaining({ errors: [new GraphQLError('Email already sent less than 10 minutes ago')], }), @@ -1128,8 +1128,8 @@ describe('UserResolver', () => { let emailContact: UserContact beforeAll(async () => { - await userFactory(testEnv, bibiBloxberg) - emailContact = await UserContact.findOneOrFail({ where: { email: bibiBloxberg.email } }) + await userFactory(testEnv, bobBaumeister) + emailContact = await UserContact.findOneOrFail({ where: { email: bobBaumeister.email } }) }) afterAll(async () => { @@ -1140,7 +1140,7 @@ describe('UserResolver', () => { it('throws an error', async () => { jest.clearAllMocks() await expect( - query({ query: queryOptIn, variables: { optIn: 'not-valid' } }), + query({ query: queryOptIn, variables: { email: 'bob@baumeister.de', optIn: 'not-valid' } }), ).resolves.toEqual( expect.objectContaining({ errors: [ @@ -1161,7 +1161,7 @@ describe('UserResolver', () => { await expect( query({ query: queryOptIn, - variables: { optIn: emailContact.emailVerificationCode.toString() }, + variables: { email: 'bob@baumeister.de', optIn: emailContact.emailVerificationCode.toString() }, }), ).resolves.toEqual( expect.objectContaining({ From 67b2506241b9164c06888e5ba2ba5cbfdf5051df Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Nov 2025 14:42:58 +0100 Subject: [PATCH 4/4] update login subtitle text --- frontend/src/locales/de.json | 2 +- frontend/src/locales/en.json | 2 +- frontend/src/locales/es.json | 2 +- frontend/src/locales/fr.json | 2 +- frontend/src/locales/nl.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index e7741f83d..4e9cdfdd5 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -266,7 +266,7 @@ "expiredOn": "Abgelaufen am", "has-account": "Du besitzt bereits ein Gradido Konto?", "header": "Gradidos versenden per Link", - "isFree": "Gradido ist weltweit kostenfrei.", + "isFree": "Gemeinschaftsbasiert – Dezentral – Open Source", "link-and-text-copied": "Der Link und deine Nachricht wurden in die Zwischenablage kopiert. Du kannst ihn jetzt in eine E-Mail oder Nachricht einfügen.", "link-copied": "Link wurde in die Zwischenablage kopiert. Du kannst ihn jetzt in eine E-Mail oder Nachricht einfügen.", "link-deleted": "Der Link wurde am {date} gelöscht.", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index d0ab23d1f..9e96a497b 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -266,7 +266,7 @@ "expiredOn": "Expired on", "has-account": "You already have a Gradido account?", "header": "Send Gradidos via link", - "isFree": "Gradido is free of charge worldwide.", + "isFree": "Community-based – Decentralized – Open Source", "link-and-text-copied": "The link and your message have been copied to the clipboard. You can now include it in an email or message.", "link-copied": "Link has been copied to the clipboard. You can now paste it into an email or message.", "link-deleted": "The link was deleted on {date}.", diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 9a0d4283f..905466540 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -214,7 +214,7 @@ "expiredOn": "Vencido el:", "has-account": "Ya tienes una cuenta Gradido?", "header": "Transferir Gradidos por medio de un enlace", - "isFree": "Gradido es gratis en todo el mundo.", + "isFree": "Comunitario – Descentralizado – Código abierto", "link-and-text-copied": "El enlace y su mensaje se han copiado en el portapapeles. Ahora puedes ponerlo en un correo electrónico o mensaje.", "link-copied": "El enlace se ha copiado en el portapapeles. Ahora puedes pegarlo en un correo electrónico o mensaje.", "link-deleted": "El enlace se eliminó el {date}.", diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index 55bdf4ee3..8024d468e 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -220,7 +220,7 @@ "expiredOn": "A expiré le", "has-account": "Vous avez déjà un compte Gradido?", "header": "Envoyer des Gradidos via lien", - "isFree": "Gradido est gratuit mondialement.", + "isFree": "Communautaire – Décentralisé – Open Source", "link-and-text-copied": "Le lien et votre message ont été copiés dans le presse-papier. Vous pouvez maintenant le joindre à un email ou à un message..", "link-copied": "Le lien a été copié dans le presse-papier. Vous pouvez désormais le coller dans votre email ou votre message.", "link-deleted": "Le lien a été supprimé le on {date}.", diff --git a/frontend/src/locales/nl.json b/frontend/src/locales/nl.json index 9b3f3d265..98eb6d2ad 100644 --- a/frontend/src/locales/nl.json +++ b/frontend/src/locales/nl.json @@ -214,7 +214,7 @@ "expiredOn": "Afgelopen op", "has-account": "Heb je al een Gradido rekening?", "header": "Gradidos per link versturen", - "isFree": "Gradido is gratis wereldwijd.", + "isFree": "Gemeenschappelijk – Decentraal – Open Source", "link-and-text-copied": "De link en jouw bericht werden naar het klembord gekopieerd. Je kunt ze nu in een email of bericht invoegen.", "link-copied": "Link werd naar het klembord gekopieerd. Je kunt deze nu in een email of bericht invoegen.", "link-deleted": "De link werd op {date} verwijderd.",