test setup done

This commit is contained in:
JasterV 2021-07-25 16:15:39 +02:00
parent 09ae5f8d2e
commit 551e04da13
12 changed files with 1035 additions and 66 deletions

View file

@ -7,7 +7,5 @@
],
"testMatch": [
"<rootDir>/**/*.test.ts"
],
"resetMocks": true,
"clearMocks": true
]
}

959
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,7 @@
"@types/express": "^4.17.13",
"@types/jest": "^26.0.24",
"@types/node": "^16.3.3",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^4.28.4",
"@typescript-eslint/parser": "^4.28.4",
"eslint": "^7.31.0",
@ -31,6 +32,8 @@
"eslint-plugin-import": "^2.23.4",
"husky": "^7.0.0",
"jest": "^27.0.6",
"mock-firebase-ts": "^2.6.2",
"supertest": "^6.1.4",
"ts-jest": "^27.0.3",
"ts-node-dev": "^1.1.8",
"typescript": "^4.3.5"

View file

@ -2,7 +2,6 @@ import { bodySchemaValidator } from '../../common/middlewares/bodySchemaValidato
import { querySchemaValidator } from '../../common/middlewares/querySchemaValidator'
import { createSchema, listSchema, updateSchema } from './schemas'
import validator from '../../common/services/validatorService'
import { sentenceModel } from './sentenceModel'
import { Router } from 'express'
import {
createSentenceController,
@ -11,16 +10,18 @@ import {
listSentencesController,
getSentenceController
} from './controllers'
import db from '../../db'
import { CrudModel } from './interfaces/crudModel'
import { Sentence } from './interfaces/sentence'
const router = Router()
const model = sentenceModel(db)
router.get('/:id', getSentenceController(model))
router.get('/', querySchemaValidator(listSchema, validator), listSentencesController(model))
router.post('/', bodySchemaValidator(createSchema, validator), createSentenceController(model))
router.put('/:id', bodySchemaValidator(updateSchema, validator), updateSentenceController(model))
router.delete('/:id', deleteSentenceController(model))
const router = (model: CrudModel<Sentence>) => {
const router = Router()
router.get('/:id', getSentenceController(model))
router.get('/', querySchemaValidator(listSchema, validator), listSentencesController(model))
router.post('/', bodySchemaValidator(createSchema, validator), createSentenceController(model))
router.put('/:id', bodySchemaValidator(updateSchema, validator), updateSentenceController(model))
router.delete('/:id', deleteSentenceController(model))
return router
}
export default router

View file

@ -1,16 +1,16 @@
import { bodySchemaValidator } from '../../common/middlewares/bodySchemaValidator'
import { translationController } from './translationController'
import { translationModel } from './translationModel'
import validator from '../../common/services/validatorService'
import { translateBody } from './schemas'
import { Router } from 'express'
import config from '../../config'
import axios from 'axios'
import { TranslationModel } from './interfaces/translationModel'
const router = Router()
const model = translationModel(axios, { key: config.deepl.key, url: config.deepl.url })
const router = (model: TranslationModel) => {
const router = Router()
router.post('/', bodySchemaValidator(translateBody, validator), translationController(model));
return router
}
router.post('/', bodySchemaValidator(translateBody, validator), translationController(model));
export default router

View file

@ -1,24 +1,31 @@
import { translationModel } from './components/translation/translationModel'
import { sentenceModel } from './components/sentences/sentenceModel'
import express, { NextFunction, Request, Response } from 'express'
import authMiddleware from './common/middlewares/authMiddleware'
import translationRouter from './components/translation/router'
import { errorService } from './common/services/errorService'
import sentenceRouter from './components/sentences/router'
import translationRouter from './components/translation/router'
import viewsRouter from './components/view/router'
import config from './config'
import axios from 'axios'
import db from './db'
const { handle } = errorService()
const app = express()
app.set('view engine', 'ejs')
app.set('views', process.cwd() + '/src/views')
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
// translation api
app.use('/api/v1/translate', authMiddleware(config.secret), translationRouter)
const trModel = translationModel(axios, { key: config.deepl.key, url: config.deepl.url })
app.use('/api/v1/translate', authMiddleware(config.secret), translationRouter(trModel))
// sentences api
app.use('/api/v1/sentences', authMiddleware(config.secret), sentenceRouter)
const sModel = sentenceModel(db)
app.use('/api/v1/sentences', authMiddleware(config.secret), sentenceRouter(sModel))
// Public views
app.use('/public', viewsRouter)
// Redirect to home page

View file

@ -1,5 +1,28 @@
describe('Dummy tests', () => {
it('1 + 1 equals 2', () => {
expect(1 + 1).toBe(2);
import sentencesData from './mock/sentences'
import supertest from 'supertest'
import app from './setup/app'
import { mockDb } from './mock/firebase'
import { mockConfig } from './mock/config'
const request = supertest(app)
beforeAll(() => {
// Create a fake Firestore with sentences
mockDb.mocker.loadCollection('sentences', sentencesData)
})
describe('Test sentences api', () => {
it('can get sentence by Id', async () => {
expect.assertions(1)
const sentence = sentencesData['abc123']
const result = await request
.get('/api/v1/sentences/abc123')
.set('Authorization', `Bearer ${mockConfig.secret}`)
expect(result.body).toMatchObject({
success: true,
data: expect.objectContaining(sentence)
})
});
});

9
test/mock/axios.ts Normal file
View file

@ -0,0 +1,9 @@
jest.mock('axios')
import axios from 'axios'
const mockAxios = axios as jest.Mocked<typeof axios>
mockAxios.create.mockReturnThis()
export { mockAxios }

9
test/mock/config.ts Normal file
View file

@ -0,0 +1,9 @@
const mockConfig = {
deepl: {
key: 'mockKey',
url: 'mockUrl'
},
secret: 'patata'
}
export { mockConfig }

11
test/mock/firebase.ts Normal file
View file

@ -0,0 +1,11 @@
import admin from 'firebase-admin';
import { mockFirebaseAdmin } from 'mock-firebase-ts';
const firebaseAdmin = mockFirebaseAdmin();
const app = firebaseAdmin.initializeApp({})
export const mockDb = app.firestore()

4
test/mock/sentences.ts Normal file
View file

@ -0,0 +1,4 @@
export default {
'abc123': { text: 'Homer Simpson', category: 'humor' },
'abc456': { text: 'Lisa Simpson', category: 'humor' },
}

27
test/setup/app.ts Normal file
View file

@ -0,0 +1,27 @@
import { translationModel } from '../../src/components/translation/translationModel'
import { sentenceModel } from '../../src/components/sentences/sentenceModel'
import authMiddleware from '../../src/common/middlewares/authMiddleware'
import translationRouter from '../../src/components/translation/router'
import { errorService } from '../../src/common/services/errorService'
import sentenceRouter from '../../src/components/sentences/router'
import express, { Request, Response, NextFunction } from 'express'
import { mockConfig } from '../mock/config'
import { mockAxios } from '../mock/axios'
import { mockDb } from '../mock/firebase'
const { handle } = errorService()
const app = express()
app.use(express.json())
// translation api
const trModel = translationModel(mockAxios, { key: mockConfig.deepl.key, url: mockConfig.deepl.url })
app.use('/api/v1/translate', authMiddleware('patata'), translationRouter(trModel))
// sentences api
const sModel = sentenceModel(mockDb as any)
app.use('/api/v1/sentences', authMiddleware(mockConfig.secret), sentenceRouter(sModel))
// Api error handling
app.use('/api/v1', (err: Error, _req: Request, res: Response, _next: NextFunction) => handle(err, res))
export default app