forked from fr/deguapp
		
	Added: Beer API, Docs API and tests for both, fixed build
This commit is contained in:
		@@ -10,6 +10,7 @@
 | 
				
			|||||||
		"start:dev": "tsx watch src/server.ts",
 | 
							"start:dev": "tsx watch src/server.ts",
 | 
				
			||||||
		"start:prod": "node dist/server.js",
 | 
							"start:prod": "node dist/server.js",
 | 
				
			||||||
		"tsc": "tsc -p .",
 | 
							"tsc": "tsc -p .",
 | 
				
			||||||
 | 
							"docs": "DOCS_GEN=true npx ts-node ./src/server.ts",
 | 
				
			||||||
		"clean": "rimraf dist",
 | 
							"clean": "rimraf dist",
 | 
				
			||||||
		"copy-assets": "ts-node src/utils/copy_assets",
 | 
							"copy-assets": "ts-node src/utils/copy_assets",
 | 
				
			||||||
		"build": "npm-run-all clean tsc copy-assets",
 | 
							"build": "npm-run-all clean tsc copy-assets",
 | 
				
			||||||
@@ -29,6 +30,7 @@
 | 
				
			|||||||
		"jsonwebtoken": "^9.0.2",
 | 
							"jsonwebtoken": "^9.0.2",
 | 
				
			||||||
		"mongoose": "^8.3.3",
 | 
							"mongoose": "^8.3.3",
 | 
				
			||||||
		"morgan": "^1.10.0",
 | 
							"morgan": "^1.10.0",
 | 
				
			||||||
 | 
							"multer": "^1.4.5-lts.1",
 | 
				
			||||||
		"pad": "^3.2.0",
 | 
							"pad": "^3.2.0",
 | 
				
			||||||
		"path": "^0.12.7",
 | 
							"path": "^0.12.7",
 | 
				
			||||||
		"yup": "^1.4.0",
 | 
							"yup": "^1.4.0",
 | 
				
			||||||
@@ -46,6 +48,7 @@
 | 
				
			|||||||
		"@types/jsonwebtoken": "^9.0.6",
 | 
							"@types/jsonwebtoken": "^9.0.6",
 | 
				
			||||||
		"@types/mocha": "^9.0.0",
 | 
							"@types/mocha": "^9.0.0",
 | 
				
			||||||
		"@types/morgan": "^1.9.9",
 | 
							"@types/morgan": "^1.9.9",
 | 
				
			||||||
 | 
							"@types/multer": "^1.4.11",
 | 
				
			||||||
		"@types/shelljs": "^0.8.11",
 | 
							"@types/shelljs": "^0.8.11",
 | 
				
			||||||
		"@types/supertest": "^6.0.2",
 | 
							"@types/supertest": "^6.0.2",
 | 
				
			||||||
		"@typescript-eslint/eslint-plugin": "^5.5.0",
 | 
							"@typescript-eslint/eslint-plugin": "^5.5.0",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										100
									
								
								api/src/controllers/beerController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								api/src/controllers/beerController.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					import { Request, Response } from 'express';
 | 
				
			||||||
 | 
					import Beer from '../models/Beer';
 | 
				
			||||||
 | 
					import { isValidObjectId, Types } from 'mongoose';
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import {Log} from 'nork'
 | 
				
			||||||
 | 
					import Docs from '../services/docsService';
 | 
				
			||||||
 | 
					import { addExam, delExam, editExam, IBeer } from '../validators/beerValidator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new Docs('beer', 'add', '/api/v1/beer/add', 'POST', 'beer add api', undefined, { ...addExam, photos: 'optional field | max 4 images | formData' }, 'status object | beer object');
 | 
				
			||||||
 | 
					export async function add_post(req: Request, res: Response) {
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							if (req.files) {
 | 
				
			||||||
 | 
								req.body.imgs = [];
 | 
				
			||||||
 | 
								const files: any = req.files;
 | 
				
			||||||
 | 
								files.forEach((el: any) => {
 | 
				
			||||||
 | 
									req.body.imgs.push(el.filename);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							const beer = new Beer(req.body);
 | 
				
			||||||
 | 
							await beer.save();
 | 
				
			||||||
 | 
							res.status(201).json(Log.info(201, 'beer was created', beer));
 | 
				
			||||||
 | 
						} catch (err: any) {
 | 
				
			||||||
 | 
							Log.error(500, 'error in add_post', err);
 | 
				
			||||||
 | 
							res.status(500).json(Log.error(500, 'something went wrong'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new Docs('beer', 'get', '/api/v1/beer/get', 'GET', 'beer get api', undefined, undefined, 'status object | array of beer objects');
 | 
				
			||||||
 | 
					export async function get_get(req: Request, res: Response) {
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							const beer = await Beer.find({}, '-__v');
 | 
				
			||||||
 | 
							res.status(200).json(Log.info(200, 'beers fetched', beer));
 | 
				
			||||||
 | 
						} catch (err: any) {
 | 
				
			||||||
 | 
							Log.error(500, 'error in get_get', err);
 | 
				
			||||||
 | 
							res.status(500).json(Log.error(500, 'something went wrong'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new Docs('beer', 'del', '/api/v1/beer/del', 'POST', 'beer del api', undefined, delExam, 'status object');
 | 
				
			||||||
 | 
					export async function del_post(req: Request, res: Response) {
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							if (!isValidObjectId(req.body._id)) throw Log.error(400, 'this is not valid _id');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const beer = await Beer.deleteOne(new Types.ObjectId(req.body._id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (beer.deletedCount > 0) {
 | 
				
			||||||
 | 
								res.status(200).json(Log.info(200, `beer ${req.body._id} deleted`));
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							throw Log.error(400, `beer ${req.body._id} does not exist`);
 | 
				
			||||||
 | 
						} catch (err: any) {
 | 
				
			||||||
 | 
							if (err.code) {
 | 
				
			||||||
 | 
								res.status(err.code).json(err);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							Log.error(500, 'error in del_post', err);
 | 
				
			||||||
 | 
							res.status(500).json(Log.error(500, 'something went wrong'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new Docs('beer', 'edit', '/api/v1/beer/edit', 'POST', 'beer edit api', undefined, { ...editExam, photos: 'optional field | max 4 images | formData' }, 'status object |  beer data');
 | 
				
			||||||
 | 
					export async function edit_post(req: Request, res: Response) {
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							if (!isValidObjectId(req.body._id)) throw Log.error(400, 'this is not valid _id');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (req.files) {
 | 
				
			||||||
 | 
								if (!req.body.imgs) {
 | 
				
			||||||
 | 
									req.body.imgs = [];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (typeof req.body.imgs == 'string') {
 | 
				
			||||||
 | 
									req.body.imgs = [req.body.imgs];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (req.body.imgs.length + req.files.length > 4) {
 | 
				
			||||||
 | 
									req.body.imgs.forEach((el: string[]) => {
 | 
				
			||||||
 | 
										fs.rmSync(path.join(__dirname, '../../uploads/' + el));
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
									throw Log.error(400, 'exceeds the 4 image limit');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const files: any = req.files;
 | 
				
			||||||
 | 
								files.forEach((el: any) => {
 | 
				
			||||||
 | 
									req.body.imgs.push(el.filename);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const payload = { ...req.body };
 | 
				
			||||||
 | 
							const beer = await Beer.findOneAndUpdate(new Types.ObjectId(req.body._id), payload, { new: true });
 | 
				
			||||||
 | 
							res.json(Log.info(200, `beer ${req.body._id} edited`, beer));
 | 
				
			||||||
 | 
						} catch (err: any) {
 | 
				
			||||||
 | 
							if (err.code && typeof err.code == 'number') {
 | 
				
			||||||
 | 
								res.status(err.code).json(err);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							Log.error(500, 'error in del_post', err);
 | 
				
			||||||
 | 
							res.status(500).json(Log.error(500, 'something went wrong'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								api/src/controllers/docsController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								api/src/controllers/docsController.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import { Request, Response } from 'express';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import {Log} from 'nork'
 | 
				
			||||||
 | 
					import { Docs } from '../services/docsService';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new Docs('docs', 'get_all', '/api/v1', 'GET', 'Get docs json', undefined, undefined, 'docs json');
 | 
				
			||||||
 | 
					export function docs_get(req: Request, res: Response) {
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							res.json(JSON.parse(fs.readFileSync(path.join(__dirname, '../public/api.json')).toString()));
 | 
				
			||||||
 | 
						} catch (err: any) {
 | 
				
			||||||
 | 
							res.status(500).json(Log.error(500, 'api.json docs file does not exists under public folder'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								api/src/middlewares/validateMulterRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								api/src/middlewares/validateMulterRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					import multer from 'multer';
 | 
				
			||||||
 | 
					import {Log} from 'nork'
 | 
				
			||||||
 | 
					import { Request, Response, NextFunction } from 'express';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const validateMulterRequestMiddleware = async (err: any, req: Request, res: Response, next: NextFunction) => {
 | 
				
			||||||
 | 
						if (err instanceof multer.MulterError) {
 | 
				
			||||||
 | 
							Log.error(500, 'error while processing uploaded files', JSON.stringify(err));
 | 
				
			||||||
 | 
							res.status(400).json(Log.error(400, 'error while processing uploaded files'));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							next();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default validateMulterRequestMiddleware;
 | 
				
			||||||
							
								
								
									
										34
									
								
								api/src/models/Beer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								api/src/models/Beer.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import { Schema, model } from 'mongoose';
 | 
				
			||||||
 | 
					import { IBeer } from '../validators/beerValidator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const schema = new Schema<IBeer | any>(
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							name: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							degree: {
 | 
				
			||||||
 | 
								type: Number,
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							packaging: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							brand: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							imgs: {
 | 
				
			||||||
 | 
								type: Array,
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
 | 
								default: []
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							timestamps: true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default model(path.basename(__filename).split('.')[0], schema);
 | 
				
			||||||
							
								
								
									
										1
									
								
								api/src/public/api.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								api/src/public/api.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"version":"2.0.0","endpoints":{"user":{"signup":{"name":"user","operation":"signup","route":"/api/v1/auth/signup","method":"POST","description":"user signup api","body":{"username":"testuser","email":"text@example.com","password":"Test1234"},"response":"status object"},"signin":{"name":"user","operation":"signin","route":"/api/v1/auth/signin","method":"POST","description":"user signin api","body":{"email":"text@example.com","password":"Test1234"},"response":"status object"},"logout":{"name":"user","operation":"logout","route":"/api/v1/auth/logout","method":"POST","description":"user logout api","body":{},"response":"status object"},"status":{"name":"user","operation":"status","route":"/api/v1/auth/status","method":"GET","description":"user login status api","response":"status code | user object"}},"beer":{"add":{"name":"beer","operation":"add","route":"/api/v1/beer/add","method":"POST","description":"beer add api","body":{"brand":"Pilsner Urqell","name":"Kozel","degree":11,"packaging":"can","photos":"optional field | max 4 images | formData"},"response":"status object | beer object"},"get":{"name":"beer","operation":"get","route":"/api/v1/beer/get","method":"GET","description":"beer get api","response":"status object | array of beer objects"},"del":{"name":"beer","operation":"del","route":"/api/v1/beer/del","method":"POST","description":"beer del api","body":{"_id":"6352b303b71cb62222f39895"},"response":"status object"},"edit":{"name":"beer","operation":"edit","route":"/api/v1/beer/edit","method":"POST","description":"beer edit api","body":{"_id":"6355b95dc03fad77bc380146","brand":"Pilsner Urqell","name":"Radegast","degree":12,"packaging":"bottle","imgs":[],"photos":"optional field | max 4 images | formData"},"response":"status object |  beer data"}},"docs":{"get_all":{"name":"docs","operation":"get_all","route":"/api/v1","method":"GET","description":"Get docs json","response":"docs json"}}}}
 | 
				
			||||||
@@ -1,14 +1,29 @@
 | 
				
			|||||||
import { Router } from "express";
 | 
					import { Router } from "express";
 | 
				
			||||||
 | 
					import multer from 'multer';
 | 
				
			||||||
 | 
					import path from 'path'
 | 
				
			||||||
import * as authController from "../controllers/authController";
 | 
					import * as authController from "../controllers/authController";
 | 
				
			||||||
import validate from '../middlewares/validateRequest'
 | 
					import * as beerController from "../controllers/beerController"
 | 
				
			||||||
import * as AuthVal from '../validators/authValidator'
 | 
					import * as docsController from "../controllers/docsController"
 | 
				
			||||||
import { requireAuth } from "../middlewares/authMiddleware";
 | 
					import { requireAuth } from "../middlewares/authMiddleware";
 | 
				
			||||||
 | 
					import validate from '../middlewares/validateRequest'
 | 
				
			||||||
 | 
					import valMulter from '../middlewares/validateMulterRequest';
 | 
				
			||||||
 | 
					import * as AuthVal from '../validators/authValidator'
 | 
				
			||||||
 | 
					import * as BVal from '../validators/beerValidator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const upload = multer({ dest: path.resolve(__dirname, '../../uploads') });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = Router();
 | 
					const router = Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					router.get('/', docsController.docs_get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.post("/auth/signup",validate(AuthVal.signup) , authController.signup_post);
 | 
					router.post("/auth/signup",validate(AuthVal.signup) , authController.signup_post);
 | 
				
			||||||
router.post("/auth/signin",validate(AuthVal.signin) , authController.signin_post);
 | 
					router.post("/auth/signin",validate(AuthVal.signin) , authController.signin_post);
 | 
				
			||||||
router.post("/auth/logout", requireAuth, authController.logout_post);
 | 
					router.post("/auth/logout", requireAuth, authController.logout_post);
 | 
				
			||||||
router.get("/auth/status", requireAuth, authController.status_get);
 | 
					router.get("/auth/status", requireAuth, authController.status_get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					router.post('/beer/add', [requireAuth, upload.array('photos', 4), valMulter, validate(BVal.add)], beerController.add_post);
 | 
				
			||||||
 | 
					router.get('/beer/get', [requireAuth], beerController.get_get);
 | 
				
			||||||
 | 
					router.post('/beer/del', [requireAuth, validate(BVal.del)], beerController.del_post);
 | 
				
			||||||
 | 
					router.post('/beer/edit', [requireAuth, upload.array('photos', 4), valMulter, validate(BVal.edit)], beerController.edit_post);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default router;
 | 
					export default router;
 | 
				
			||||||
							
								
								
									
										65
									
								
								api/src/validators/beerValidator.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								api/src/validators/beerValidator.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					import * as yup from 'yup';
 | 
				
			||||||
 | 
					import YupPassword from 'yup-password';
 | 
				
			||||||
 | 
					YupPassword(yup);
 | 
				
			||||||
 | 
					import { Schema } from 'mongoose';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface mongooseAddition {
 | 
				
			||||||
 | 
						_id?: Schema.Types.ObjectId;
 | 
				
			||||||
 | 
						createdAt?: Schema.Types.Date;
 | 
				
			||||||
 | 
						updatedAt?: Schema.Types.Date;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Create
 | 
				
			||||||
 | 
					export const add = yup.object({
 | 
				
			||||||
 | 
						brand: yup.string().required(),
 | 
				
			||||||
 | 
						name: yup.string().required(),
 | 
				
			||||||
 | 
						degree: yup.number().required(),
 | 
				
			||||||
 | 
						packaging: yup.string().required()
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					export interface IBeer extends yup.InferType<typeof add>, mongooseAddition {}
 | 
				
			||||||
 | 
					export const addExam: IBeer = {
 | 
				
			||||||
 | 
						brand: 'Pilsner Urqell',
 | 
				
			||||||
 | 
						name: 'Kozel',
 | 
				
			||||||
 | 
						degree: 11,
 | 
				
			||||||
 | 
						packaging: 'can'
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Remove
 | 
				
			||||||
 | 
					export const del = yup.object({
 | 
				
			||||||
 | 
						_id: yup.string().required()
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					export interface IDel extends yup.InferType<typeof del> {}
 | 
				
			||||||
 | 
					export const delExam: IDel = {
 | 
				
			||||||
 | 
						_id: '6352b303b71cb62222f39895'
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Update
 | 
				
			||||||
 | 
					export const edit = yup.object({
 | 
				
			||||||
 | 
						_id: yup.string().required(),
 | 
				
			||||||
 | 
						brand: yup.string(),
 | 
				
			||||||
 | 
						name: yup.string(),
 | 
				
			||||||
 | 
						degree: yup.number(),
 | 
				
			||||||
 | 
						packaging: yup.string(),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //imgs: yup.mixed().when('$imgs', (imgs, schema) => 
 | 
				
			||||||
 | 
					  //  Array.isArray(imgs) ? schema.array() : schema.string()
 | 
				
			||||||
 | 
					  //)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  imgs: yup.mixed().test('is-array-or-string', 'imgs must be either an array or a string', value =>  
 | 
				
			||||||
 | 
					    Array.isArray(value) || typeof value === 'string')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//imgs: yup.mixed().when('isArray', {
 | 
				
			||||||
 | 
						//	is: Array.isArray,
 | 
				
			||||||
 | 
						//	then: yup.array(),
 | 
				
			||||||
 | 
						//	otherwise: yup.string()
 | 
				
			||||||
 | 
						//})
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					export interface IEdit extends yup.InferType<typeof edit> {}
 | 
				
			||||||
 | 
					export const editExam: IEdit = {
 | 
				
			||||||
 | 
						_id: '6355b95dc03fad77bc380146',
 | 
				
			||||||
 | 
						brand: 'Pilsner Urqell',
 | 
				
			||||||
 | 
						name: 'Radegast',
 | 
				
			||||||
 | 
						degree: 12,
 | 
				
			||||||
 | 
						packaging: 'bottle',
 | 
				
			||||||
 | 
						imgs: []
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										175
									
								
								api/tests/beer.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								api/tests/beer.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					import supertest from 'supertest';
 | 
				
			||||||
 | 
					import { app } from '../src/app';
 | 
				
			||||||
 | 
					import { login } from './auth.test';
 | 
				
			||||||
 | 
					import { addExam, delExam, editExam } from '../src/validators/beerValidator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const request = supertest(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('POST /api/v1/beer/add', () => {
 | 
				
			||||||
 | 
						const url = '/api/v1/beer/add';
 | 
				
			||||||
 | 
						test('should drop 401 error', async () => {
 | 
				
			||||||
 | 
							const res = await request.post(url).send({});
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(401);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 400 ()', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(400);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 400 (brand)', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const body: any = { ...addExam };
 | 
				
			||||||
 | 
							delete body.brand;
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(400);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 201', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(addExam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(201);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('GET /api/v1/beer/get', () => {
 | 
				
			||||||
 | 
						const url = '/api/v1/beer/get';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 401', async () => {
 | 
				
			||||||
 | 
							const res = await request.get(url).send();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(401);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const res = await request.get(url).set('Cookie', jwt).send();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('POST /api/v1/beer/del', () => {
 | 
				
			||||||
 | 
						const url = '/api/v1/beer/del';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 401', async () => {
 | 
				
			||||||
 | 
							const res = await request.post(url).send();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(401);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 400', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(delExam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(400);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 400', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send({
 | 
				
			||||||
 | 
								_id: 'thisWillNotWork'
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(400);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const req = await request.post('/api/v1/beer/add').set('Cookie', jwt).send(addExam);
 | 
				
			||||||
 | 
							const id = req.body.data._id;
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send({
 | 
				
			||||||
 | 
								_id: id
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('POST /api/v1/beer/edit', () => {
 | 
				
			||||||
 | 
						const url = '/api/v1/beer/edit';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 401', async () => {
 | 
				
			||||||
 | 
							const res = await request.post(url).send();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(401);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 400', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const payload: any = { ...editExam };
 | 
				
			||||||
 | 
							delete payload._id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(400);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const payload: any = { ...editExam };
 | 
				
			||||||
 | 
							delete payload.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const payload: any = { ...editExam };
 | 
				
			||||||
 | 
							delete payload.degree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const payload: any = { ...editExam };
 | 
				
			||||||
 | 
							delete payload.packaging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const payload: any = { ...editExam };
 | 
				
			||||||
 | 
							delete payload.brand;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await request.post(url).set('Cookie', jwt).send(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test('should drop 200', async () => {
 | 
				
			||||||
 | 
							const jwt = await login();
 | 
				
			||||||
 | 
							const req = await request.post('/api/v1/beer/add').set('Cookie', jwt).send(addExam);
 | 
				
			||||||
 | 
							const _id = req.body.data._id;
 | 
				
			||||||
 | 
							const payload = { ...editExam, _id: _id };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let res = await request.post(url).set('Cookie', jwt).send(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							delete res.body.data._id;
 | 
				
			||||||
 | 
							delete res.body.data.__v;
 | 
				
			||||||
 | 
							delete res.body.data.createdAt;
 | 
				
			||||||
 | 
							delete res.body.data.updatedAt;
 | 
				
			||||||
 | 
							delete payload._id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const eq = JSON.stringify(Object.keys(res.body.data).sort()) === JSON.stringify(Object.keys(payload).sort());
 | 
				
			||||||
 | 
							expect(res.statusCode).toBe(200);
 | 
				
			||||||
 | 
							expect(eq).toBe(true);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										12
									
								
								api/tests/docs.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								api/tests/docs.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import request from 'supertest';
 | 
				
			||||||
 | 
					import { app } from '../src/app';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('GET /api/v1', () => {
 | 
				
			||||||
 | 
						describe('should return json with docs', () => {
 | 
				
			||||||
 | 
							test('should respond with a 200 status code', async () => {
 | 
				
			||||||
 | 
								const response = await request(app).get('/api/v1').send({});
 | 
				
			||||||
 | 
								expect(response.headers['content-type']).toMatch(/json/);
 | 
				
			||||||
 | 
								expect(response.statusCode).toBe(200);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Reference in New Issue
	
	Block a user