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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user