mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge pull request #1513 from gradido/backend-tests-running-again
fix: Backend Unit Tests Running Again
This commit is contained in:
commit
5efb7115de
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@ -431,7 +431,7 @@ jobs:
|
||||
unit_test_backend:
|
||||
name: Unit tests - Backend
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_test_backend,build_test_mariadb]
|
||||
needs: [build_test_mariadb]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
@ -448,13 +448,6 @@ jobs:
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/mariadb.tar
|
||||
- name: Download Docker Image (Backend)
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/backend.tar
|
||||
##########################################################################
|
||||
# UNIT TESTS BACKEND #####################################################
|
||||
##########################################################################
|
||||
@ -469,7 +462,7 @@ jobs:
|
||||
run: sleep 30s
|
||||
shell: bash
|
||||
- name: backend Unit tests | test
|
||||
run: cd database && yarn && yarn build && cd ../backend && yarn && yarn CI_workflow_test
|
||||
run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
|
||||
# run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn test
|
||||
##########################################################################
|
||||
# COVERAGE CHECK BACKEND #################################################
|
||||
@ -480,7 +473,7 @@ jobs:
|
||||
report_name: Coverage Backend
|
||||
type: lcov
|
||||
result_path: ./backend/coverage/lcov.info
|
||||
min_coverage: 38
|
||||
min_coverage: 48
|
||||
token: ${{ github.token }}
|
||||
|
||||
##########################################################################
|
||||
|
||||
@ -1,21 +1,18 @@
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = async () => {
|
||||
process.env.TZ = 'UTC'
|
||||
return {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**'],
|
||||
moduleNameMapper: {
|
||||
'@entity/(.*)': '<rootDir>/../database/build/entity/$1',
|
||||
// This is hack to fix a problem with the library `ts-mysql-migrate` which does differentiate between its ts/js state
|
||||
'@dbTools/(.*)': '<rootDir>/../database/src/$1',
|
||||
/*
|
||||
'@dbTools/(.*)':
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/src/$1'
|
||||
: '<rootDir>/../database/build/src/$1',
|
||||
*/
|
||||
},
|
||||
}
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**'],
|
||||
setupFiles: ['<rootDir>/test/testSetup.ts'],
|
||||
moduleNameMapper: {
|
||||
'@entity/(.*)':
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/entity/$1'
|
||||
: '<rootDir>/../database/build/entity/$1',
|
||||
'@dbTools/(.*)':
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/src/$1'
|
||||
: '<rootDir>/../database/build/src/$1',
|
||||
},
|
||||
}
|
||||
|
||||
@ -13,8 +13,7 @@
|
||||
"start": "node build/index.js",
|
||||
"dev": "nodemon -w src --ext ts --exec ts-node src/index.ts",
|
||||
"lint": "eslint . --ext .js,.ts",
|
||||
"CI_workflow_test": "jest --runInBand --coverage ",
|
||||
"test": "NODE_ENV=development jest --runInBand --coverage "
|
||||
"test": "TZ=UTC NODE_ENV=development jest --runInBand --coverage --forceExit --detectOpenHandles"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
|
||||
@ -6,14 +6,13 @@ import gql from 'graphql-tag'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import createServer from '../../server/createServer'
|
||||
import { resetDB, initialize } from '@dbTools/helpers'
|
||||
import { getRepository } from 'typeorm'
|
||||
import { LoginUser } from '@entity/LoginUser'
|
||||
import { LoginUserBackup } from '@entity/LoginUserBackup'
|
||||
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
|
||||
import { User } from '@entity/User'
|
||||
import CONFIG from '../../config'
|
||||
import { sendAccountActivationEmail } from '../../mailer/sendAccountActivationEmail'
|
||||
import { klicktippSignIn } from '../../apis/KlicktippController'
|
||||
// import { klicktippSignIn } from '../../apis/KlicktippController'
|
||||
|
||||
jest.setTimeout(10000)
|
||||
|
||||
jest.mock('../../mailer/sendAccountActivationEmail', () => {
|
||||
return {
|
||||
@ -22,12 +21,14 @@ jest.mock('../../mailer/sendAccountActivationEmail', () => {
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
jest.mock('../../apis/KlicktippController', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
klicktippSignIn: jest.fn(),
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
let mutate: any
|
||||
let con: any
|
||||
@ -40,6 +41,11 @@ beforeAll(async () => {
|
||||
await resetDB()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await resetDB(true)
|
||||
await con.close()
|
||||
})
|
||||
|
||||
describe('UserResolver', () => {
|
||||
describe('createUser', () => {
|
||||
const variables = {
|
||||
@ -84,70 +90,32 @@ describe('UserResolver', () => {
|
||||
})
|
||||
|
||||
describe('valid input data', () => {
|
||||
let loginUser: LoginUser[]
|
||||
let user: User[]
|
||||
let loginUserBackup: LoginUserBackup[]
|
||||
let loginEmailOptIn: LoginEmailOptIn[]
|
||||
beforeAll(async () => {
|
||||
loginUser = await getRepository(LoginUser).createQueryBuilder('login_user').getMany()
|
||||
user = await getRepository(User).createQueryBuilder('state_user').getMany()
|
||||
loginUserBackup = await getRepository(LoginUserBackup)
|
||||
.createQueryBuilder('login_user_backup')
|
||||
.getMany()
|
||||
loginEmailOptIn = await getRepository(LoginEmailOptIn)
|
||||
.createQueryBuilder('login_email_optin')
|
||||
.getMany()
|
||||
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(loginUser).toEqual([
|
||||
expect(user).toEqual([
|
||||
{
|
||||
id: expect.any(Number),
|
||||
email: 'peter@lustig.de',
|
||||
firstName: 'Peter',
|
||||
lastName: 'Lustig',
|
||||
username: '',
|
||||
description: '',
|
||||
password: '0',
|
||||
pubKey: null,
|
||||
privKey: null,
|
||||
emailHash: expect.any(Buffer),
|
||||
createdAt: expect.any(Date),
|
||||
emailChecked: false,
|
||||
passphraseShown: false,
|
||||
language: 'de',
|
||||
disabled: false,
|
||||
groupId: 1,
|
||||
publisherId: 1234,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('saves the user in state_user table', () => {
|
||||
expect(user).toEqual([
|
||||
{
|
||||
id: expect.any(Number),
|
||||
indexId: 0,
|
||||
groupId: 0,
|
||||
pubkey: expect.any(Buffer),
|
||||
email: 'peter@lustig.de',
|
||||
firstName: 'Peter',
|
||||
lastName: 'Lustig',
|
||||
username: '',
|
||||
disabled: false,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('saves the user in login_user_backup table', () => {
|
||||
expect(loginUserBackup).toEqual([
|
||||
{
|
||||
id: expect.any(Number),
|
||||
passphrase: expect.any(String),
|
||||
userId: loginUser[0].id,
|
||||
mnemonicType: 2,
|
||||
language: 'de',
|
||||
deletedAt: null,
|
||||
publisherId: 1234,
|
||||
},
|
||||
])
|
||||
})
|
||||
@ -156,7 +124,7 @@ describe('UserResolver', () => {
|
||||
expect(loginEmailOptIn).toEqual([
|
||||
{
|
||||
id: expect.any(Number),
|
||||
userId: loginUser[0].id,
|
||||
userId: user[0].id,
|
||||
verificationCode: expect.any(String),
|
||||
emailOptInTypeId: 1,
|
||||
createdAt: expect.any(Date),
|
||||
@ -196,9 +164,7 @@ describe('UserResolver', () => {
|
||||
mutation,
|
||||
variables: { ...variables, email: 'bibi@bloxberg.de', language: 'es' },
|
||||
})
|
||||
await expect(
|
||||
getRepository(LoginUser).createQueryBuilder('login_user').getMany(),
|
||||
).resolves.toEqual(
|
||||
await expect(User.find()).resolves.toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
email: 'bibi@bloxberg.de',
|
||||
@ -215,9 +181,7 @@ describe('UserResolver', () => {
|
||||
mutation,
|
||||
variables: { ...variables, email: 'raeuber@hotzenplotz.de', publisherId: undefined },
|
||||
})
|
||||
await expect(
|
||||
getRepository(LoginUser).createQueryBuilder('login_user').getMany(),
|
||||
).resolves.toEqual(
|
||||
await expect(User.find()).resolves.toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
email: 'raeuber@hotzenplotz.de',
|
||||
@ -265,23 +229,17 @@ describe('UserResolver', () => {
|
||||
let emailOptIn: string
|
||||
|
||||
describe('valid optin code and valid password', () => {
|
||||
let loginUser: any
|
||||
let newLoginUser: any
|
||||
let newUser: any
|
||||
|
||||
beforeAll(async () => {
|
||||
await mutate({ mutation: createUserMutation, variables: createUserVariables })
|
||||
const loginEmailOptIn = await getRepository(LoginEmailOptIn)
|
||||
.createQueryBuilder('login_email_optin')
|
||||
.getMany()
|
||||
loginUser = await getRepository(LoginUser).createQueryBuilder('login_user').getMany()
|
||||
const loginEmailOptIn = await LoginEmailOptIn.find()
|
||||
emailOptIn = loginEmailOptIn[0].verificationCode.toString()
|
||||
result = await mutate({
|
||||
mutation: setPasswordMutation,
|
||||
variables: { code: emailOptIn, password: 'Aa12345_' },
|
||||
})
|
||||
newLoginUser = await getRepository(LoginUser).createQueryBuilder('login_user').getMany()
|
||||
newUser = await getRepository(User).createQueryBuilder('state_user').getMany()
|
||||
newUser = await User.find()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
@ -289,38 +247,27 @@ describe('UserResolver', () => {
|
||||
})
|
||||
|
||||
it('sets email checked to true', () => {
|
||||
expect(newLoginUser[0].emailChecked).toBeTruthy()
|
||||
expect(newUser[0].emailChecked).toBeTruthy()
|
||||
})
|
||||
|
||||
it('updates the password', () => {
|
||||
expect(newLoginUser[0].password).toEqual('3917921995996627700')
|
||||
})
|
||||
|
||||
it('updates the public Key on both user tables', () => {
|
||||
expect(newLoginUser[0].pubKey).toEqual(expect.any(Buffer))
|
||||
expect(newLoginUser[0].pubKey).not.toEqual(loginUser[0].pubKey)
|
||||
expect(newLoginUser[0].pubKey).toEqual(newUser[0].pubkey)
|
||||
})
|
||||
|
||||
it('updates the private Key', () => {
|
||||
expect(newLoginUser[0].privKey).toEqual(expect.any(Buffer))
|
||||
expect(newLoginUser[0].privKey).not.toEqual(loginUser[0].privKey)
|
||||
expect(newUser[0].password).toEqual('3917921995996627700')
|
||||
})
|
||||
|
||||
it('removes the optin', async () => {
|
||||
await expect(
|
||||
getRepository(LoginEmailOptIn).createQueryBuilder('login_email_optin').getMany(),
|
||||
).resolves.toHaveLength(0)
|
||||
await expect(LoginEmailOptIn.find()).resolves.toHaveLength(0)
|
||||
})
|
||||
|
||||
/*
|
||||
it('calls the klicktipp API', () => {
|
||||
expect(klicktippSignIn).toBeCalledWith(
|
||||
loginUser[0].email,
|
||||
loginUser[0].language,
|
||||
loginUser[0].firstName,
|
||||
loginUser[0].lastName,
|
||||
user[0].email,
|
||||
user[0].language,
|
||||
user[0].firstName,
|
||||
user[0].lastName,
|
||||
)
|
||||
})
|
||||
*/
|
||||
|
||||
it('returns true', () => {
|
||||
expect(result).toBeTruthy()
|
||||
@ -330,9 +277,7 @@ describe('UserResolver', () => {
|
||||
describe('no valid password', () => {
|
||||
beforeAll(async () => {
|
||||
await mutate({ mutation: createUserMutation, variables: createUserVariables })
|
||||
const loginEmailOptIn = await getRepository(LoginEmailOptIn)
|
||||
.createQueryBuilder('login_email_optin')
|
||||
.getMany()
|
||||
const loginEmailOptIn = await LoginEmailOptIn.find()
|
||||
emailOptIn = loginEmailOptIn[0].verificationCode.toString()
|
||||
result = await mutate({
|
||||
mutation: setPasswordMutation,
|
||||
@ -380,8 +325,3 @@ describe('UserResolver', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await resetDB(true)
|
||||
await con.close()
|
||||
})
|
||||
@ -4,40 +4,42 @@
|
||||
import { ApolloLogPlugin, LogMutateData } from 'apollo-log'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
|
||||
const plugins = [
|
||||
{
|
||||
requestDidStart() {
|
||||
return {
|
||||
willSendResponse(requestContext: any) {
|
||||
const { setHeaders = [] } = requestContext.context
|
||||
setHeaders.forEach(({ key, value }: { [key: string]: string }) => {
|
||||
if (requestContext.response.http.headers.get(key)) {
|
||||
requestContext.response.http.headers.set(key, value)
|
||||
} else {
|
||||
requestContext.response.http.headers.append(key, value)
|
||||
}
|
||||
})
|
||||
return requestContext
|
||||
},
|
||||
}
|
||||
},
|
||||
const setHeadersPlugin = {
|
||||
requestDidStart() {
|
||||
return {
|
||||
willSendResponse(requestContext: any) {
|
||||
const { setHeaders = [] } = requestContext.context
|
||||
setHeaders.forEach(({ key, value }: { [key: string]: string }) => {
|
||||
if (requestContext.response.http.headers.get(key)) {
|
||||
requestContext.response.http.headers.set(key, value)
|
||||
} else {
|
||||
requestContext.response.http.headers.append(key, value)
|
||||
}
|
||||
})
|
||||
return requestContext
|
||||
},
|
||||
}
|
||||
},
|
||||
ApolloLogPlugin({
|
||||
mutate: (data: LogMutateData) => {
|
||||
// We need to deep clone the object in order to not modify the actual request
|
||||
const dataCopy = cloneDeep(data)
|
||||
}
|
||||
|
||||
// mask password if part of the query
|
||||
if (dataCopy.context.request.variables && dataCopy.context.request.variables.password) {
|
||||
dataCopy.context.request.variables.password = '***'
|
||||
}
|
||||
const apolloLogPlugin = ApolloLogPlugin({
|
||||
mutate: (data: LogMutateData) => {
|
||||
// We need to deep clone the object in order to not modify the actual request
|
||||
const dataCopy = cloneDeep(data)
|
||||
|
||||
// mask token at all times
|
||||
dataCopy.context.context.token = '***'
|
||||
// mask password if part of the query
|
||||
if (dataCopy.context.request.variables && dataCopy.context.request.variables.password) {
|
||||
dataCopy.context.request.variables.password = '***'
|
||||
}
|
||||
|
||||
return dataCopy
|
||||
},
|
||||
}),
|
||||
]
|
||||
// mask token at all times
|
||||
dataCopy.context.context.token = '***'
|
||||
|
||||
return dataCopy
|
||||
},
|
||||
})
|
||||
|
||||
const plugins =
|
||||
process.env.NODE_ENV === 'development' ? [setHeadersPlugin] : [setHeadersPlugin, apolloLogPlugin]
|
||||
|
||||
export default plugins
|
||||
|
||||
6
backend/test/testSetup.ts
Normal file
6
backend/test/testSetup.ts
Normal file
@ -0,0 +1,6 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
// disable console.info for apollo log
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
console.info = () => {}
|
||||
@ -5,19 +5,20 @@
|
||||
* This also removes the trailing space
|
||||
*/
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
const TARGET_MNEMONIC_TYPE = 2
|
||||
const PHRASE_WORD_COUNT = 24
|
||||
const WORDS_MNEMONIC_0 = fs
|
||||
.readFileSync('src/config/mnemonic.uncompressed_buffer18112.txt')
|
||||
.readFileSync(path.resolve(__dirname, '../src/config/mnemonic.uncompressed_buffer18112.txt'))
|
||||
.toString()
|
||||
.split(',')
|
||||
const WORDS_MNEMONIC_1 = fs
|
||||
.readFileSync('src/config/mnemonic.uncompressed_buffer18113.txt')
|
||||
.readFileSync(path.resolve(__dirname, '../src/config/mnemonic.uncompressed_buffer18113.txt'))
|
||||
.toString()
|
||||
.split(',')
|
||||
const WORDS_MNEMONIC_2 = fs
|
||||
.readFileSync('src/config/mnemonic.uncompressed_buffer13116.txt')
|
||||
.readFileSync(path.resolve(__dirname, '../src/config/mnemonic.uncompressed_buffer13116.txt'))
|
||||
.toString()
|
||||
.split(',')
|
||||
const WORDS_MNEMONIC = [WORDS_MNEMONIC_0, WORDS_MNEMONIC_1, WORDS_MNEMONIC_2]
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
"license": "MIT",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"build": "tsc --build",
|
||||
"build": "mkdir -p build/src/config/ && cp src/config/*.txt build/src/config/ && tsc --build",
|
||||
"clean": "tsc --build --clean",
|
||||
"up": "node build/src/index.js up",
|
||||
"down": "node build/src/index.js down",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user