-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45 from atlp-rwanda/ft-wishlist-#187419184
#187419184 A buyer should be able to wish a product
- Loading branch information
Showing
15 changed files
with
865 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,13 @@ const product:any = { | |
categoryID: 1, | ||
}; | ||
|
||
const dummyBuyer = { | ||
name: "test user", | ||
username: "testUser", | ||
email: "[email protected]", | ||
password: "soleil00", | ||
} | ||
|
||
|
||
describe("Testing product Routes", () => { | ||
beforeAll(async () => { | ||
|
@@ -76,7 +83,23 @@ describe("Testing product Routes", () => { | |
.send(userData); | ||
expect(response.status).toBe(201); | ||
}, 20000); | ||
|
||
|
||
test('should return 201 and register a dummy buyer user', async () => { | ||
const response = await request(app) | ||
.post("/api/v1/users/register") | ||
.send(dummyBuyer); | ||
expect(response.status).toBe(201); | ||
}) | ||
let buyerToken: any; | ||
|
||
test("should login an buyer", async () =>{ | ||
const response = await request(app).post("/api/v1/users/login").send({ | ||
email: "[email protected]", | ||
password: "soleil00" | ||
}) | ||
buyerToken = response.body.token; | ||
}); | ||
|
||
let token:any, adminToken:any; | ||
test('It should return status 401 for unthorized',async() =>{ | ||
const response = await request(app) | ||
|
@@ -227,6 +250,35 @@ test("should return all products in db --> given '/api/v1/products'", async () = | |
expect(response.status).toBe(201); | ||
},40000); | ||
|
||
test('It should add a product to the user wishes', async () => { | ||
const response = await request(app) | ||
.post('/api/v1/wishes') | ||
.send({ productId }) | ||
.set("Authorization", "Bearer " + buyerToken); | ||
expect(response.status).toBe(201) | ||
}, 20000); | ||
|
||
test('It should return a list of user wishes', async () => { | ||
const response = await request(app) | ||
.get('/api/v1/wishes') | ||
.set("Authorization", "Bearer " + buyerToken); | ||
expect(response.status).toBe(200) | ||
}); | ||
|
||
test('It should retrieve wishes on a single product', async () => { | ||
const response = await request(app) | ||
.get(`/api/v1/wishes/${productId}`) | ||
.set("Authorization", "Bearer " + token); | ||
expect(response.status).toBe(200) | ||
}) | ||
|
||
test('It should remove a product from user wishlist', async () => { | ||
const response = await request(app) | ||
.delete(`/api/v1/wishes/${productId}`) | ||
.set("Authorization", "Bearer " + buyerToken); | ||
expect(response.status).toBe(200) | ||
}) | ||
|
||
test('It should return status 200 for removed Product',async() =>{ | ||
const response = await request(app) | ||
.delete(`/api/v1/products/${productId}`) | ||
|
@@ -247,5 +299,6 @@ test('It should return status 200 for removed category',async() =>{ | |
.set("Authorization", "Bearer " + token); | ||
expect(response.status).toBe(200); | ||
},20000); | ||
|
||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import * as wishlistService from "../services/wishlist.service"; | ||
import { Request, Response } from "express"; | ||
import { wishSchema } from "../schemas/wishShema"; | ||
|
||
export const addToWishes = async (req: Request, res: Response) => { | ||
//@ts-ignore | ||
const id = req.user.id; | ||
try { | ||
const { error, value } = wishSchema.validate(req.body); | ||
if (error) { | ||
return res.status(400).json({ | ||
status: "Error", | ||
message: error.details[0].message, | ||
}); | ||
} | ||
const product = await wishlistService.getProduct(value.productId); | ||
if(!product){ | ||
return res.status(404).json({ | ||
message: 'product not found' | ||
}) | ||
} | ||
const isProdExisting = await wishlistService.getSingleWish(id, value.productId); | ||
if (isProdExisting) { | ||
return res.status(409).json({ | ||
message: "product already exists in your wishlist", | ||
}); | ||
} | ||
const wish = await wishlistService.addToWishlist(id, value.productId); | ||
if (wish) { | ||
return res.status(201).json({ | ||
message: "product was added to your wishlist", | ||
}); | ||
} | ||
} catch (err: any) { | ||
return res.status(500).json({ | ||
message: err.message, | ||
}); | ||
} | ||
}; | ||
|
||
export const getUserWishes = async (req: Request, res: Response) => { | ||
const { user } = req; | ||
try { | ||
//@ts-ignore | ||
const wishes = await wishlistService.getAllUserWishes(user.id); | ||
if (wishes.length == 0) { | ||
return res.status(200).json({ | ||
message: "No wishes found", | ||
}); | ||
} else { | ||
return res.status(200).json({ | ||
message: "wishes was retrieved successfully", | ||
wishes, | ||
}); | ||
} | ||
} catch (err: any) { | ||
return res.status(500).json({ | ||
message: err.message, | ||
}); | ||
} | ||
}; | ||
|
||
export const getProductWishes = async (req: Request, res: Response) => { | ||
const productId = req.params.id; | ||
try { | ||
//@ts-ignore | ||
const isOwner = await wishlistService.checkOwnership(Number(productId), req.user.id); | ||
if (!isOwner) { | ||
return res.status(403).json({ | ||
message: "you're not allowed to access this", | ||
}); | ||
} | ||
const wishes = await wishlistService.getProductWishes(Number(productId)); | ||
if (wishes.length === 0) { | ||
return res.status(200).json({ | ||
message: "no wishes were made on this product", | ||
}); | ||
} else { | ||
return res.status(200).json({ | ||
message: "success", | ||
wishes, | ||
}); | ||
} | ||
} catch (err: any) { | ||
return res.status(500).json({ | ||
message: err.message, | ||
}); | ||
} | ||
}; | ||
|
||
export const deleteWish = async (req: Request, res: Response) => { | ||
//@ts-ignore | ||
const id = req.user.id; | ||
const productId = Number(req.params.id); | ||
try { | ||
const isOwner = await wishlistService.getSingleWish(id, productId); | ||
if (!isOwner) { | ||
return res.status(404).json({ | ||
message: "wish product does not exist", | ||
}); | ||
} else { | ||
await wishlistService.removeProduct(id, productId); | ||
return res.status(200).json({ | ||
message: "product was removed from your wishes", | ||
}); | ||
} | ||
} catch (err: any) { | ||
return res.status(500).json({ | ||
message: err.message, | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
export const wishSchema = { | ||
type: 'object', | ||
properties: { | ||
productId: { | ||
type: 'number' | ||
}, | ||
userId: { | ||
type: 'number' | ||
} | ||
} | ||
} | ||
|
||
export const AddToWishes = { | ||
tags: ["Wishes"], | ||
security: [{ bearerAuth: [] }], | ||
summary: "Add a product to the wishlist", | ||
requestBody: { | ||
required: true, | ||
content: { | ||
"application/json": { | ||
schema: { | ||
type: "object", | ||
properties: { | ||
productId: { | ||
type: "number", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
responses: { | ||
201: { | ||
description: "Created", | ||
}, | ||
404: { description: "Not Found" | ||
}, | ||
|
||
}, | ||
} | ||
|
||
export const getWishes = { | ||
tags: ["Wishes"], | ||
security: [{ bearerAuth: [] }], | ||
summary: "Get all wished products", | ||
responses: { | ||
200: { | ||
description: "success", | ||
}, | ||
500: { | ||
description: "Internal Server Error" | ||
} | ||
}, | ||
} | ||
|
||
export const getWishesByProduct = { | ||
tags: ["Wishes"], | ||
security: [{ bearerAuth: [] }], | ||
summary: "Get all wishes on a single products", | ||
parameters: [ | ||
{ | ||
name: "id", | ||
in: "path", | ||
required: true, | ||
description: "Product Id", | ||
schema: { | ||
type: "number", | ||
}, | ||
}, | ||
], | ||
responses: { | ||
200: { | ||
description: "success", | ||
}, | ||
403: { | ||
description: "Forbidden" | ||
}, | ||
404: { | ||
description: "Not found" | ||
} | ||
}, | ||
} | ||
|
||
export const deleteWish = { | ||
tags: ["Wishes"], | ||
security: [{ bearerAuth: [] }], | ||
summary: "Remove a product from your wishlist", | ||
parameters: [ | ||
{ | ||
name: "id", | ||
in: "path", | ||
required: true, | ||
description: "Product Id", | ||
schema: { | ||
type: "number", | ||
}, | ||
}, | ||
], | ||
responses: { | ||
200: { | ||
description: "success", | ||
}, | ||
404: { | ||
description: "Not Found" | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Request,Response, NextFunction} from "express"; | ||
import { isLoggedIn } from "./isLoggedIn"; | ||
import { Role } from "../sequelize/models/roles"; | ||
|
||
export const isAbuyer = async(req:Request,res:Response,next:NextFunction) => { | ||
try { | ||
await isLoggedIn(req,res,() => {}); | ||
//@ts-ignore | ||
const roleId = req.user.roleId; | ||
const role = await Role.findByPk(roleId); | ||
if(role?.name === 'buyer'){ | ||
next(); | ||
}else{ | ||
res.status(403).json({message:"Forbidden: only buyers can perform this"}); | ||
} | ||
} catch (error:any) { | ||
console.error("Error:", error); | ||
res.status(500).json({ message: "Internal Server Error" }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import express from 'express' | ||
import * as wishesController from '../controllers/wishesController' | ||
import { isLoggedIn } from '../middlewares/isLoggedIn' | ||
import { isAseller } from '../middlewares/sellerAuth' | ||
import { isAbuyer } from '../middlewares/isAbuyer' | ||
|
||
const wishesRouter = express.Router() | ||
|
||
wishesRouter.post('/', isLoggedIn, isAbuyer, wishesController.addToWishes) | ||
wishesRouter.get('/', isLoggedIn, isAbuyer, wishesController.getUserWishes) | ||
wishesRouter.delete('/:id', isLoggedIn, isAbuyer, wishesController.deleteWish) | ||
wishesRouter.get('/:id', isLoggedIn, isAseller, wishesController.getProductWishes) | ||
|
||
export default wishesRouter |
Oops, something went wrong.