mirror of
https://codeberg.org/JasterV/sentences-crud.git
synced 2026-04-26 18:10:05 +00:00
test setup done
This commit is contained in:
parent
09ae5f8d2e
commit
551e04da13
12 changed files with 1035 additions and 66 deletions
|
|
@ -7,7 +7,5 @@
|
||||||
],
|
],
|
||||||
"testMatch": [
|
"testMatch": [
|
||||||
"<rootDir>/**/*.test.ts"
|
"<rootDir>/**/*.test.ts"
|
||||||
],
|
]
|
||||||
"resetMocks": true,
|
|
||||||
"clearMocks": true
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
959
package-lock.json
generated
959
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
9
test/mock/axios.ts
Normal 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
9
test/mock/config.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
const mockConfig = {
|
||||||
|
deepl: {
|
||||||
|
key: 'mockKey',
|
||||||
|
url: 'mockUrl'
|
||||||
|
},
|
||||||
|
secret: 'patata'
|
||||||
|
}
|
||||||
|
|
||||||
|
export { mockConfig }
|
||||||
11
test/mock/firebase.ts
Normal file
11
test/mock/firebase.ts
Normal 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
4
test/mock/sentences.ts
Normal 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
27
test/setup/app.ts
Normal 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
|
||||||
Loading…
Reference in a new issue