/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { testEnvironment, headerPushMock, resetToken, cleanDB } from '@test/helpers' import { userFactory } from '@/seeds/factory/user' import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' import { createUser, setPassword } from '@/seeds/graphql/mutations' import { login, logout } from '@/seeds/graphql/queries' import { GraphQLError } from 'graphql' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { User } from '@entity/User' import CONFIG from '@/config' import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail' import { printTimeDuration } from './UserResolver' // import { klicktippSignIn } from '@/apis/KlicktippController' jest.mock('@/mailer/sendAccountActivationEmail', () => { return { __esModule: true, sendAccountActivationEmail: jest.fn(), } }) /* jest.mock('@/apis/KlicktippController', () => { return { __esModule: true, klicktippSignIn: jest.fn(), } }) */ let mutate: any, query: any, con: any let testEnv: any beforeAll(async () => { testEnv = await testEnvironment() mutate = testEnv.mutate query = testEnv.query con = testEnv.con await cleanDB() }) afterAll(async () => { await cleanDB() await con.close() }) describe('UserResolver', () => { describe('createUser', () => { const variables = { email: 'peter@lustig.de', firstName: 'Peter', lastName: 'Lustig', language: 'de', publisherId: 1234, } let result: any let emailOptIn: string beforeAll(async () => { jest.clearAllMocks() result = await mutate({ mutation: createUser, variables }) }) afterAll(async () => { await cleanDB() }) it('returns success', () => { expect(result).toEqual( expect.objectContaining({ data: { createUser: { id: expect.any(Number) } } }), ) }) describe('valid input data', () => { let user: User[] let loginEmailOptIn: LoginEmailOptIn[] beforeAll(async () => { user = await User.find() loginEmailOptIn = await LoginEmailOptIn.find() emailOptIn = loginEmailOptIn[0].verificationCode.toString() }) describe('filling all tables', () => { it('saves the user in login_user table', () => { expect(user).toEqual([ { id: expect.any(Number), email: 'peter@lustig.de', firstName: 'Peter', lastName: 'Lustig', password: '0', pubKey: null, privKey: null, emailHash: expect.any(Buffer), createdAt: expect.any(Date), emailChecked: false, passphrase: expect.any(String), language: 'de', deletedAt: null, publisherId: 1234, referrerId: null, }, ]) }) it('creates an email optin', () => { expect(loginEmailOptIn).toEqual([ { id: expect.any(Number), userId: user[0].id, verificationCode: expect.any(String), emailOptInTypeId: 1, createdAt: expect.any(Date), resendCount: 0, updatedAt: expect.any(Date), }, ]) }) }) }) describe('account activation email', () => { it('sends an account activation email', () => { const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace( /{optin}/g, emailOptIn, ).replace(/{code}/g, '') expect(sendAccountActivationEmail).toBeCalledWith({ link: activationLink, firstName: 'Peter', lastName: 'Lustig', email: 'peter@lustig.de', duration: expect.any(String), }) }) }) describe('email already exists', () => { it('throws an error', async () => { await expect(mutate({ mutation: createUser, variables })).resolves.toEqual( expect.objectContaining({ errors: [new GraphQLError('User already exists.')], }), ) }) }) describe('unknown language', () => { it('sets "de" as default language', async () => { await mutate({ mutation: createUser, variables: { ...variables, email: 'bibi@bloxberg.de', language: 'es' }, }) await expect(User.find()).resolves.toEqual( expect.arrayContaining([ expect.objectContaining({ email: 'bibi@bloxberg.de', language: 'de', }), ]), ) }) }) describe('no publisher id', () => { it('sets publisher id to null', async () => { await mutate({ mutation: createUser, variables: { ...variables, email: 'raeuber@hotzenplotz.de', publisherId: undefined }, }) await expect(User.find()).resolves.toEqual( expect.arrayContaining([ expect.objectContaining({ email: 'raeuber@hotzenplotz.de', publisherId: null, }), ]), ) }) }) }) describe('setPassword', () => { const createUserVariables = { email: 'peter@lustig.de', firstName: 'Peter', lastName: 'Lustig', language: 'de', publisherId: 1234, } let result: any let emailOptIn: string describe('valid optin code and valid password', () => { let newUser: any beforeAll(async () => { await mutate({ mutation: createUser, variables: createUserVariables }) const loginEmailOptIn = await LoginEmailOptIn.find() emailOptIn = loginEmailOptIn[0].verificationCode.toString() result = await mutate({ mutation: setPassword, variables: { code: emailOptIn, password: 'Aa12345_' }, }) newUser = await User.find() }) afterAll(async () => { await cleanDB() }) it('sets email checked to true', () => { expect(newUser[0].emailChecked).toBeTruthy() }) it('updates the password', () => { expect(newUser[0].password).toEqual('3917921995996627700') }) it('removes the optin', async () => { await expect(LoginEmailOptIn.find()).resolves.toHaveLength(0) }) /* it('calls the klicktipp API', () => { expect(klicktippSignIn).toBeCalledWith( user[0].email, user[0].language, user[0].firstName, user[0].lastName, ) }) */ it('returns true', () => { expect(result).toBeTruthy() }) }) describe('no valid password', () => { beforeAll(async () => { await mutate({ mutation: createUser, variables: createUserVariables }) const loginEmailOptIn = await LoginEmailOptIn.find() emailOptIn = loginEmailOptIn[0].verificationCode.toString() result = await mutate({ mutation: setPassword, variables: { code: emailOptIn, password: 'not-valid' }, }) }) afterAll(async () => { await cleanDB() }) it('throws an error', () => { expect(result).toEqual( expect.objectContaining({ errors: [ new GraphQLError( 'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!', ), ], }), ) }) }) describe('no valid optin code', () => { beforeAll(async () => { await mutate({ mutation: createUser, variables: createUserVariables }) result = await mutate({ mutation: setPassword, variables: { code: 'not valid', password: 'Aa12345_' }, }) }) afterAll(async () => { await cleanDB() }) it('throws an error', () => { expect(result).toEqual( expect.objectContaining({ errors: [new GraphQLError('Could not login with emailVerificationCode')], }), ) }) }) }) describe('login', () => { const variables = { email: 'bibi@bloxberg.de', password: 'Aa12345_', publisherId: 1234, } let result: User afterAll(async () => { await cleanDB() }) describe('no users in database', () => { beforeAll(async () => { result = await query({ query: login, variables }) }) it('throws an error', () => { expect(result).toEqual( expect.objectContaining({ errors: [new GraphQLError('No user with this credentials')], }), ) }) }) describe('user is in database and correct login data', () => { beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) result = await query({ query: login, variables }) }) afterAll(async () => { await cleanDB() }) it('returns the user object', () => { expect(result).toEqual( expect.objectContaining({ data: { login: { coinanimation: true, email: 'bibi@bloxberg.de', firstName: 'Bibi', hasElopage: false, id: expect.any(Number), isAdmin: false, klickTipp: { newsletterState: false, }, language: 'de', lastName: 'Bloxberg', publisherId: 1234, }, }, }), ) }) it('sets the token in the header', () => { expect(headerPushMock).toBeCalledWith({ key: 'token', value: expect.any(String) }) }) }) describe('user is in database and wrong password', () => { beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) }) afterAll(async () => { await cleanDB() }) it('returns an error', () => { expect( query({ query: login, variables: { ...variables, password: 'wrong' } }), ).resolves.toEqual( expect.objectContaining({ errors: [new GraphQLError('No user with this credentials')], }), ) }) }) }) describe('logout', () => { describe('unauthenticated', () => { it('throws an error', async () => { resetToken() await expect(query({ query: logout })).resolves.toEqual( expect.objectContaining({ errors: [new GraphQLError('401 Unauthorized')], }), ) }) }) describe('authenticated', () => { const variables = { email: 'bibi@bloxberg.de', password: 'Aa12345_', } beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) await query({ query: login, variables }) }) afterAll(async () => { await cleanDB() }) it('returns true', async () => { await expect(query({ query: logout })).resolves.toEqual( expect.objectContaining({ data: { logout: 'true' }, errors: undefined, }), ) }) }) }) }) describe('printTimeDuration', () => { it('works with 10 minutes', () => { expect(printTimeDuration(10)).toBe('10 minutes') }) it('works with 1440 minutes', () => { expect(printTimeDuration(1440)).toBe('24 hours') }) it('works with 1410 minutes', () => { expect(printTimeDuration(1410)).toBe('23 hours and 30 minutes') }) })