From 7c16e76a0d7ee3e307e90b6a6761734abdbcb9f1 Mon Sep 17 00:00:00 2001 From: Kfir Dayan Date: Wed, 14 Jun 2023 10:40:11 +0300 Subject: [PATCH] fine tunning --- __tests__/controllers/CartController.test.ts | 75 ---------------- .../controllers/ProductController.test.ts | 58 ------------- __tests__/controllers/UserController.test.ts | 87 ------------------- __tests__/index.test.ts | 39 --------- __tests__/middlewares/checkAuth.test.ts | 33 ------- __tests__/mongoose/Schema.test.ts | 74 ---------------- __tests__/routes/cart.test.ts | 14 --- __tests__/routes/product.test.ts | 12 --- __tests__/routes/user.test.ts | 10 --- __tests__/services/sendGrid.test.ts | 26 ------ src/controllers/CartController.ts | 1 - src/controllers/ProductController.ts | 6 +- tsconfig.json | 3 +- 13 files changed, 5 insertions(+), 433 deletions(-) delete mode 100644 __tests__/controllers/CartController.test.ts delete mode 100644 __tests__/controllers/ProductController.test.ts delete mode 100644 __tests__/controllers/UserController.test.ts delete mode 100644 __tests__/middlewares/checkAuth.test.ts delete mode 100644 __tests__/mongoose/Schema.test.ts delete mode 100644 __tests__/routes/cart.test.ts delete mode 100644 __tests__/routes/product.test.ts delete mode 100644 __tests__/routes/user.test.ts delete mode 100644 __tests__/services/sendGrid.test.ts diff --git a/__tests__/controllers/CartController.test.ts b/__tests__/controllers/CartController.test.ts deleted file mode 100644 index a7e39f8..0000000 --- a/__tests__/controllers/CartController.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Request, Response } from 'express'; -import { Cart, ICart, Order } from '../mongoose/Schema.test'; -import { config } from 'dotenv'; - -config(); - -export async function addToCart(req: Request, res: Response) { - try { - const { userId, productId } = req.body; - if (!productId) { - res.status(400).json({ error: 'Product id is required.' }); - return; - } - let cart: ICart | null = await Cart.findOne({ userId }); - if (!cart) { - cart = await Cart.create({ - userId, - products: { [productId]: 1 }, - }); - } else { - const currentQuantity = cart.products[productId]; - if (currentQuantity === undefined) { - cart.products[productId] = 1; - } else { - cart.products[productId] += 1; - } - cart.markModified('products'); - } - - await cart.save(); - res.status(200).json(cart); - } catch (error) { - console.error('Error adding product to cart:', error); - res.status(500).json({ error: 'An error occurred while adding the product to the cart.' }); - } -} - -export async function listCart(req: Request, res: Response) { - try { - const { userId } = req.body; - const cart = await Cart.findOne({ userId }); - if (!cart) { - res.status(404).json({ error: 'Cart not found.' }); - return; - } - res.status(200).json(cart.products); - } catch (error) { - console.error('Error listing cart:', error); - res.status(500).json({ error: 'An error occurred while listing the cart.' }); - } -} - -export async function checkout(req: Request, res: Response) { - - const { userId } = req.body; - const usersCart = await Cart.findOne({ userId }); - - if (!usersCart) { - res.status(404).json({ error: 'Cart not found.' }); - return; - } - - const order = await Order.create({ - userId, - products: usersCart.products, - }); - - await removeCart(userId); - // sendEmailasync(order.id, userId); - res.status(200).json(order); -} - -async function removeCart(userId: string) { - await Cart.deleteOne({ userId }); -} \ No newline at end of file diff --git a/__tests__/controllers/ProductController.test.ts b/__tests__/controllers/ProductController.test.ts deleted file mode 100644 index 37a17f1..0000000 --- a/__tests__/controllers/ProductController.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Request, Response } from 'express'; -import { Product, IProduct } from '../mongoose/Schema'; - -export async function createProduct(req: Request, res: Response) { - try { - const { name, description, price, userId } = req.body; - if(!name || !description || !price || !userId) { - res.status(400).json({ error: 'Name, description, price are required.' }); - return; - } - - const productExists = await Product.exists({ name, userId }); - if(productExists) { - res.status(400).json({ error: 'Product already exists.' }); - return; - } - const product: IProduct = await Product.create({ - name, - description, - price, - userId: userId, - }); - - res.status(201).json(product); - } catch (error) { - console.error('Error creating product:', error); - res.status(500).json({ error: 'An error occurred while creating the product.' }); - } -} - -export async function listProducts(req: Request, res: Response) { - try { - const { page, limit } = req.query; - const dbPage = Number(page) || 0; - const dbLimit = Number(limit) || 50; - const products = await Product.find().sort({ price: 1 }).skip(Number(dbPage) * Number(dbLimit)).limit(Number(dbLimit)); - - res.json(products); - } catch (error) { - console.error('Error listing products:', error); - res.status(500).json({ error: 'An error occurred while listing the products.' }); - } -} - -export async function getProduct(req: Request, res: Response) { - const { id } = req.params; - try { - const product = await Product.findById(id); - if(!product) { - res.status(404).json({ error: 'Product not found.' }); - return; - } - res.json(product); - } catch (error) { - console.error('Error getting product:', error); - res.status(404).json({ error: 'Product not found.' }); - } -} diff --git a/__tests__/controllers/UserController.test.ts b/__tests__/controllers/UserController.test.ts deleted file mode 100644 index 634002b..0000000 --- a/__tests__/controllers/UserController.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Request, Response } from 'express'; -import bcrypt from 'bcryptjs'; -import jwt from 'jsonwebtoken'; -import { User, IUser } from '../mongoose/Schema'; -import { clearJwtCookie, setJwtCookie } from '../middlewares/checkAuth.test'; -import validate from 'deep-email-validator'; - -export async function createUser(req: Request, res: Response) { - try { - const { email, password, address } = req.body; - const isValidEmail = await validate(email); - if (!isValidEmail.valid) { - console.error('Email is invalid:', isValidEmail.validators); - return res.status(400).json({ error: 'Email is invalid' }); - } - - if (!(password && address)) { - return res.status(400).json({ error: 'All inputs are required' }); - } - // checkIfUserExists return true if the user exists - const userExists = await User.exists({ email }); - if(userExists) { - return res.status(400).json({ error: 'User already exists, Try login :)' }); - } - - const hashedPassword = await bcrypt.hash(password, 10); - - const user: IUser = await User.create({ - email, - password: hashedPassword, - address, - }); - - res.status(200).json({ - massage: 'User created successfully' - }); - } catch (error) { - console.error('Error creating user:', error); - res.status(500).json({ error: 'An error occurred while creating the user.' }); - } -} - -export async function login(req: Request, res: Response) { - try { - const { email, password } = req.body; - - // Check if the user exists - const user: IUser | null = await User.findOne({ email }); - if (!user) { - console.error('User not found'); - return res.status(401).json({ error: 'Invalid email or password' }); - } - - // Compare the provided password with the stored password - const isPasswordCorrect = await bcrypt.compare(password, user.password); - if (!isPasswordCorrect) { - console.error('Invalid password'); - return res.status(401).json({ error: 'Invalid email or password' }); - } - - const payload = { - userId: user._id - } - // Generate a JWT - const token = jwt.sign(payload, process.env.JWT_SECRET as string, { expiresIn: '1d' }); - - setJwtCookie(res, token); - - // Send the JWT as the response - res.status(200).json({ - token - }); - } catch (error) { - console.error('Error during login:', error); - res.status(500).json({ error: 'An error occurred during login' }); - } -} - -export async function logout(req: Request, res: Response) { - try { - clearJwtCookie(res); - res.status(200).json({ message: 'Logout successful' }); - } catch (error) { - console.error('Error during logout:', error); - res.status(500).json({ error: 'An error occurred during logout' }); - } -} \ No newline at end of file diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts index ec1dc24..e69de29 100644 --- a/__tests__/index.test.ts +++ b/__tests__/index.test.ts @@ -1,39 +0,0 @@ -import express from 'express'; -import mongoose from 'mongoose'; -import cookieParser from 'cookie-parser'; - -import userRouter from './routes/user'; -import productRouter from './routes/product'; -import cartRouter from './routes/cart'; - -const env = require('dotenv').config().parsed; - -const app = express(); -const PORT = env.PORT || 3000; - -app.use(express.json()); -app.use(cookieParser()) - -// Connect to MongoDB using Mongoose -mongoose.connect(env.DATABASE_URL); - -const db = mongoose.connection; - -// Check for DB connection -db.on('error', () => { - console.error.bind(console, 'MongoDB connection error:') - process.exit(1); -}); -db.once('open', () => { - console.log('Connected to MongoDB'); -}); - -// Routes -app.use('/users', userRouter); -app.use('/products', productRouter); -app.use('/cart', cartRouter); - -// Start server -app.listen(PORT, () => { - console.log(`Server started on port ${PORT}`); -}); diff --git a/__tests__/middlewares/checkAuth.test.ts b/__tests__/middlewares/checkAuth.test.ts deleted file mode 100644 index 9c62104..0000000 --- a/__tests__/middlewares/checkAuth.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Request, Response, NextFunction } from 'express'; -import jwt from 'jsonwebtoken'; - -interface AuthenticatedRequest extends Request { - userId?: string; -} - -// Middleware function to authenticate requests -export function authenticateToken(req: AuthenticatedRequest, res: Response, next: NextFunction) { - - const token = req.cookies.access_token; - if (!token) { - return res.status(401).json({ error: 'Unauthorized' }); - } - - jwt.verify(token, process.env.JWT_SECRET as string, (err: any, decoded: { userId: any; }) => { - if (err) { - return res.status(401).json({ error: 'In Valid Token' }); - } - req.body.userId = decoded.userId; - next(); - }); -} - -// Set JWT as cookie in the response -export function setJwtCookie(res: Response, token: string) { - res.cookie('access_token', token, { httpOnly: true }); -} - -// Clear JWT cookie in the response -export function clearJwtCookie(res: Response) { - res.clearCookie('access_token'); -} diff --git a/__tests__/mongoose/Schema.test.ts b/__tests__/mongoose/Schema.test.ts deleted file mode 100644 index 0a1157b..0000000 --- a/__tests__/mongoose/Schema.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import mongoose, { Schema, Document } from 'mongoose'; - -export interface IUser extends Document { - email: string; - password: string; - address: string; - createdAt: Date; - updatedAt: Date; -} - -export interface IProduct extends Document { - name: string; - description: string; - price: number; - userId: string; - createdAt: Date; - updatedAt: Date; -} - -export interface ICart extends Document { - userId: string; - products: { [itemId: string]: number }; - createdAt: Date; - updatedAt: Date; -} - -export interface IOrder extends Document { - userId: string; - products: { [itemId: string]: number }; - emailSent: boolean; - createdAt: Date; - updatedAt: Date; -} - -const UserSchema: Schema = new Schema({ - email: { type: String, required: true, unique: true }, - password: { type: String, required: true }, - address: { type: String, required: true }, - createdAt: { type: Date, default: Date.now }, - updatedAt: { type: Date, default: Date.now }, -}); - -const ProductSchema: Schema = new Schema({ - name: { type: String, required: true }, - description: { type: String, required: true }, - price: { type: Number, required: true }, - userId: { type: Schema.Types.ObjectId, ref: 'User', required: true }, - createdAt: { type: Date, default: Date.now }, - updatedAt: { type: Date, default: Date.now }, -}); - -const CartSchema: Schema = new Schema({ - userId: { type: Schema.Types.ObjectId, ref: 'User', required: true, unique: true }, - products: { type: Schema.Types.Mixed, default: {} }, - createdAt: { type: Date, default: Date.now }, - updatedAt: { type: Date, default: Date.now }, -}); - -const OrderSchema: Schema = new Schema({ - userId: { type: Schema.Types.ObjectId, ref: 'User', required: true }, - products: { type: Schema.Types.Mixed, default: {} }, - emailSent: { type: Boolean, default: false }, - createdAt: { type: Date, default: Date.now }, - updatedAt: { type: Date, default: Date.now }, -}); - -ProductSchema.index({ name: 1, userId: 1 }, { unique: true }); - -const User = mongoose.model('User', UserSchema); -const Product = mongoose.model('Product', ProductSchema); -const Cart = mongoose.model('Cart', CartSchema); -const Order = mongoose.model('Order', OrderSchema); - -export { User, Product, Cart, Order }; diff --git a/__tests__/routes/cart.test.ts b/__tests__/routes/cart.test.ts deleted file mode 100644 index 10f68ef..0000000 --- a/__tests__/routes/cart.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import express from 'express'; -import { authenticateToken } from '../middlewares/checkAuth.test'; -import { addToCart, listCart, checkout } from '../controllers/CartController.test'; - - - -const cartRouter = express.Router(); - -cartRouter.post('/', authenticateToken, addToCart); -cartRouter.get('/', authenticateToken, listCart); - -cartRouter.post('/checkout', authenticateToken, checkout); - -export default cartRouter; \ No newline at end of file diff --git a/__tests__/routes/product.test.ts b/__tests__/routes/product.test.ts deleted file mode 100644 index 43d344b..0000000 --- a/__tests__/routes/product.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import express from 'express'; -import { authenticateToken } from '../middlewares/checkAuth.test'; -import { createProduct, listProducts, getProduct } from '../controllers/ProductController.test'; - -const productRouter = express.Router(); - -productRouter.post('/', authenticateToken, createProduct) -productRouter.get('/', listProducts); -productRouter.get('/:id', getProduct); - - -export default productRouter; \ No newline at end of file diff --git a/__tests__/routes/user.test.ts b/__tests__/routes/user.test.ts deleted file mode 100644 index efb5204..0000000 --- a/__tests__/routes/user.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import express from 'express'; -import { createUser, login, logout } from '../controllers/UserController.test'; - -const userRouter = express.Router(); - -userRouter.post('/', createUser); -userRouter.post('/login', login); -userRouter.post('/logout', logout); - -export default userRouter; \ No newline at end of file diff --git a/__tests__/services/sendGrid.test.ts b/__tests__/services/sendGrid.test.ts deleted file mode 100644 index a5ae023..0000000 --- a/__tests__/services/sendGrid.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -// import { config } from "dotenv"; -// import { User, Order } from "../mongoose/Schema"; -// import client from '@sendgrid/mail'; -// config(); - -// export async function sendEmailasync(orderId:string, userId: string) { -// console.log(`Sending email for order ${orderId} to user ${userId}`); -// try { -// client.setApiKey(process.env.SENDGRID_API_KEY); -// const msg = { -// to: await User.findOne({ _id: userId }).select('email'), -// from: process.env.EMAIL_FROM, -// subject: 'Order Confirmation', -// text: 'Your order has been placed', -// html: 'Thank you for shopping with us!' -// }; -// await client.send(msg); -// console.log(`Email sent for order ${orderId} to user ${userId}`); -// // Update the order to indicate email has been sent -// await Order.findOne({ _id: orderId }).updateOne({ emailSent: true }); -// console.log(`Updated order ${orderId} to indicate email has been sent`); -// return; -// } catch (error) { -// console.error('Error sending email:', error); -// } -// }; \ No newline at end of file diff --git a/src/controllers/CartController.ts b/src/controllers/CartController.ts index 3dbd652..279bfc3 100644 --- a/src/controllers/CartController.ts +++ b/src/controllers/CartController.ts @@ -27,7 +27,6 @@ export async function addToCart(req: Request, res: Response) { } cart.markModified('products'); } - await cart.save(); res.status(200).json(cart); } catch (error) { diff --git a/src/controllers/ProductController.ts b/src/controllers/ProductController.ts index 37a17f1..2477bb8 100644 --- a/src/controllers/ProductController.ts +++ b/src/controllers/ProductController.ts @@ -18,7 +18,7 @@ export async function createProduct(req: Request, res: Response) { name, description, price, - userId: userId, + userId, }); res.status(201).json(product); @@ -33,7 +33,7 @@ export async function listProducts(req: Request, res: Response) { const { page, limit } = req.query; const dbPage = Number(page) || 0; const dbLimit = Number(limit) || 50; - const products = await Product.find().sort({ price: 1 }).skip(Number(dbPage) * Number(dbLimit)).limit(Number(dbLimit)); + const products = await Product.find(null, 'name description price').sort({ price: 1 }).skip(Number(dbPage) * Number(dbLimit)).limit(Number(dbLimit)); res.json(products); } catch (error) { @@ -45,7 +45,7 @@ export async function listProducts(req: Request, res: Response) { export async function getProduct(req: Request, res: Response) { const { id } = req.params; try { - const product = await Product.findById(id); + const product = await Product.findById(id, 'name description price'); if(!product) { res.status(404).json({ error: 'Product not found.' }); return; diff --git a/tsconfig.json b/tsconfig.json index f49f825..e6fc176 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,5 @@ { + "exclude": ["__tests__"], "compilerOptions": { "module": "CommonJS", "allowSyntheticDefaultImports": true, @@ -7,6 +8,6 @@ "moduleResolution": "node", "sourceMap": true, "outDir": "./dist", - "rootDir": "./src" + "rootDir": "./src", } } \ No newline at end of file