diff --git a/src/controllers/ProductController.ts b/src/controllers/ProductController.ts index 40636bef..567ad3d0 100644 --- a/src/controllers/ProductController.ts +++ b/src/controllers/ProductController.ts @@ -168,7 +168,7 @@ export class ProductController { * @swagger * /api/v1/products/{product_id}: * get: - * summary: Fetch a product by {id} + * summary: Fetch a product by its ID * tags: [Product] * parameters: * - in: path @@ -176,17 +176,17 @@ export class ProductController { * required: true * schema: * type: integer - * description: String ID of the product + * description: The ID of the product to fetch * responses: * 200: - * description: Successful response + * description: Product retrieved successfully * content: * application/json: * schema: * type: object * properties: * id: - * type: string + * type: integer * example: 123 * name: * type: string @@ -196,30 +196,42 @@ export class ProductController { * example: Product is robust * price: * type: number - * exanple: 19 + * example: 19 * category: * type: string * example: Gadgets * 400: - * description: Bad request + * description: Bad request due to invalid product ID * content: * application/json: * schema: * type: object * properties: - * error: + * status: + * type: string + * example: Bad Request + * message: * type: string - * example: Invalid product ID + * example: Invalid Product Id + * status_code: + * type: integer + * example: 400 * 404: - * description: Not found + * description: Product not found * content: * application/json: * schema: * type: object * properties: - * error: + * status: + * type: string + * example: Not Found + * message: * type: string * example: Product not found + * status_code: + * type: integer + * example: 404 * 500: * description: Internal server error * content: @@ -227,11 +239,49 @@ export class ProductController { * schema: * type: object * properties: - * error: + * status: * type: string * example: An unexpected error occurred + * message: + * type: string + * example: Internal server error + * status_code: + * type: integer + * example: 500 */ - async fetchProductById(req: Request, res: Response) {} + + async fetchProductById(req: Request, res: Response) { + + const productId = req.params.product_id; + + if(isNaN(Number(productId))){ + return res.status(400).json({ + status: "Bad Request", + message: "Invalid Product Id", + status_code: 400, + }) + } + + try { + const product = await this.productService.getOneProduct(productId) + if (!product) { + return res.status(404).json({ + status: "Not found", + message: "Product not found", + status_code: 404, + }); + + } + return res.status(200).json(product); + } catch (error) { + return res.status(500).json({ + status: "An unexpected error occurred", + message: "Internal server error", + status_code: 500, + }); + } + + } /** * @swagger @@ -515,7 +565,10 @@ export class ProductController { * type: string * example: Product not found */ - async deleteProduct(req: Request, res: Response) {} + async deleteProduct(req: Request, res: Response) { + + + } } export default ProductController; diff --git a/src/services/product.services.ts b/src/services/product.services.ts index 14c34d74..879ba370 100644 --- a/src/services/product.services.ts +++ b/src/services/product.services.ts @@ -55,4 +55,13 @@ export class ProductService { throw new Error(err.message); } } + async getOneProduct(id: string): Promise { + + const product = await this.productRepository.findOneBy({id}); + + return product; + + + } + } diff --git a/src/test/product.spec.ts b/src/test/product.spec.ts new file mode 100644 index 00000000..bf5d5741 --- /dev/null +++ b/src/test/product.spec.ts @@ -0,0 +1,84 @@ +import { Repository } from "typeorm"; +import AppDataSource from "../data-source"; +import { Product } from "../models/product"; +import { User } from "../models"; +import { ProductService } from "../services"; +import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; + +jest.mock("../data-source", () => ({ + __esModule: true, + default: { + getRepository: jest.fn(), + initialize: jest.fn(), + isInitialized: false, + }, +})); + +describe("ProductService", () => { + let productService: ProductService; + let mockRepository: jest.Mocked>; + + beforeEach(() => { + mockRepository = { + findOneBy: jest.fn(), + // Add other methods if needed + } as any; + + (AppDataSource.getRepository as jest.Mock).mockReturnValue(mockRepository); + + productService = new ProductService(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + describe("fetchProductById", () => { + it("should return the product if it exists", async () => { + const productId = "123"; + const user: User = { + id: 'user-123', + name: 'John Doe', + // Add any other necessary properties + } as User; + const product = { + id: "123", + name: "Product 1", + description: "Product is robust", + price: 19, + category: "Gadgets", + user:user + + } as Product; + + mockRepository.findOneBy.mockResolvedValue(product); + + const result = await productService.getOneProduct(productId); + expect(result).toEqual(product); + expect(mockRepository.findOneBy).toHaveBeenCalledWith({ id: productId }); + }); + + it("should return null if the product does not exist", async () => { + const productId = "non-existing-id"; + + mockRepository.findOneBy.mockResolvedValue(null); + + const result = await productService.getOneProduct(productId); + + expect(result).toBeNull(); + expect(mockRepository.findOneBy).toHaveBeenCalledWith({ id: productId }); + }); + + it("should throw an error if there is an issue with fetching the product", async () => { + const productId = "123"; + const error = new Error("Error fetching product"); + + mockRepository.findOneBy.mockRejectedValue(error); + + await expect(productService.getOneProduct(productId)).rejects.toThrow( + "Error fetching product", + ); + expect(mockRepository.findOneBy).toHaveBeenCalledWith({ id: productId }); + }); + }); +});