Squashed commit of the following:
commit c0148e8301b9d2a987c79d8f49f90e678c75e5a4 Author: Roberto Tonino <roberto.tonino5@gmail.com> Date: Fri Apr 9 21:06:02 2021 +0200 test: disabled logger when in test mode; refactor: type names commit 418fc5647f2adb97df312eed5eb9c2d17de9d24c Author: Roberto Tonino <roberto.tonino5@gmail.com> Date: Fri Apr 9 20:49:54 2021 +0200 test: added albumSearch test; chore: removed sample endpoint commit e2c79f6ee65448b92714bffd5281072279e0b522 Author: Roberto Tonino <roberto.tonino5@gmail.com> Date: Fri Apr 9 19:16:25 2021 +0200 test: added cookie parser test commit 78d70b7369015cd467f684e636c6788b58c54a7a Author: Roberto Tonino <roberto.tonino5@gmail.com> Date: Fri Apr 9 19:07:44 2021 +0200 feat: added root path first test commit eb91ff06d62d81fbfa6851f1dea374addf709582 Author: Roberto Tonino <roberto.tonino5@gmail.com> Date: Fri Apr 9 18:45:32 2021 +0200 feat: added test deps
This commit is contained in:
parent
9800edf68d
commit
29c84cf8b9
@ -3,5 +3,8 @@ NODE_BIN ?= .\node_modules\.bin
|
|||||||
lint:
|
lint:
|
||||||
@$(NODE_BIN)\eslint ./src/** --fix
|
@$(NODE_BIN)\eslint ./src/** --fix
|
||||||
|
|
||||||
build: lint
|
test:
|
||||||
|
@$(NODE_BIN)\jest
|
||||||
|
|
||||||
|
build: lint test
|
||||||
@$(NODE_BIN)\tsc
|
@$(NODE_BIN)\tsc
|
||||||
|
6
server/jest.config.js
Normal file
6
server/jest.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
clearMocks: true,
|
||||||
|
roots: ['<rootDir>/src'],
|
||||||
|
testEnvironment: 'node',
|
||||||
|
preset: 'ts-jest'
|
||||||
|
}
|
@ -8,7 +8,9 @@
|
|||||||
"start-build": "node dist/app.js",
|
"start-build": "node dist/app.js",
|
||||||
"lint": "eslint . --fix",
|
"lint": "eslint . --fix",
|
||||||
"prebuild": "yarn lint",
|
"prebuild": "yarn lint",
|
||||||
"build": "tsc"
|
"build": "tsc",
|
||||||
|
"test": "jest",
|
||||||
|
"test-watch": "jest --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie-parser": "1.4.5",
|
"cookie-parser": "1.4.5",
|
||||||
@ -24,16 +26,21 @@
|
|||||||
"@types/cookie-parser": "1.4.2",
|
"@types/cookie-parser": "1.4.2",
|
||||||
"@types/debug": "4.1.5",
|
"@types/debug": "4.1.5",
|
||||||
"@types/express": "4.17.11",
|
"@types/express": "4.17.11",
|
||||||
|
"@types/jest": "26.0.22",
|
||||||
"@types/morgan": "1.9.2",
|
"@types/morgan": "1.9.2",
|
||||||
"@types/node": "14.14.37",
|
"@types/node": "14.14.37",
|
||||||
"@types/ws": "^7.4.1",
|
"@types/ws": "^7.4.1",
|
||||||
|
"@types/supertest": "2.0.11",
|
||||||
"@typescript-eslint/eslint-plugin": "4.21.0",
|
"@typescript-eslint/eslint-plugin": "4.21.0",
|
||||||
"@typescript-eslint/parser": "4.21.0",
|
"@typescript-eslint/parser": "4.21.0",
|
||||||
"eslint": "7.23.0",
|
"eslint": "7.23.0",
|
||||||
"eslint-config-prettier": "^8.1.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-plugin-prettier": "3.3.1",
|
"eslint-plugin-prettier": "3.3.1",
|
||||||
|
"jest": "26.6.3",
|
||||||
"nodemon": "2.0.7",
|
"nodemon": "2.0.7",
|
||||||
"prettier": "2.2.1",
|
"prettier": "2.2.1",
|
||||||
|
"supertest": "6.1.3",
|
||||||
|
"ts-jest": "26.5.4",
|
||||||
"ts-node": "9.1.1",
|
"ts-node": "9.1.1",
|
||||||
"ts-node-dev": "1.1.6",
|
"ts-node-dev": "1.1.6",
|
||||||
"typescript": "4.2.4"
|
"typescript": "4.2.4"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import http from 'http'
|
import http from 'http'
|
||||||
import express, { Application } from 'express'
|
import express, { Application } from 'express'
|
||||||
import {Server as wsServer } from 'ws'
|
import { Server as wsServer } from 'ws'
|
||||||
import initDebug from 'debug'
|
import initDebug from 'debug'
|
||||||
|
|
||||||
import { registerMiddlewares } from './middlewares'
|
import { registerMiddlewares } from './middlewares'
|
||||||
@ -14,7 +14,7 @@ import { registerApis } from './routes/api/register'
|
|||||||
const PORT = normalizePort(process.env.PORT || '6595')
|
const PORT = normalizePort(process.env.PORT || '6595')
|
||||||
|
|
||||||
const debug = initDebug('deemix-gui:server')
|
const debug = initDebug('deemix-gui:server')
|
||||||
const app: Application = express()
|
export const app: Application = express()
|
||||||
const ws = new wsServer({ noServer: true })
|
const ws = new wsServer({ noServer: true })
|
||||||
const server = http.createServer(app)
|
const server = http.createServer(app)
|
||||||
|
|
||||||
@ -31,13 +31,15 @@ registerApis(app)
|
|||||||
app.set('port', PORT)
|
app.set('port', PORT)
|
||||||
|
|
||||||
/* === Server port === */
|
/* === Server port === */
|
||||||
server.listen(PORT)
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
|
server.listen(PORT)
|
||||||
|
}
|
||||||
|
|
||||||
/* === Server callbacks === */
|
/* === Server callbacks === */
|
||||||
server.on('upgrade', (request, socket, head) => {
|
server.on('upgrade', (request, socket, head) => {
|
||||||
ws.handleUpgrade(request, socket, head, socket => {
|
ws.handleUpgrade(request, socket, head, socket => {
|
||||||
ws.emit('connection', socket, request)
|
ws.emit('connection', socket, request)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
server.on('error', getErrorCb(PORT))
|
server.on('error', getErrorCb(PORT))
|
||||||
server.on('listening', getListeningCb(server, debug))
|
server.on('listening', getListeningCb(server, debug))
|
||||||
|
@ -5,7 +5,10 @@ import cookieParser from 'cookie-parser'
|
|||||||
import { WEBUI_DIR } from './helpers/paths'
|
import { WEBUI_DIR } from './helpers/paths'
|
||||||
|
|
||||||
export function registerMiddlewares(app: Application) {
|
export function registerMiddlewares(app: Application) {
|
||||||
app.use(logger('dev'))
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
|
app.use(logger('dev'))
|
||||||
|
}
|
||||||
|
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
app.use(express.urlencoded({ extended: false }))
|
app.use(express.urlencoded({ extended: false }))
|
||||||
app.use(cookieParser())
|
app.use(cookieParser())
|
||||||
|
41
server/src/routes/api/get/albumSearch.spec.ts
Normal file
41
server/src/routes/api/get/albumSearch.spec.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import request from 'supertest'
|
||||||
|
import { app } from '../../../app'
|
||||||
|
|
||||||
|
describe('albumSearch requests', () => {
|
||||||
|
it('should respond 200 to calls with term', async () => {
|
||||||
|
const responseStatusCollector: number[] = []
|
||||||
|
const batchCalls = [
|
||||||
|
'/api/album-search/?term=eminem',
|
||||||
|
'/api/album-search/?term=eminem?start=10',
|
||||||
|
'/api/album-search/?term=eminem?ack=aa',
|
||||||
|
'/api/album-search/?term=eminem?ack=aa?start=10',
|
||||||
|
'/api/album-search/?term=eminem?ack=aa?start=10?nb=34'
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const uri of batchCalls) {
|
||||||
|
responseStatusCollector.push((await request(app).get(uri).send()).status)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(responseStatusCollector).toMatchObject(new Array(batchCalls.length).fill(200))
|
||||||
|
expect(responseStatusCollector).toMatchObject(new Array(responseStatusCollector.length).fill(200))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond 400 to calls without term', async () => {
|
||||||
|
const responseStatusCollector: number[] = []
|
||||||
|
const batchCalls = [
|
||||||
|
'/api/album-search/',
|
||||||
|
'/api/album-search/?start=10',
|
||||||
|
'/api/album-search/?ack=aa',
|
||||||
|
'/api/album-search/?ack=aa?start=10',
|
||||||
|
'/api/album-search/?ack=aa?start=10?nb=34'
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const uri of batchCalls) {
|
||||||
|
responseStatusCollector.push((await request(app).get(uri).send()).status)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(responseStatusCollector).toMatchObject(new Array(responseStatusCollector.length).fill(400))
|
||||||
|
})
|
||||||
|
|
||||||
|
it.todo('should respond the desired search result')
|
||||||
|
})
|
@ -0,0 +1,77 @@
|
|||||||
|
import { RequestHandler } from 'express'
|
||||||
|
import { ApiHandler } from '../../../types'
|
||||||
|
|
||||||
|
export interface RawAlbumQuery {
|
||||||
|
term: string
|
||||||
|
start?: string
|
||||||
|
nb?: string
|
||||||
|
ack: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumSearchParams extends Omit<RawAlbumQuery, 'start' | 'nb'> {
|
||||||
|
start: number
|
||||||
|
nb: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumResponse {
|
||||||
|
data: any[]
|
||||||
|
total: number
|
||||||
|
ack: RawAlbumQuery['ack']
|
||||||
|
}
|
||||||
|
|
||||||
|
const path: ApiHandler['path'] = '/album-search/'
|
||||||
|
|
||||||
|
const handler: RequestHandler<{}, {}, {}, RawAlbumQuery> = (req, res, next) => {
|
||||||
|
if (!req.query) {
|
||||||
|
res.status(400).send()
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
const { term, start, nb, ack } = parseQuery(req.query)
|
||||||
|
|
||||||
|
if (!term || term.trim() === '') {
|
||||||
|
res.status(400).send()
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// const albums = getAlbums(term, start, nb)
|
||||||
|
|
||||||
|
// const output: AlbumResponse = {
|
||||||
|
// data: albums,
|
||||||
|
// total: albums.length,
|
||||||
|
// ack
|
||||||
|
// }
|
||||||
|
|
||||||
|
// res.send(output)
|
||||||
|
res.send()
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiHandler = { path, handler }
|
||||||
|
|
||||||
|
export default apiHandler
|
||||||
|
|
||||||
|
function parseQuery(query: RawAlbumQuery): AlbumSearchParams {
|
||||||
|
let startingPoint = 0
|
||||||
|
|
||||||
|
if (typeof query.start !== 'undefined') {
|
||||||
|
startingPoint = parseInt(query.start)
|
||||||
|
}
|
||||||
|
|
||||||
|
let newNb = 30
|
||||||
|
|
||||||
|
if (typeof query.nb !== 'undefined') {
|
||||||
|
newNb = parseInt(query.nb)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
term: query.term,
|
||||||
|
start: startingPoint,
|
||||||
|
nb: newNb,
|
||||||
|
ack: query.ack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function getAlbums(term: string, start: number, nb: number): any[] {
|
||||||
|
// return []
|
||||||
|
// }
|
@ -1,8 +1,8 @@
|
|||||||
import sample from './sample'
|
|
||||||
import getHome from './getHome'
|
import getHome from './getHome'
|
||||||
import getCharts from './getCharts'
|
import getCharts from './getCharts'
|
||||||
import mainSearch from './mainSearch'
|
import mainSearch from './mainSearch'
|
||||||
import search from './search'
|
import search from './search'
|
||||||
import getTracklist from './getTracklist'
|
import getTracklist from './getTracklist'
|
||||||
|
import albumSearch from './albumSearch'
|
||||||
|
|
||||||
export default [sample, getHome, getCharts, mainSearch, search, getTracklist]
|
export default [albumSearch, getHome, getCharts, mainSearch, search, getTracklist]
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import { ApiHandler } from '../../../types'
|
|
||||||
|
|
||||||
const path: ApiHandler['path'] = '/sample'
|
|
||||||
|
|
||||||
const handler: ApiHandler['handler'] = (_, res) => {
|
|
||||||
res.send('Mandi')
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiHandler: ApiHandler = { path, handler }
|
|
||||||
|
|
||||||
export default apiHandler
|
|
28
server/src/routes/index.spec.ts
Normal file
28
server/src/routes/index.spec.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import request from 'supertest'
|
||||||
|
import { app } from '../app'
|
||||||
|
|
||||||
|
describe('root path requests', () => {
|
||||||
|
it('it responds 200 to the GET method', async () => {
|
||||||
|
const result = await request(app).get('/').send()
|
||||||
|
|
||||||
|
expect(result.status).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('it responds 404 to the POST method', async () => {
|
||||||
|
const result = await request(app).post('/').send()
|
||||||
|
|
||||||
|
expect(result.status).toBe(404)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('it responds 404 to the PATCH method', async () => {
|
||||||
|
const result = await request(app).patch('/').send()
|
||||||
|
|
||||||
|
expect(result.status).toBe(404)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('it responds 404 to the DELETE method', async () => {
|
||||||
|
const result = await request(app).delete('/').send()
|
||||||
|
|
||||||
|
expect(result.status).toBe(404)
|
||||||
|
})
|
||||||
|
})
|
30
server/src/tests/cookie-parser.spec.ts
Normal file
30
server/src/tests/cookie-parser.spec.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Taken from https://github.com/visionmedia/supertest
|
||||||
|
|
||||||
|
import request from 'supertest'
|
||||||
|
import express from 'express'
|
||||||
|
import cookieParser from 'cookie-parser'
|
||||||
|
|
||||||
|
describe('cookie parser', () => {
|
||||||
|
const app = express()
|
||||||
|
app.use(cookieParser())
|
||||||
|
|
||||||
|
app.get('/', (_, res) => {
|
||||||
|
res.cookie('cookie', 'hey')
|
||||||
|
res.send()
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/return', (req, res) => {
|
||||||
|
if (req.cookies.cookie) res.send(req.cookies.cookie)
|
||||||
|
else res.send(':(')
|
||||||
|
})
|
||||||
|
|
||||||
|
const agent = request.agent(app)
|
||||||
|
|
||||||
|
it('should save cookies', done => {
|
||||||
|
agent.get('/').expect('set-cookie', 'cookie=hey; Path=/', done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should send cookies', done => {
|
||||||
|
agent.get('/return').expect('hey', done)
|
||||||
|
})
|
||||||
|
})
|
@ -1,8 +1,12 @@
|
|||||||
import { RequestHandler } from 'express'
|
import { RequestHandler } from 'express'
|
||||||
|
|
||||||
|
/* === Utilities === */
|
||||||
|
// https://github.com/Microsoft/TypeScript/issues/25760#issuecomment-614417742
|
||||||
|
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>
|
||||||
|
|
||||||
export type Port = number | string | boolean
|
export type Port = number | string | boolean
|
||||||
|
|
||||||
export interface ApiHandler {
|
export interface ApiHandler {
|
||||||
path: string
|
path: string
|
||||||
handler: RequestHandler
|
handler: RequestHandler<any, any, any, any>
|
||||||
}
|
}
|
||||||
|
3918
server/yarn.lock
3918
server/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user