Skip to content

Commit

Permalink
Merge pull request #73 from atlp-rwanda/ft-buyer-view-product-#54
Browse files Browse the repository at this point in the history
#54 Buyer should be able to get a single product
  • Loading branch information
Habinezajanvier authored May 20, 2024
2 parents f871225 + 12f82fd commit e270cb3
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 1 deletion.
75 changes: 75 additions & 0 deletions src/__test__/buyerController.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import request from 'supertest';
import app from '../app';
import {
afterAllHook,
beforeAllHook,
getBuyerToken,
getVendorToken,
} from './testSetup';
beforeAll(beforeAllHook);
afterAll(afterAllHook);

describe('Buyer Controller test', () => {
let buyerToken: string;
let vendorToken: string;
let productId: number;
let categoryId: number;

beforeAll(async () => {
buyerToken = await getBuyerToken();
vendorToken = await getVendorToken();
});

it('should get a product by id', async () => {
// create a category
const categoryData = {
name: 'Category4',
description: 'category description',
};

const categoryResponse = await request(app)
.post('/api/v1/category')
.set('Authorization', `Bearer ${vendorToken}`)
.send(categoryData);

categoryId = categoryResponse.body.data.id;

const productData = {
name: 'New Product Two',
image: 'new_product.jpg',
gallery: [],
shortDesc: 'This is a new product',
longDesc: 'Detailed description of the new product',
categoryId: categoryId,
quantity: 10,
regularPrice: 5,
salesPrice: 4,
tags: ['tag1', 'tag2'],
type: 'Simple',
isAvailable: true,
};

const response = await request(app)
.post('/api/v1/product')
.set('Authorization', `Bearer ${vendorToken}`)
.send(productData);

productId = response.body.data.id;

const getResponse = await request(app)
.get(`/api/v1/buyer/get_product/${productId}`)
.set('Authorization', `Bearer ${buyerToken}`);


expect(getResponse.statusCode).toEqual(200);
expect(getResponse.body.msg).toEqual('Product retrieved successfully');
});

it('should return a 404 if product is not found', async () => {
const response = await request(app)
.get('/api/v1/buyer/get_product/5')
.set('Authorization', `Bearer ${buyerToken}`);
expect(response.status).toBe(404);
expect(response.body.msg).toBe('Product not found');
});
});
37 changes: 37 additions & 0 deletions src/__test__/testSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,52 @@ export async function getVendorToken() {
return verifyResponse.body.token;
}

export const getBuyerToken = async () => {
const userRepository = await DbConnection.connection.getRepository(UserModel);
const formData = {
name: 'Buyer',
permissions: ['test-permission1', 'test-permission2'],
};
await request(app)
.post('/api/v1/roles/create_role')
.send(formData);

const userData = {
firstName: 'Tester',
lastName: 'Test',
email: 'test4@gmail.com',
password: 'TestPassword123',
userType: 'buyer',
};
await request(app).post('/api/v1/register').send(userData);

const updatedUser = await userRepository.findOne({
where: { email: userData.email },
});
if (updatedUser) {
updatedUser.isVerified = true;
await userRepository.save(updatedUser);
}

const loginResponse = await request(app).post('/api/v1/login').send({
email: userData.email,
password: userData.password,
});

return loginResponse.body.token;
};

export async function afterAllHook() {
await DbConnection.connection.transaction(async (transactionManager) => {
const userRepository = transactionManager.getRepository(UserModel);
const categoryRepository = transactionManager.getRepository(Category);
const productRepository = transactionManager.getRepository(Product);
const roleRepository = transactionManager.getRepository(Role);

await userRepository.createQueryBuilder().delete().execute();
await categoryRepository.createQueryBuilder().delete().execute();
await productRepository.createQueryBuilder().delete().execute();
await roleRepository.createQueryBuilder().delete().execute();
});
await DbConnection.instance.disconnectDb();
}
25 changes: 25 additions & 0 deletions src/controller/buyerController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Request, Response } from 'express';
import dbConnection from '../database';
import Product from '../database/models/productEntity';
import errorHandler from '../middlewares/errorHandler';

const productRepository = dbConnection.getRepository(Product);

export const getOneProduct = errorHandler(
async (req: Request, res: Response) => {
const productId = parseInt(req.params.id);

const product = await productRepository.findOne({
where: { id: productId },
relations: ['category'],
});

if (!product) {
return res.status(404).json({ msg: 'Product not found' });
}

return res
.status(200)
.json({ msg: 'Product retrieved successfully', product });
}
);
2 changes: 1 addition & 1 deletion src/database/models/productEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default class Product {
@Column({ default: true })
isAvailable: boolean;

@ManyToOne(() => UserModel)
@ManyToOne(() => UserModel, { onDelete: 'CASCADE' })
vendor: UserModel;

@CreateDateColumn()
Expand Down
22 changes: 22 additions & 0 deletions src/docs/buyerDocs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @swagger
* /api/v1/buyer/get_product/{id}:
* get:
* summary: Get a specific product
* tags: [Buyer]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* type: string
* required: true
* description: ID of the product to get
* responses:
* '200':
* description: Successful
* '404':
* description: Product not found
* '500':
* description: Internal Server Error
*/
15 changes: 15 additions & 0 deletions src/routes/buyerRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Router } from 'express';
import { checkRole } from '../middlewares/authorize';
import { getOneProduct } from '../controller/buyerController'
import { IsLoggedIn } from '../middlewares/isLoggedIn';

const buyerRouter = Router();

buyerRouter.get(
'/get_product/:id',
IsLoggedIn,
checkRole(['Buyer']),
getOneProduct
);

export default buyerRouter;
2 changes: 2 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import userRouter from './userRoutes';
import roleRoutes from './roleRoutes';
import productRoutes from './productRoutes';
import categoryRoutes from './categoryRoutes';
import buyerRoutes from './buyerRoutes';

const router = Router();

router.use('/user', userRouter);
router.use('/roles', roleRoutes);
router.use('/product', productRoutes);
router.use('/category', categoryRoutes);
router.use('/buyer', buyerRoutes);

export default router;

0 comments on commit e270cb3

Please sign in to comment.