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": [ "testMatch": [
"<rootDir>/**/*.test.ts" "<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/express": "^4.17.13",
"@types/jest": "^26.0.24", "@types/jest": "^26.0.24",
"@types/node": "^16.3.3", "@types/node": "^16.3.3",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^4.28.4", "@typescript-eslint/eslint-plugin": "^4.28.4",
"@typescript-eslint/parser": "^4.28.4", "@typescript-eslint/parser": "^4.28.4",
"eslint": "^7.31.0", "eslint": "^7.31.0",
@ -31,6 +32,8 @@
"eslint-plugin-import": "^2.23.4", "eslint-plugin-import": "^2.23.4",
"husky": "^7.0.0", "husky": "^7.0.0",
"jest": "^27.0.6", "jest": "^27.0.6",
"mock-firebase-ts": "^2.6.2",
"supertest": "^6.1.4",
"ts-jest": "^27.0.3", "ts-jest": "^27.0.3",
"ts-node-dev": "^1.1.8", "ts-node-dev": "^1.1.8",
"typescript": "^4.3.5" "typescript": "^4.3.5"

View file

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

View file

@ -1,16 +1,16 @@
import { bodySchemaValidator } from '../../common/middlewares/bodySchemaValidator' import { bodySchemaValidator } from '../../common/middlewares/bodySchemaValidator'
import { translationController } from './translationController' import { translationController } from './translationController'
import { translationModel } from './translationModel'
import validator from '../../common/services/validatorService' import validator from '../../common/services/validatorService'
import { translateBody } from './schemas' import { translateBody } from './schemas'
import { Router } from 'express' import { Router } from 'express'
import config from '../../config' import { TranslationModel } from './interfaces/translationModel'
import axios from 'axios'
const router = Router() const router = (model: TranslationModel) => {
const model = translationModel(axios, { key: config.deepl.key, url: config.deepl.url }) const router = Router()
router.post('/', bodySchemaValidator(translateBody, validator), translationController(model));
return router
}
router.post('/', bodySchemaValidator(translateBody, validator), translationController(model));
export default router 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 express, { NextFunction, Request, Response } from 'express'
import authMiddleware from './common/middlewares/authMiddleware' import authMiddleware from './common/middlewares/authMiddleware'
import translationRouter from './components/translation/router'
import { errorService } from './common/services/errorService' import { errorService } from './common/services/errorService'
import sentenceRouter from './components/sentences/router' import sentenceRouter from './components/sentences/router'
import translationRouter from './components/translation/router'
import viewsRouter from './components/view/router' import viewsRouter from './components/view/router'
import config from './config' import config from './config'
import axios from 'axios'
import db from './db'
const { handle } = errorService() const { handle } = errorService()
const app = express() const app = express()
app.set('view engine', 'ejs') app.set('view engine', 'ejs')
app.set('views', process.cwd() + '/src/views') app.set('views', process.cwd() + '/src/views')
app.use(express.json()) app.use(express.json())
app.use(express.urlencoded({ extended: false })) app.use(express.urlencoded({ extended: false }))
// translation api // 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 // 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 // Public views
app.use('/public', viewsRouter) app.use('/public', viewsRouter)
// Redirect to home page // Redirect to home page

View file

@ -1,5 +1,28 @@
describe('Dummy tests', () => { import sentencesData from './mock/sentences'
it('1 + 1 equals 2', () => { import supertest from 'supertest'
expect(1 + 1).toBe(2); 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