diff --git a/starter-project-backend-g31/src/controllers/comment.ts b/starter-project-backend-g31/src/controllers/comment.ts index d225522..487a3e3 100644 --- a/starter-project-backend-g31/src/controllers/comment.ts +++ b/starter-project-backend-g31/src/controllers/comment.ts @@ -1,6 +1,8 @@ import {Request,Response} from 'express'; import mongoose from 'mongoose'; import {Comment} from'../models/comment'; +import {userModel} from'../models/user-model'; +import {Article} from'../models/article'; export async function getCommentsWithArticleId (limit = 3, skip = 0, article_id: any) { @@ -24,8 +26,20 @@ export async function deleteCommentsWithArticleId(article_id: any) { export async function getCommentById(req: Request,res: Response){ try{ - const comment = await Comment.findById(req.params.commentId); - res.status(200).json(comment); + + const comment = await Comment.findById(req.params.commentId) + .populate([ + { + path: 'author', + select: ['name -_id'] + }, + { + path :'article', + select: 'content -_id' + + } + ]); + res.status(200).send(comment); }catch(err){ res.status(404).send("Error"); @@ -33,10 +47,17 @@ export async function getCommentById(req: Request,res: Response){ } export async function addComment(req: Request,res:Response){ + const user = await userModel.findById(req.params.userId); + if (!user) return res.status(404).send("User not found"); + + const article = await Article.findById(req.params.articleId); + if (!article) return res.status(404).send("Article not found"); + + const comment = new Comment({ - author: req.body.author, - description: req.body.description, - article: req.body.article + author: req.params.userId, + article: req.params.articleId, + description: req.body.description }) try{ const savedComment = await comment.save(); @@ -47,23 +68,45 @@ export async function addComment(req: Request,res:Response){ } export async function deleteCommentById(req:Request,res:Response){ + + const user = await userModel.findById(req.params.userId); + if (!user) return res.status(404).send("User not found"); + const article = await Article.findById(req.params.articleId); + if (!article) return res.status(404).send("Article not found"); try{ - const deletedComment = await Comment.findByIdAndRemove(req.params.commentId); - res.status(200).json(deletedComment); + let comment:any = await Comment.findById(req.params.commentId); + + if (comment.author == req.params.userId){ + const deletedComment = await Comment.remove({ _id:req.params.commentId}); + res.status(200).json(deletedComment); + } + else{ + res.status(401).send("You are not alowed to delete this comment"); + } }catch(err){ res.status(404).send("Error"); } } export async function updateCommentById(req:Request,res:Response){ + const user = await userModel.findById(req.params.userId); + if (!user) return res.status(404).send("User not found"); + const article = await Article.findById(req.params.articleId); + if (!article) return res.status(404).send("Article not found"); + try{ + let comment:any = await Comment.findById(req.params.commentId); - const updatedComment = await Comment.updateOne({ _id:req.params.commentId}, - { $set:{ - author: req.body.author, - description: req.body.description - }}); - res.status(200).json(updatedComment); + if (comment.author == req.params.userId){ + const updatedComment = await Comment.updateOne({ _id:req.params.commentId}, + { $set:{ + description: req.body.description + }}); + res.status(200).json(updatedComment); + } + else{ + res.status(401).send("You are not alowed to edit this comment"); + } }catch(err){ res.status(404).send(err); diff --git a/starter-project-backend-g31/src/controllers/rating.ts b/starter-project-backend-g31/src/controllers/rating.ts index f36e70e..cbedb8b 100644 --- a/starter-project-backend-g31/src/controllers/rating.ts +++ b/starter-project-backend-g31/src/controllers/rating.ts @@ -1,96 +1,96 @@ -import { Rating } from "../models/rating"; - -export const getAllRatings = (req: any, res: any) => { - return Rating.find({}) - .then((ratings: any) => res.send(ratings)) - .catch((error: any) => res.status(404).send(error)); -}; - -export const getSingleRating = async (req: any, res: any) => { - try { - const rating = await Rating.findById(req.params.id); - if (rating) return res.send(rating) - return res.status(404).send("cannot get rating"); - } catch (error) { - return res.status(404).send("cannot get rating"); - } -}; -export const getAllRatingsForAGivenArticle = async (req: any, res: any) => { - try { - const ratings = await Rating.find({ articleID: req.params.articleID }) - if (ratings.length > 0) return res.send(ratings); - return res.status(404).send("Ratings not found"); - } - catch (error) { - res.status(404).send("Ratings not found") - } -} -export const getAllRatingsForAGivenUser = async (req: any, res: any) => { - try { - const ratings = await Rating.find({ userID: req.params.userID }) - if (ratings.length > 0) return res.send(ratings); - return res.status(404).send("Ratings not found"); - } - catch (error) { - return res.status(404).send("Ratings not found") - } -} -export const getAllRatingsForAGivenArticleAndUser = async (req: any, res: any) => { - try { - const ratings = await Rating.find({ articleID: req.params.articleID, userID: req.params.userID }) - if (ratings.length > 0) return res.send(ratings); - return res.status(404).send("Ratings not found"); - } - catch (error) { - return res.status(404).send("Ratings not found") - } -} - - -export const createRating = async (req: any, res: any) => { - try { - const ratedBefore = await Rating.findOne({ articleID: req.body.articleID, userID: req.body.userID }); - if (ratedBefore) { - ratedBefore.rating = req.body.rating - await ratedBefore.save() - return res.send(ratedBefore) - } - let newRating = new Rating({ - articleID: req.body.articleID, - userID: req.body.userID, - rating: req.body.rating, - }); - await newRating.save(); - return res.status(201).send(newRating) - } - catch (error) { - res.status(400).send("error"); - } -} - -export const updateRating = async (req: any, res: any) => { - try { - const rating = await Rating.findById({ _id: req.params.id }) - if (!rating) return res.status(404).send("Rating not found to be updated") - rating.rating = req.body.rating || rating.rating; - await rating.save() - return res.send(rating) - } catch (er) { - return res.status(404).send("Please enter a valid ID") - } - -}; - -export const deleteRating = async (req: any, res: any) => { - try { - const rating = await Rating.find({ _id: req.params.id }) - if (!rating) return res.status(404).send("Rating not found to be deleted") - const deleteSuccess = await Rating.deleteOne({ _id: req.params.id }) - if (!deleteSuccess) return res.status(500).send("Cannot delete rating") - return res.send(rating) - } - catch (e) { - return res.status(404).send("Please enter a valid id") - } - -}; +import { Rating } from "../models/rating"; + +export const getAllRatings = (req: any, res: any) => { + return Rating.find({}) + .then((ratings: any) => res.send(ratings)) + .catch((error: any) => res.status(404).send(error)); +}; + +export const getSingleRating = async (req: any, res: any) => { + try { + const rating = await Rating.findById(req.params.id); + if (rating) return res.send(rating) + return res.status(404).send("cannot get rating"); + } catch (error) { + return res.status(404).send("cannot get rating"); + } +}; +export const getAllRatingsForAGivenArticle = async (req: any, res: any) => { + try { + const ratings = await Rating.find({ articleID: req.params.articleID }) + if (ratings.length > 0) return res.send(ratings); + return res.status(404).send("Ratings not found"); + } + catch (error) { + res.status(404).send("Ratings not found") + } +} +export const getAllRatingsForAGivenUser = async (req: any, res: any) => { + try { + const ratings = await Rating.find({ userID: req.params.userID }) + if (ratings.length > 0) return res.send(ratings); + return res.status(404).send("Ratings not found"); + } + catch (error) { + return res.status(404).send("Ratings not found") + } +} +export const getAllRatingsForAGivenArticleAndUser = async (req: any, res: any) => { + try { + const ratings = await Rating.find({ articleID: req.params.articleID, userID: req.params.userID }) + if (ratings.length > 0) return res.send(ratings); + return res.status(404).send("Ratings not found"); + } + catch (error) { + return res.status(404).send("Ratings not found") + } +} + + +export const createRating = async (req: any, res: any) => { + try { + const ratedBefore = await Rating.findOne({ articleID: req.body.articleID, userID: req.body.userID }); + if (ratedBefore) { + ratedBefore.rating = req.body.rating + await ratedBefore.save() + return res.send(ratedBefore) + } + let newRating = new Rating({ + articleID: req.body.articleID, + userID: req.body.userID, + rating: req.body.rating, + }); + await newRating.save(); + return res.status(201).send(newRating) + } + catch (error) { + res.status(400).send("error"); + } +} + +export const updateRating = async (req: any, res: any) => { + try { + const rating = await Rating.findById({ _id: req.params.id }) + if (!rating) return res.status(404).send("Rating not found to be updated") + rating.rating = req.body.rating || rating.rating; + await rating.save() + return res.send(rating) + } catch (er) { + return res.status(404).send("Please enter a valid ID") + } + +}; + +export const deleteRating = async (req: any, res: any) => { + try { + const rating = await Rating.find({ _id: req.params.id }) + if (!rating) return res.status(404).send("Rating not found to be deleted") + const deleteSuccess = await Rating.deleteOne({ _id: req.params.id }) + if (!deleteSuccess) return res.status(500).send("Cannot delete rating") + return res.send(rating) + } + catch (e) { + return res.status(404).send("Please enter a valid id") + } + +}; diff --git a/starter-project-backend-g31/src/controllers/user.ts b/starter-project-backend-g31/src/controllers/user.ts index c4762c2..2be47ab 100644 --- a/starter-project-backend-g31/src/controllers/user.ts +++ b/starter-project-backend-g31/src/controllers/user.ts @@ -1,170 +1,170 @@ -import { userModel } from '../models/user-model'; -import { NextFunction, Request, Response } from 'express' - -/* -@Description: Get all users -@Route: users/ -@Access: Public -*/ -export const getUsers = async ( - req: Request, - res: Response, - _next: NextFunction - ) => { - try { - const users = await userModel.find({}) - const results = users.map((user) => ({ _id: user._id, name: user.name, email: user.email })) - if (!users) { - return res - .status(404) - .json({ data: `Users do not exist` }) - } - return res.status(200).json({ data: results }) - } catch (err) { - return res - .status(500) - .json({ data: 'Error: Retrieving users failed' }) - } - } - - -/* -@Description: Get a user by ID -@Route: users/:id -@Access: Public -*/ -export const getUserById = async ( - req: Request, - res: Response, - _next: NextFunction - ) => { - try { - const { id } = req.params - const user = await userModel.findById(id) - if (!user) { - return res - .status(404) - .json({ data: `Error: User with id ${id} does not exist` }) - } - return res.status(200).json({ data: { _id: user._id, name: user.name, email: user.email } }) - } catch (err) { - return res - .status(500) - .json({ data: 'Error: Retrieving user failed' }) - } - } - -/* -@Description: Filter users by name or email -@Route: users/filter/:name, users/filter/:email -@Access: Public -*/ -export const filterUsers = async ( - req: Request, - res: Response, - _next: NextFunction - ) => { - try { - const { name, email } = req.params - const user: any = await userModel.find({$or:[{ name: name },{ email: email }]}) - if (!user) { - return res - .status(404) - .json({ data: `Error: User with specified parameters does not exist` }) - } - return res.status(200).json({ data: { _id: user._id, name: user.name, email: user.email } }) - } catch (err) { - return res - .status(500) - .json({ data: 'Error: Retrieving user failed' }) - } - } - -/* -@Description: Create a user -@Route: users/ -@Access: Private -*/ -export const createUser = async ( - req: Request, - res: Response, - _next: NextFunction - ) => { - const { name, email, password } = req.body - const user = new userModel({ - name, - email, - password - }) - try { - const newUser = await user.save() - return res.status(201).json({ data: { _id: newUser._id, name: newUser.name, email: newUser.email } }) - } catch (err) { - return res - .status(500) - .json({ data: 'Error: Creation of user failed' }) - } - } - - - -/* -@Description: Update a user using a specific Id -@Route: users/update/:id -@Access: Private -*/ -export const updateUser = async ( - req: Request, - res: Response, - _next: NextFunction - ) => { - try { - const { id } = req.params - - const user = await userModel.findByIdAndUpdate( - id, - { - $set: req.body - }, - { new: true, runValidators:true, } - ) - if (!user) { - return res.status(404).json({ - message: `Error: User with id number ${id} does not exist` - }) - } - return res.status(201).json({ data: { _id: user._id, name: user.name, email: user.email } }) - } catch (e) { - return res - .status(500) - .json({ data: 'Error: User update operation failed' }) - } - } - - -/* -@Description: Delete a user using a specific Id -@Route: users/delete/:id -@Access: Private -*/ -export const deleteUser = async ( - req: Request, - res: Response, - _next: NextFunction - ) => { - try { - const { id } = req.params - const user = await userModel.findByIdAndDelete({ _id: id }) - - if (!user) { - return res.status(404).json({ - message: `Error: User with id number ${id} does not exist` - }) - } - return res.status(201).json({ data: 'User deleted successfully' }) - } catch (e) { - return res - .status(500) - .json({ data: 'Error: User delete operation failed' }) - } - } +import { userModel } from '../models/user-model'; +import { NextFunction, Request, Response } from 'express' + +/* +@Description: Get all users +@Route: users/ +@Access: Public +*/ +export const getUsers = async ( + req: Request, + res: Response, + _next: NextFunction + ) => { + try { + const users = await userModel.find({}) + const results = users.map((user) => ({ _id: user._id, name: user.name, email: user.email })) + if (!users) { + return res + .status(404) + .json({ data: `Users do not exist` }) + } + return res.status(200).json({ data: results }) + } catch (err) { + return res + .status(500) + .json({ data: 'Error: Retrieving users failed' }) + } + } + + +/* +@Description: Get a user by ID +@Route: users/:id +@Access: Public +*/ +export const getUserById = async ( + req: Request, + res: Response, + _next: NextFunction + ) => { + try { + const { id } = req.params + const user = await userModel.findById(id) + if (!user) { + return res + .status(404) + .json({ data: `Error: User with id ${id} does not exist` }) + } + return res.status(200).json({ data: { _id: user._id, name: user.name, email: user.email } }) + } catch (err) { + return res + .status(500) + .json({ data: 'Error: Retrieving user failed' }) + } + } + +/* +@Description: Filter users by name or email +@Route: users/filter/:name, users/filter/:email +@Access: Public +*/ +export const filterUsers = async ( + req: Request, + res: Response, + _next: NextFunction + ) => { + try { + const { name, email } = req.params + const user: any = await userModel.find({$or:[{ name: name },{ email: email }]}) + if (!user) { + return res + .status(404) + .json({ data: `Error: User with specified parameters does not exist` }) + } + return res.status(200).json({ data: { _id: user._id, name: user.name, email: user.email } }) + } catch (err) { + return res + .status(500) + .json({ data: 'Error: Retrieving user failed' }) + } + } + +/* +@Description: Create a user +@Route: users/ +@Access: Private +*/ +export const createUser = async ( + req: Request, + res: Response, + _next: NextFunction + ) => { + const { name, email, password } = req.body + const user = new userModel({ + name, + email, + password + }) + try { + const newUser = await user.save() + return res.status(201).json({ data: { _id: newUser._id, name: newUser.name, email: newUser.email } }) + } catch (err) { + return res + .status(500) + .json({ data: 'Error: Creation of user failed' }) + } + } + + + +/* +@Description: Update a user using a specific Id +@Route: users/update/:id +@Access: Private +*/ +export const updateUser = async ( + req: Request, + res: Response, + _next: NextFunction + ) => { + try { + const { id } = req.params + + const user = await userModel.findByIdAndUpdate( + id, + { + $set: req.body + }, + { new: true, runValidators:true, } + ) + if (!user) { + return res.status(404).json({ + message: `Error: User with id number ${id} does not exist` + }) + } + return res.status(201).json({ data: { _id: user._id, name: user.name, email: user.email } }) + } catch (e) { + return res + .status(500) + .json({ data: 'Error: User update operation failed' }) + } + } + + +/* +@Description: Delete a user using a specific Id +@Route: users/delete/:id +@Access: Private +*/ +export const deleteUser = async ( + req: Request, + res: Response, + _next: NextFunction + ) => { + try { + const { id } = req.params + const user = await userModel.findByIdAndDelete({ _id: id }) + + if (!user) { + return res.status(404).json({ + message: `Error: User with id number ${id} does not exist` + }) + } + return res.status(201).json({ data: 'User deleted successfully' }) + } catch (e) { + return res + .status(500) + .json({ data: 'Error: User delete operation failed' }) + } + } diff --git a/starter-project-backend-g31/src/controllers/userProfile.ts b/starter-project-backend-g31/src/controllers/userProfile.ts index 7f2bfd2..fd04d9e 100644 --- a/starter-project-backend-g31/src/controllers/userProfile.ts +++ b/starter-project-backend-g31/src/controllers/userProfile.ts @@ -1,5 +1,4 @@ import {Request, Response} from "express" - import { Model, Mongoose, Schema } from "mongoose" import { destructProfile } from "../helper/userprofilehelper" import {UserProfile} from "../models/UserProfile" diff --git a/starter-project-backend-g31/src/helper/userprofilehelper.ts b/starter-project-backend-g31/src/helper/userprofilehelper.ts index d57a3c5..65a791e 100644 --- a/starter-project-backend-g31/src/helper/userprofilehelper.ts +++ b/starter-project-backend-g31/src/helper/userprofilehelper.ts @@ -1,23 +1,23 @@ -export function destructProfile(body: any){ - var {_id, name, username, bio, phone, avatar } = body - - interface Profile{ - _id?: string, - name?: string, - username?: string, - bio?: string, - phone?: string, - avatar?: string - } - - var newProfile: Profile = {} - - if (_id) newProfile["_id"] = _id - if (username) newProfile["username"] = username - if (name) newProfile["name"] = name - if (bio) newProfile["bio"] = bio - if (phone) newProfile["phone"] = phone - if (avatar) newProfile["avatar"] = avatar - - return newProfile +export function destructProfile(body: any){ + var {_id, name, username, bio, phone, avatar } = body + + interface Profile{ + _id?: string, + name?: string, + username?: string, + bio?: string, + phone?: string, + avatar?: string + } + + var newProfile: Profile = {} + + if (_id) newProfile["_id"] = _id + if (username) newProfile["username"] = username + if (name) newProfile["name"] = name + if (bio) newProfile["bio"] = bio + if (phone) newProfile["phone"] = phone + if (avatar) newProfile["avatar"] = avatar + + return newProfile } \ No newline at end of file diff --git a/starter-project-backend-g31/src/models/UserProfile.ts b/starter-project-backend-g31/src/models/UserProfile.ts index 9937a14..b3fc92c 100644 --- a/starter-project-backend-g31/src/models/UserProfile.ts +++ b/starter-project-backend-g31/src/models/UserProfile.ts @@ -1,36 +1,36 @@ -import mongoose,{Schema,Document} from "mongoose" - -export interface IProfile{ - name: string | undefined, - username: string, - bio: string | undefined, - phone: string | undefined, - avatar: string | undefined, -} -export const UserProfileSchema = new mongoose.Schema({ - name: { - type: String, - required: true - }, - username: { - type: String, - required: true, - unique: true - }, - - bio: { - type: String - }, - - phone: { - type: String - }, - - avatar: { - - required: false - } - -}); - -export const UserProfile = mongoose.model("UserProfile", UserProfileSchema); +import mongoose,{Schema,Document} from "mongoose" + +export interface IProfile{ + name: string | undefined, + username: string, + bio: string | undefined, + phone: string | undefined, + avatar: string | undefined, +} +export const UserProfileSchema = new mongoose.Schema({ + name: { + type: String, + required: true + }, + username: { + type: String, + required: true, + unique: true + }, + + bio: { + type: String + }, + + phone: { + type: String + }, + + avatar: { + + required: false + } + +}); + +export const UserProfile = mongoose.model("UserProfile", UserProfileSchema); diff --git a/starter-project-backend-g31/src/models/article.ts b/starter-project-backend-g31/src/models/article.ts index 6838325..cb56313 100644 --- a/starter-project-backend-g31/src/models/article.ts +++ b/starter-project-backend-g31/src/models/article.ts @@ -1,39 +1,39 @@ -import mongoose , { Schema, Document } from 'mongoose'; - -export interface IArticle extends Document{ - author:string, - content:string, - comment:string, - rating:string, - postdate:Date -} - - -const articleSchema: Schema = new mongoose.Schema({ - author: { - type: String, - minlength: 5, - maxlength:50, - required: true - }, - content: { - type: String, - minLength: 20, - maxLength: 10000, - required: true, - }, - rating: { - type: Number, - min: 0, - max: 5, - required: true - }, - postdate: { - type: Date, - default: Date.now() - } -}); - - - +import mongoose , { Schema, Document } from 'mongoose'; + +export interface IArticle extends Document{ + author:string, + content:string, + comment:string, + rating:string, + postdate:Date +} + + +const articleSchema: Schema = new mongoose.Schema({ + author: { + type: String, + minlength: 5, + maxlength:50, + required: true + }, + content: { + type: String, + minLength: 20, + maxLength: 10000, + required: true, + }, + rating: { + type: Number, + min: 0, + max: 5, + required: true + }, + postdate: { + type: Date, + default: Date.now() + } +}); + + + export const Article = mongoose.model('Article', articleSchema); \ No newline at end of file diff --git a/starter-project-backend-g31/src/models/comment.ts b/starter-project-backend-g31/src/models/comment.ts index dab9f28..7409c3a 100644 --- a/starter-project-backend-g31/src/models/comment.ts +++ b/starter-project-backend-g31/src/models/comment.ts @@ -1,8 +1,23 @@ import mongoose from 'mongoose'; +import {userModel} from './user-model'; +import {Article} from './article'; -const CommentSchema = new mongoose.Schema({ +export interface IComment extends Document{ + author:mongoose.Types.ObjectId, + article:mongoose.Types.ObjectId, + description:string, + date:Date +} + +const CommentSchema :mongoose.Schema = new mongoose.Schema({ author : { - type : String, + type : mongoose.Types.ObjectId, + ref: userModel, + required : true + }, + article : { + type : mongoose.Types.ObjectId, + ref: Article, required : true }, description : { @@ -13,12 +28,9 @@ const CommentSchema = new mongoose.Schema({ type : Date, default : Date.now() }, - article: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Article' - } + }); -export const Comment = mongoose.model('Comment', CommentSchema); +export const Comment = mongoose.model('Comment', CommentSchema); diff --git a/starter-project-backend-g31/src/models/rating.ts b/starter-project-backend-g31/src/models/rating.ts index d0cd75c..8f9ccde 100644 --- a/starter-project-backend-g31/src/models/rating.ts +++ b/starter-project-backend-g31/src/models/rating.ts @@ -1,33 +1,33 @@ -import mongoose , { Schema, Document } from 'mongoose'; - -export interface IRating extends Document{ - articleID:string, - userID:string, - rating:number, - ratedAt:string, -} -const ratingSchema : Schema = new mongoose.Schema( - { - articleID: { - type: String, - required: true - }, - userID: { - type: String, - required: true - }, - rating: { - type: Number, - required: true - }, - ratedAt: { - type: Date, - default: Date.now() - } - - } -); - -export const Rating = mongoose.model("Rating", ratingSchema); - - +import mongoose , { Schema, Document } from 'mongoose'; + +export interface IRating extends Document{ + articleID:string, + userID:string, + rating:number, + ratedAt:string, +} +const ratingSchema : Schema = new mongoose.Schema( + { + articleID: { + type: String, + required: true + }, + userID: { + type: String, + required: true + }, + rating: { + type: Number, + required: true + }, + ratedAt: { + type: Date, + default: Date.now() + } + + } +); + +export const Rating = mongoose.model("Rating", ratingSchema); + + diff --git a/starter-project-backend-g31/src/models/user-model.ts b/starter-project-backend-g31/src/models/user-model.ts index 47284b0..c781c08 100644 --- a/starter-project-backend-g31/src/models/user-model.ts +++ b/starter-project-backend-g31/src/models/user-model.ts @@ -1,80 +1,80 @@ -// user.model.ts -import { Document, Schema, model } from 'mongoose'; - -import bcrypt from 'bcryptjs'; - -// Create the interface -export interface IUser extends Document { - [x: string]: any; - name: string; - email: string; - password: string; -} - -// Create the schema -const userSchema = new Schema({ - name: { - type: String, - required: true, - unique: true - }, - email: { - type: String, - required: true, - unique: true - }, - password: { - type: String, - required: true, - minlength: 6, - maxlength: 128 - } -}, { - timestamps: { - createdAt: 'created_at', - updatedAt: 'updated_at' - } -}); - - -// methods - -userSchema.pre('save', function preSave(next) { - let model = this; - - model.hashpassword(model.password, (err: any, hash: string) => { - model.password = hash; - next(); - }); -}) - - -userSchema.method({ - hashpassword(passwd, cb) { - let createHash = (err: any, hash: any) => { - if (err) { - return cb(err); - } - - cb(null, hash); - } - - let generateSalt = (err: any, salt: string | number) => { - if (err) { - return cb(err); - } - - // Hash the password using the generated salt - bcrypt.hash(passwd, salt, createHash); - } - - // Generate a salt factor - bcrypt.genSalt(12, generateSalt); - } -}) - -// Create and export user model -export const userModel = model("User", userSchema); - - - +// user.model.ts +import { Document, Schema, model } from 'mongoose'; + +import bcrypt from 'bcryptjs'; + +// Create the interface +export interface IUser extends Document { + [x: string]: any; + name: string; + email: string; + password: string; +} + +// Create the schema +const userSchema = new Schema({ + name: { + type: String, + required: true, + unique: true + }, + email: { + type: String, + required: true, + unique: true + }, + password: { + type: String, + required: true, + minlength: 6, + maxlength: 128 + } +}, { + timestamps: { + createdAt: 'created_at', + updatedAt: 'updated_at' + } +}); + + +// methods + +userSchema.pre('save', function preSave(next) { + let model = this; + + model.hashpassword(model.password, (err: any, hash: string) => { + model.password = hash; + next(); + }); +}) + + +userSchema.method({ + hashpassword(passwd, cb) { + let createHash = (err: any, hash: any) => { + if (err) { + return cb(err); + } + + cb(null, hash); + } + + let generateSalt = (err: any, salt: string | number) => { + if (err) { + return cb(err); + } + + // Hash the password using the generated salt + bcrypt.hash(passwd, salt, createHash); + } + + // Generate a salt factor + bcrypt.genSalt(12, generateSalt); + } +}) + +// Create and export user model +export const userModel = model("User", userSchema); + + + diff --git a/starter-project-backend-g31/src/routes/article.ts b/starter-project-backend-g31/src/routes/article.ts index 4bbe6e6..190347c 100644 --- a/starter-project-backend-g31/src/routes/article.ts +++ b/starter-project-backend-g31/src/routes/article.ts @@ -1,13 +1,13 @@ -import mongoose from 'mongoose'; -import express from 'express'; -import {getMany, getOne, createArticle, updateOne, deleteOne} from '../controllers/article'; - - -const router = express.Router(); -router.get('/', getMany); -router.get('/:id', getOne); -router.post('/', createArticle); -router.put('/:id', updateOne); -router.delete('/:id', deleteOne); - +import mongoose from 'mongoose'; +import express from 'express'; +import {getMany, getOne, createArticle, updateOne, deleteOne} from '../controllers/article'; + + +const router = express.Router(); +router.get('/', getMany); +router.get('/:id', getOne); +router.post('/', createArticle); +router.put('/:id', updateOne); +router.delete('/:id', deleteOne); + export default router; \ No newline at end of file diff --git a/starter-project-backend-g31/src/routes/comment.ts b/starter-project-backend-g31/src/routes/comment.ts index e9a8e7a..a89a4ff 100644 --- a/starter-project-backend-g31/src/routes/comment.ts +++ b/starter-project-backend-g31/src/routes/comment.ts @@ -8,14 +8,12 @@ import { updateCommentById} from '../controllers/comment'; const router = express.Router(); - - router.get('/:commentId', getCommentById); -router.post('/', addComment); +router.post('/:userId/:articleId', addComment); -router.delete('/:commentId', deleteCommentById); +router.delete('/:commentId/:userId/:articleId', deleteCommentById); -router.patch('/:commentId', updateCommentById); +router.patch('/:commentId/:userId/:articleId', updateCommentById); export const commentRoute = router; \ No newline at end of file diff --git a/starter-project-backend-g31/src/routes/index.ts b/starter-project-backend-g31/src/routes/index.ts index f562c89..5e294cf 100644 --- a/starter-project-backend-g31/src/routes/index.ts +++ b/starter-project-backend-g31/src/routes/index.ts @@ -1,19 +1,19 @@ -import * as express from 'express'; -const indexRouter = express.Router(); - -/* - * Returns API status - * @route GET / - * @group Index - API service status - * @returns {object} 200 - * @returns {Error} default - Unexpected error - */ -indexRouter.get('/', async function(req: express.Request, res: express.Response) { - return res.json({ - title: 'Blog API', - version: '1.0.0', - description: 'Services for managing blog applications' - }) -}); - +import * as express from 'express'; +const indexRouter = express.Router(); + +/* + * Returns API status + * @route GET / + * @group Index - API service status + * @returns {object} 200 + * @returns {Error} default - Unexpected error + */ +indexRouter.get('/', async function(req: express.Request, res: express.Response) { + return res.json({ + title: 'Blog API', + version: '1.0.0', + description: 'Services for managing blog applications' + }) +}); + export const indexRoute = indexRouter; \ No newline at end of file diff --git a/starter-project-backend-g31/src/routes/rating.ts b/starter-project-backend-g31/src/routes/rating.ts index a9ff9e3..1652965 100644 --- a/starter-project-backend-g31/src/routes/rating.ts +++ b/starter-project-backend-g31/src/routes/rating.ts @@ -1,48 +1,48 @@ -import express from "express" -import { - getAllRatings, - getSingleRating, - createRating, - updateRating, - deleteRating, - getAllRatingsForAGivenArticle, - getAllRatingsForAGivenArticleAndUser, - getAllRatingsForAGivenUser -} from "../controllers/rating" - -const ratingRouter = express.Router() - -ratingRouter.get("/", async (req, res) => { - await getAllRatings(req, res); -}) - -ratingRouter.get("/:id", async (req, res) => { - await getSingleRating(req, res) -}) - -ratingRouter.get("/articles/:articleID", async (req, res) => { - await getAllRatingsForAGivenArticle(req, res) -}) - -ratingRouter.get("/users/:userID", async (req, res) => { - await getAllRatingsForAGivenUser(req, res) -}) - -ratingRouter.get("/:articleID/:userID", async (req, res) => { - await getAllRatingsForAGivenArticleAndUser(req, res) -}) - -ratingRouter.post("/", async (req, res) => { - const response = await createRating(req, res) -}) - -ratingRouter.put("/:id", async (req, res) => { - await updateRating(req, res); -}) - -ratingRouter.delete("/:id", async (req, res) => { - await deleteRating(req, res); -}) - - +import express from "express" +import { + getAllRatings, + getSingleRating, + createRating, + updateRating, + deleteRating, + getAllRatingsForAGivenArticle, + getAllRatingsForAGivenArticleAndUser, + getAllRatingsForAGivenUser +} from "../controllers/rating" + +const ratingRouter = express.Router() + +ratingRouter.get("/", async (req, res) => { + await getAllRatings(req, res); +}) + +ratingRouter.get("/:id", async (req, res) => { + await getSingleRating(req, res) +}) + +ratingRouter.get("/articles/:articleID", async (req, res) => { + await getAllRatingsForAGivenArticle(req, res) +}) + +ratingRouter.get("/users/:userID", async (req, res) => { + await getAllRatingsForAGivenUser(req, res) +}) + +ratingRouter.get("/:articleID/:userID", async (req, res) => { + await getAllRatingsForAGivenArticleAndUser(req, res) +}) + +ratingRouter.post("/", async (req, res) => { + const response = await createRating(req, res) +}) + +ratingRouter.put("/:id", async (req, res) => { + await updateRating(req, res); +}) + +ratingRouter.delete("/:id", async (req, res) => { + await deleteRating(req, res); +}) + + export default ratingRouter; \ No newline at end of file diff --git a/starter-project-backend-g31/src/routes/routes.ts b/starter-project-backend-g31/src/routes/routes.ts index 690f74c..5009ed8 100644 --- a/starter-project-backend-g31/src/routes/routes.ts +++ b/starter-project-backend-g31/src/routes/routes.ts @@ -1,11 +1,11 @@ -import Express,{Router} from "express"; -import { getProfileHandler, createProfileHandler, deleteProfileHandler, updateProfileHandler, getProfilesHandler } from "../controllers/userProfile" - - -export const router: Router = Express.Router() - -router.get("/:id", getProfileHandler) -router.get("", getProfilesHandler) -router.post("", createProfileHandler) -router.delete("/:id", deleteProfileHandler) -router.patch("/:id", updateProfileHandler) +import Express,{Router} from "express"; +import { getProfileHandler, createProfileHandler, deleteProfileHandler, updateProfileHandler, getProfilesHandler } from "../controllers/userProfile" + + +export const router: Router = Express.Router() + +router.get("/:id", getProfileHandler) +router.get("", getProfilesHandler) +router.post("", createProfileHandler) +router.delete("/:id", deleteProfileHandler) +router.patch("/:id", updateProfileHandler) diff --git a/starter-project-backend-g31/src/routes/user.ts b/starter-project-backend-g31/src/routes/user.ts index 8702c0e..85ceba1 100644 --- a/starter-project-backend-g31/src/routes/user.ts +++ b/starter-project-backend-g31/src/routes/user.ts @@ -1,88 +1,88 @@ -import { - getUsers, - getUserById, - filterUsers, - createUser, - updateUser, - deleteUser -} from '../controllers/user'; -import * as express from 'express'; -const userRouter = express.Router(); - -/* - * @typedef User - * @property {string} name.required - User name - * @property {string} email.required - User email address - * @property {string} password.required - User password with a minimum length requirement of 6 - */ - -/* - * Returns ALL Users - * @route GET /users - * @returns {object} 200 - Array of users - * @returns {Error} default - Unexpected error - */ -userRouter.get('/', getUsers); - -/* - * Get a user by id - * @route GET /users/{id} - * @param {string} id.path.required - user id - * @returns {object} 200 - User object - * @returns {Error} default - Unexpected error - */ -userRouter.get('/:id', getUserById); - - -/* - * Returns filetered User by name - * @route GET /users/filter/:name - * @param {string} name.query - filter query of name - * @returns {object} 200 - User object - * @returns {Error} default - Unexpected error - */ -userRouter.get('/filter/:name', filterUsers); - - -/* - * Returns filetered User by email - * @route GET /users/filter/:email - * @param {string} email.query - filter query of email - * @returns {object} 200 - User object - * @returns {Error} default - Unexpected error - */ -userRouter.get('/filter/:email', filterUsers); - - -/* - * Create a new user - * @route Post /users - * @param {USER.model} user.body - the new user object - * @returns {object} 200 - User object - * @returns {Error} default - Unexpected error - */ -userRouter.post('/', createUser); - - -/* - * Update an existing user by id - * @route Put /users/update/:id - * @param {string} id.path.required - user id - * @param {USER.model} user.body - the updated user object - * @returns {object} 200 - User object - * @returns {Error} default - Unexpected error - */ -userRouter.patch('/update/:id', updateUser); - - -/* - * Remove a user with id - * @route DELETE /users/delete/:id - * @param {string} id.path.required - user id - * @returns {object} 200 - User object - * @returns {Error} default - Unexpected error - */ -userRouter.delete('/delete/:id', deleteUser); - - -export const userRoute = userRouter; +import { + getUsers, + getUserById, + filterUsers, + createUser, + updateUser, + deleteUser +} from '../controllers/user'; +import * as express from 'express'; +const userRouter = express.Router(); + +/* + * @typedef User + * @property {string} name.required - User name + * @property {string} email.required - User email address + * @property {string} password.required - User password with a minimum length requirement of 6 + */ + +/* + * Returns ALL Users + * @route GET /users + * @returns {object} 200 - Array of users + * @returns {Error} default - Unexpected error + */ +userRouter.get('/', getUsers); + +/* + * Get a user by id + * @route GET /users/{id} + * @param {string} id.path.required - user id + * @returns {object} 200 - User object + * @returns {Error} default - Unexpected error + */ +userRouter.get('/:id', getUserById); + + +/* + * Returns filetered User by name + * @route GET /users/filter/:name + * @param {string} name.query - filter query of name + * @returns {object} 200 - User object + * @returns {Error} default - Unexpected error + */ +userRouter.get('/filter/:name', filterUsers); + + +/* + * Returns filetered User by email + * @route GET /users/filter/:email + * @param {string} email.query - filter query of email + * @returns {object} 200 - User object + * @returns {Error} default - Unexpected error + */ +userRouter.get('/filter/:email', filterUsers); + + +/* + * Create a new user + * @route Post /users + * @param {USER.model} user.body - the new user object + * @returns {object} 200 - User object + * @returns {Error} default - Unexpected error + */ +userRouter.post('/', createUser); + + +/* + * Update an existing user by id + * @route Put /users/update/:id + * @param {string} id.path.required - user id + * @param {USER.model} user.body - the updated user object + * @returns {object} 200 - User object + * @returns {Error} default - Unexpected error + */ +userRouter.patch('/update/:id', updateUser); + + +/* + * Remove a user with id + * @route DELETE /users/delete/:id + * @param {string} id.path.required - user id + * @returns {object} 200 - User object + * @returns {Error} default - Unexpected error + */ +userRouter.delete('/delete/:id', deleteUser); + + +export const userRoute = userRouter; diff --git a/starter-project-backend-g31/src/server.ts b/starter-project-backend-g31/src/server.ts index 457f74c..d66fb38 100644 --- a/starter-project-backend-g31/src/server.ts +++ b/starter-project-backend-g31/src/server.ts @@ -1,19 +1,19 @@ -import app from "./app" -import mongoose from 'mongoose'; - -const PORT = process.env.PORT || 8000 -const DB_URI = process.env.MONGO_URI || "mongodb://localhost:27017/test"; - - -mongoose.connect(DB_URI, { - useNewUrlParser: true, - useUnifiedTopology: true, - useCreateIndex: true, - useFindAndModify: false, -}) -.then(() => { - console.log("Connected to mongodb...") - app.listen(PORT, () => console.log('Server running...')); -}) -.catch((err: any) => console.log('Error occurred while connecting', err)); - +import app from "./app" +import mongoose from 'mongoose'; + +const PORT = process.env.PORT || 8000 +const DB_URI = process.env.MONGO_URI || "mongodb://localhost:27017/test"; + + +mongoose.connect(DB_URI, { + useNewUrlParser: true, + useUnifiedTopology: true, + useCreateIndex: true, + useFindAndModify: false, +}) +.then(() => { + console.log("Connected to mongodb...") + app.listen(PORT, () => console.log('Server running...')); +}) +.catch((err: any) => console.log('Error occurred while connecting', err)); + diff --git a/starter-project-backend-g31/src/tests/__tests__/comments.test.ts b/starter-project-backend-g31/src/tests/__tests__/comments.test.ts index cd2f0a2..7fba2e9 100644 --- a/starter-project-backend-g31/src/tests/__tests__/comments.test.ts +++ b/starter-project-backend-g31/src/tests/__tests__/comments.test.ts @@ -1,181 +1,175 @@ - -import mongoose from 'mongoose' -import app from '../../app'; -import {connect, clear, disconnect} from '../setupdb' -import request from 'supertest' -import {Comment} from '../../models/comment'; - -//connect to data base before starting any test -beforeAll(async () => { - await connect(); -}); - -//disconect from database after any test -afterAll(async ()=>{ - await disconnect(); -}) - -jest.setTimeout(30000); - -// dummy data to insert -const dummy = { - author: "another person", - description: "another description" -}; - -// Test Suite on comments feature -// describe('comment', () => { - -// Create an object id for dummy document to use for testing -const commentId = mongoose.Types.ObjectId(); - -// create a variable to hole a sample/dummy document -let comment: any; - -// create and save sample document before any test -beforeEach(async()=>{ - - comment = new Comment({ - _id:commentId, - author:"someone", - description:"test comment description", - }); - await comment.save(); -}); - -// remove sample document after any test to avoid object id redundancy -afterEach(async()=>{ - await comment.remove({}) -}); - - -// test the get comment by id feature -describe('GET: "/api/comment/:id" get a comment by id', ()=>{ - - // check succes situations - - // check sent data and check status - it('return the comment', async ()=>{ - - const res = await request(app).get(`/api/comment/${commentId}`); - - expect(res.body).not.toBeNull(); - expect(res.status).toBe(200); - - }); - - // on failure - it('returns 404 status code', async()=>{ - const res = await request(app).get(`/api/comment/wrongId`); - - expect(res.status).toBe(404); - - - }); - - -}); - - -// check the add comment feature -describe('POST: "/api/comment" Add new comment', ()=>{ - - // if author and description are properly filled - - - // check status code and check response data - it('status code should be 200', async ()=>{ - const res = await request(app).post('/api/comment').send(dummy); - - expect(res.status).toBe(200); - expect( - { - author: res.body.author, - description: res.body.description - }).toStrictEqual(dummy); - }); - - - - // if author and description are not filled properly - - - // check status - it('return status code 404', async()=>{ - const res = await request(app).post('/api/comment').send({}); - expect(res.status).toBe(404); - }); - - - -}); - - -//check the update comment by id feature -describe('PATCH: "/api/comment/:id" update existing comment by id', ()=>{ - - - // check status, content type, database - it('return status code 200', async ()=>{ - const res = await request(app).patch(`/api/comment/${commentId}`).send({ - author: "changed" - }); - - const updatedcomment = await Comment.findById(commentId); - - expect(updatedcomment.author).toStrictEqual("changed"); - expect(res.status).toBe(200); - expect(res.headers['content-type']).toEqual(expect.stringContaining('json')); - - }); - - - - - - //check status - it('returns 404 status code', async()=>{ - const res = await request(app).patch(`/api/comment/wrongId`); - - expect(res.status).toBe(404); - - - }); - - -}) - - - -//check the delete comment by id feature -describe('DELETE: "/api/comment" delete existing comment by id', ()=>{ - - - // Check status code and database - it('return 200 status code', async ()=>{ - const res = await request(app).delete(`/api/comment/${commentId}`); - - const updatedcomment = await Comment.findById(commentId); - - expect(updatedcomment).toBeNull(); - expect(res.status).toBe(200); - }); - - - - - - - - //check status code - it('return 404 status code', async()=>{ - const res = await request(app).delete(`/api/comment/wrongId`); - - expect(res.status).toBe(404); - }) - - -}) -// }); - -afterAll( async () => await disconnect()); +import mongoose from 'mongoose' +import app from '../../app'; +import {connect, clear, disconnect} from '../setupdb' +import request from 'supertest' +import {Comment} from '../../models/comment'; +import {userModel} from '../../models/user-model'; +import {Article} from '../../models/article'; + +import bcrypt from 'bcrypt'; + + +//connect to data base before starting any test +beforeAll(async () => { + await connect(); +}); + +//disconect from database after any test +afterAll(async ()=>{ + await clear(); + await disconnect(); +}) + +jest.setTimeout(30000); + + + +// Test Suite on comments feature + +// Create an object id for dummy document to use for testing +const commentId = mongoose.Types.ObjectId(); +const userId = mongoose.Types.ObjectId(); +const articleId = mongoose.Types.ObjectId(); + +// create a variable to hole a sample/dummy document +let comment: any; +let user: any; +let article: any; + +// create and save sample document before any test +beforeEach(async()=>{ + user = new userModel({ + _id:userId, + name: 'Sasi', + email: 'sasi@gmail.com', + password: "password" + }) + await user.save() + + article = new Article({ + _id : articleId, + author: 'sample author', + content: 'sample article 12345678901112131415', + rating: 4 +}); + await article.save() + comment = new Comment({ + _id:commentId, + author:userId, + article: articleId, + description:"test comment description", + }); + await comment.save(); +}); +// dummy data to insert +const dummy = { + description: "another description" +}; +// remove sample document after any test to avoid object id redundancy +afterEach(async()=>{ + await Comment.collection.remove({}) + await Article.collection.remove({}) + await userModel.collection.remove({}) + + +}); + + + +// test the get comment by id feature +describe('GET: "/api/comment/:id" get a comment by id', ()=>{ + + // check succes situations + + // check sent data and check status + it('return the comment', async ()=>{ + + const res = await request(app).get(`/api/comment/${commentId}`); + expect(res.body).not.toBeNull(); + expect(res.status).toBe(200); + + }); + + // on failure + it('returns 404 status code', async()=>{ + const res = await request(app).get(`/api/comment/wrongId`); + + expect(res.status).toBe(404); + }); + }); + + +// check the add comment feature +describe('POST: "/api/comment/:userId/:articleId" Add new comment', ()=>{ + + // if author and description are properly filled + + + // check status code and check response data + it('status code should be 200', async ()=>{ + const res = await request(app).post(`/api/comment/${userId}/${articleId}`).send(dummy); + + expect(res.status).toBe(200); + expect( + { + description: res.body.description + }).toStrictEqual(dummy); + }); + + // if author and description are not filled properly + // check status + it('return status code 404', async()=>{ + const res = await request(app).post('/api/comment').send({}); + expect(res.status).toBe(404); + }); +}); + + +//check the update comment by id feature +describe('PATCH: "/api/comment/commentId:/id:userId/:articleId" update existing comment by id', ()=>{ + + // check status, content type, database + it('return status code 200', async ()=>{ + const res = await request(app).patch(`/api/comment/${commentId}/${userId}/${articleId}`).send({ + description: "changed" + }); + + const updatedcomment:any = await Comment.findById(commentId); + + expect(updatedcomment.description).toStrictEqual("changed"); + expect(res.status).toBe(200); + expect(res.headers['content-type']).toEqual(expect.stringContaining('json')); + + }); + + //check status + it('returns 404 status code', async()=>{ + const res = await request(app).patch(`/api/comment/wrongId`); + expect(res.status).toBe(404); + }); +}) + +//check the delete comment by id feature +describe('DELETE: "/api/comment" delete existing comment by id', ()=>{ + + + // Check status code and database + it('return 200 status code', async ()=>{ + const res = await request(app).delete(`/api/comment/${commentId}/${userId}/${articleId}`); + + const updatedcomment = await Comment.findById(commentId); + + expect(updatedcomment).toBeNull(); + expect(res.status).toBe(200); + }); + + //check status code + it('return 404 status code', async()=>{ + const res = await request(app).delete(`/api/comment/wrongId`); + + expect(res.status).toBe(404); + }) + + +}) + diff --git a/starter-project-backend-g31/src/tests/__tests__/user_profile.test.ts b/starter-project-backend-g31/src/tests/__tests__/user_profile.test.ts index 442f9e7..098faa2 100644 --- a/starter-project-backend-g31/src/tests/__tests__/user_profile.test.ts +++ b/starter-project-backend-g31/src/tests/__tests__/user_profile.test.ts @@ -1,242 +1,242 @@ - -import supertest from "supertest"; -import mongoose from "mongoose"; -import {clear, connect, disconnect } from "../setupdb"; -import app from "../../app"; - -import {request, Request, response} from "express" - -import { UserProfile } from "../../models/UserProfile"; - -export const userId = new mongoose.Types.ObjectId().toString(); -export const userProfile = { - _id: userId, - username: "sdcfggh", - name: "jane.doe@example.com", - bio: "Jane Doe", - phone: "+25143674477" -}; - -jest.setTimeout(10000) -describe("user profile", () => { - - beforeAll(async () => { - await connect(); -}) -// beforeEach(async () => { -// await clear(); -// }) -afterAll(async () => { - await clear(); - disconnect(); -}) - - describe("CREATE user Profile route", ()=> { - describe("", () => { - - it("should return 201 status and the user profile", async () => { - // @ts-ignore - - - - const { body, statusCode } = await supertest(app).post( - `/api/user-profiles` - ).send(userProfile); - - expect(statusCode).toBe(201); - expect(body._id).toBe(userId); - }); - - }); - - describe("given the profile already exist", () => { - - it("should return 400 status", async () => { - // @ts-ignore - - - - const { body, statusCode } = await supertest(app).post( - `/api/user-profiles` - ).send(userProfile); - - expect(statusCode).toBe(400); - - }); - - }); - - describe("given the profile is missing required field", () => { - - it("should return 400 status", async () => { - // @ts-ignore - - userProfile = { - bio: "Jane Doe", - phone: "+25143674477" - }; - - const { body, statusCode } = await supertest(app).post( - `/api/user-profiles` - ).send(userProfile); - - expect(statusCode).toBe(400); - - }); - - }); - - - }); - - - - describe("get user Profile route", ()=> { - describe("given the user profile exist", () => { - - it("should return 200 status and the user profile", async () => { - // @ts-ignore - - - - const { body, statusCode } = await supertest(app).get( - `/api/user-profiles/${userId}` - ); - - expect(statusCode).toBe(200); - expect(body._id).toBe(userId); - }); - - }); - - describe("given the user profile does not exist", () => { - - it("should return 404 status", async () => { - // @ts-ignore - - - - const { body, statusCode } = await supertest(app).get( - `/api/user-profiles/${new mongoose.Types.ObjectId().toString()}` - ); - - expect(statusCode).toBe(404); - - }); - - }); - - }); - - describe("get user Profiles route", ()=> { - describe("given the user profiles exist", () => { - - it("should return 200 status and user profiles list", async () => { - // @ts-ignore - - - const { body, statusCode } = await supertest(app).get( - `/api/user-profiles/` - ); - - expect(statusCode).toBe(200); - expect(body.length).toBeGreaterThan(0) - }); - - }); - - - }); - - describe("update user Profile route", ()=> { - describe("given the user profile exist", () => { - - it("should return 200 status and user profiles list", async () => { - // @ts-ignore - - export const newUserProfile = { - - name: "new name", - bio: "Jane Doe", - phone: "+253762737263" - }; - const { statusCode } = await supertest(app).patch( - `/api/user-profiles/${userId}` - ).send(newUserProfile); - - const {body} = await supertest(app).get( - `/api/user-profiles/${userId}` - ); - - expect(statusCode).toBe(200); - expect(body.name).toBe(newUserProfile.name) - expect(body.bio).toBe(newUserProfile.bio) - expect(body.phone).toBe(newUserProfile.phone) - }); - - }); - - describe("given the user profile does not exist", () => { - - it("should return 400 status", async () => { - // @ts-ignore - - const newUserProfile = { - - name: "new name", - bio: "Jane Doe", - phone: "+253762737263" - }; - const fakeId = "dkfjds".toString(); - const { statusCode } = await supertest(app).patch( - `/api/user-profiles/${1}` - ).send(newUserProfile); - - - - expect(statusCode).toBe(400); - - }); - - }); - - - }); - - describe("delete user Profile route", ()=> { - describe("given the user profile exist", () => { - - it("should return 204 status", async () => { - // @ts-ignore - - const {statusCode} = await supertest(app).delete( - `/api/user-profiles/${userId}` - ); - - expect(statusCode).toBe(204); - - }); - - }); - - describe("given the user profile does not exist", () => { - - it("should return 204 status", async () => { - // @ts-ignore - - const {statusCode} = await supertest(app).delete( - `/api/user-profiles/${userId}` - ); - - expect(statusCode).toBe(204); - - }); - - }); - - - }); - - - + +import supertest from "supertest"; +import mongoose from "mongoose"; +import {clear, connect, disconnect } from "../setupdb"; +import app from "../../app"; + +import {request, Request, response} from "express" + +import { UserProfile } from "../../models/UserProfile"; + +export const userId = new mongoose.Types.ObjectId().toString(); +export const userProfile = { + _id: userId, + username: "sdcfggh", + name: "jane.doe@example.com", + bio: "Jane Doe", + phone: "+25143674477" +}; + +jest.setTimeout(10000) +describe("user profile", () => { + + beforeAll(async () => { + await connect(); +}) +// beforeEach(async () => { +// await clear(); +// }) +afterAll(async () => { + await clear(); + disconnect(); +}) + + describe("CREATE user Profile route", ()=> { + describe("", () => { + + it("should return 201 status and the user profile", async () => { + // @ts-ignore + + + + const { body, statusCode } = await supertest(app).post( + `/api/user-profiles` + ).send(userProfile); + + expect(statusCode).toBe(201); + expect(body._id).toBe(userId); + }); + + }); + + describe("given the profile already exist", () => { + + it("should return 400 status", async () => { + // @ts-ignore + + + + const { body, statusCode } = await supertest(app).post( + `/api/user-profiles` + ).send(userProfile); + + expect(statusCode).toBe(400); + + }); + + }); + + describe("given the profile is missing required field", () => { + + it("should return 400 status", async () => { + // @ts-ignore + + userProfile = { + bio: "Jane Doe", + phone: "+25143674477" + }; + + const { body, statusCode } = await supertest(app).post( + `/api/user-profiles` + ).send(userProfile); + + expect(statusCode).toBe(400); + + }); + + }); + + + }); + + + + describe("get user Profile route", ()=> { + describe("given the user profile exist", () => { + + it("should return 200 status and the user profile", async () => { + // @ts-ignore + + + + const { body, statusCode } = await supertest(app).get( + `/api/user-profiles/${userId}` + ); + + expect(statusCode).toBe(200); + expect(body._id).toBe(userId); + }); + + }); + + describe("given the user profile does not exist", () => { + + it("should return 404 status", async () => { + // @ts-ignore + + + + const { body, statusCode } = await supertest(app).get( + `/api/user-profiles/${new mongoose.Types.ObjectId().toString()}` + ); + + expect(statusCode).toBe(404); + + }); + + }); + + }); + + describe("get user Profiles route", ()=> { + describe("given the user profiles exist", () => { + + it("should return 200 status and user profiles list", async () => { + // @ts-ignore + + + const { body, statusCode } = await supertest(app).get( + `/api/user-profiles/` + ); + + expect(statusCode).toBe(200); + expect(body.length).toBeGreaterThan(0) + }); + + }); + + + }); + + describe("update user Profile route", ()=> { + describe("given the user profile exist", () => { + + it("should return 200 status and user profiles list", async () => { + // @ts-ignore + + export const newUserProfile = { + + name: "new name", + bio: "Jane Doe", + phone: "+253762737263" + }; + const { statusCode } = await supertest(app).patch( + `/api/user-profiles/${userId}` + ).send(newUserProfile); + + const {body} = await supertest(app).get( + `/api/user-profiles/${userId}` + ); + + expect(statusCode).toBe(200); + expect(body.name).toBe(newUserProfile.name) + expect(body.bio).toBe(newUserProfile.bio) + expect(body.phone).toBe(newUserProfile.phone) + }); + + }); + + describe("given the user profile does not exist", () => { + + it("should return 400 status", async () => { + // @ts-ignore + + const newUserProfile = { + + name: "new name", + bio: "Jane Doe", + phone: "+253762737263" + }; + const fakeId = "dkfjds".toString(); + const { statusCode } = await supertest(app).patch( + `/api/user-profiles/${1}` + ).send(newUserProfile); + + + + expect(statusCode).toBe(400); + + }); + + }); + + + }); + + describe("delete user Profile route", ()=> { + describe("given the user profile exist", () => { + + it("should return 204 status", async () => { + // @ts-ignore + + const {statusCode} = await supertest(app).delete( + `/api/user-profiles/${userId}` + ); + + expect(statusCode).toBe(204); + + }); + + }); + + describe("given the user profile does not exist", () => { + + it("should return 204 status", async () => { + // @ts-ignore + + const {statusCode} = await supertest(app).delete( + `/api/user-profiles/${userId}` + ); + + expect(statusCode).toBe(204); + + }); + + }); + + + }); + + + }); \ No newline at end of file diff --git a/starter-project-backend-g31/src/tests/setupdb.ts b/starter-project-backend-g31/src/tests/setupdb.ts index e6fecdd..2adf092 100644 --- a/starter-project-backend-g31/src/tests/setupdb.ts +++ b/starter-project-backend-g31/src/tests/setupdb.ts @@ -1,34 +1,34 @@ -import { MongoMemoryServer } from "mongodb-memory-server"; - - -const mongoose = require("mongoose"); - -let mongoServer: { - [x: string]: any; getUri: () => any; stop: () => any -}; - -export const connect = async () => { - await mongoose.disconnect() - - mongoServer = await MongoMemoryServer.create(); - const URI = mongoServer.getUri(); - - mongoose.connect(URI, { - useNewUrlParser: true, - useCreateIndex: true, - useUnifiedTopology: true, - useFindAndModify: false, - }); -}; - -export const clear = async () => { - const collections = await mongoose.connection.db.collection; - for (let collection of collections) { - await collection.deleteMany({}); - } -}; - -export const disconnect = async () => { - mongoose.disconnect(); - await mongoServer.stop(); -}; +import { MongoMemoryServer } from "mongodb-memory-server"; + + +const mongoose = require("mongoose"); + +let mongoServer: { + [x: string]: any; getUri: () => any; stop: () => any +}; + +export const connect = async () => { + await mongoose.disconnect() + + mongoServer = await MongoMemoryServer.create(); + const URI = mongoServer.getUri(); + + mongoose.connect(URI, { + useNewUrlParser: true, + useCreateIndex: true, + useUnifiedTopology: true, + useFindAndModify: false, + }); +}; + +export const clear = async () => { + const collections = await mongoose.connection.db.collection; + for (let collection of collections) { + await collection.deleteMany({}); + } +}; + +export const disconnect = async () => { + mongoose.disconnect(); + await mongoServer.stop(); +};