Skip to content

Commit

Permalink
Merge pull request #18 from zylcom/product-service
Browse files Browse the repository at this point in the history
feat: add update product api
  • Loading branch information
zylcom authored Aug 15, 2023
2 parents f03c0cd + 4b8cfec commit 97cee82
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 105 deletions.
128 changes: 77 additions & 51 deletions __test__/product.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import supertest from "supertest";
import { web } from "../src/app/web";
import {
createTestUser,
createTestProduct,
Expand All @@ -10,7 +8,9 @@ import {
productSlug,
removeTestProduct,
removeTestUser,
token,
} from "./test-util";
import { request } from "./setup";

describe("GET /api/products/:slug", function () {
beforeEach(async () => {
Expand All @@ -22,7 +22,7 @@ describe("GET /api/products/:slug", function () {
});

it("should can get product", async () => {
const result = await supertest(web).get(`/api/products/${productSlug}`);
const result = await request.get(`/api/products/${productSlug}`);

expect(result.status).toBe(200);
expect(result.body.data.name).toBe(productName);
Expand All @@ -34,7 +34,7 @@ describe("GET /api/products/:slug", function () {
});

it("should reject if slug is invalid", async () => {
const result = await supertest(web).get("/api/products/invalid-slug");
const result = await request.get("/api/products/invalid-slug");

expect(result.status).toBe(404);
expect(result.body.data).toBeUndefined();
Expand All @@ -52,7 +52,7 @@ describe("GET /api/products/search", function () {
});

it("should can search products without parameters", async () => {
const result = await supertest(web).get("/api/products/search");
const result = await request.get("/api/products/search");

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -63,9 +63,7 @@ describe("GET /api/products/search", function () {
});

it("should can search to page 2", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ page: 2 });
const result = await request.get("/api/products/search").query({ page: 2 });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -76,11 +74,7 @@ describe("GET /api/products/search", function () {
});

it("should can get all products", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ getAll: true });

console.log(result.body);
const result = await request.get("/api/products/search").query({ getAll: true });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(20);
Expand All @@ -91,11 +85,7 @@ describe("GET /api/products/search", function () {
});

it("should can get all products even with size query", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ getAll: true });

console.log(result.body);
const result = await request.get("/api/products/search").query({ getAll: true });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(20);
Expand All @@ -106,9 +96,7 @@ describe("GET /api/products/search", function () {
});

it("should can search with size 15", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ size: 15 });
const result = await request.get("/api/products/search").query({ size: 15 });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(15);
Expand All @@ -119,9 +107,7 @@ describe("GET /api/products/search", function () {
});

it("should can search using name", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ name: "1" });
const result = await request.get("/api/products/search").query({ name: "1" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -132,9 +118,7 @@ describe("GET /api/products/search", function () {
});

it("should can search using category", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ category: "food" });
const result = await request.get("/api/products/search").query({ category: "food" });

expect(result.status).toBe(200);
expect(result.body.data).toBeDefined();
Expand All @@ -145,9 +129,7 @@ describe("GET /api/products/search", function () {
});

it("should can search using tag", async () => {
const result = await supertest(web)
.get("/api/products/search")
.query({ tag: "tag" });
const result = await request.get("/api/products/search").query({ tag: "tag" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -158,7 +140,7 @@ describe("GET /api/products/search", function () {
});

it("should can search using tag, name, category, size, page", async () => {
const result = await supertest(web).get("/api/products/search").query({
const result = await request.get("/api/products/search").query({
category: "food",
name: "pizza",
page: 2,
Expand All @@ -185,7 +167,7 @@ describe("GET /api/products", function () {
});

it("should can get products", async () => {
const result = await supertest(web).get("/api/products").query();
const result = await request.get("/api/products").query();

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -196,9 +178,7 @@ describe("GET /api/products", function () {
});

it("should can get products using name", async () => {
const result = await supertest(web)
.get("/api/products")
.query({ name: "5" });
const result = await request.get("/api/products").query({ name: "5" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(2);
Expand All @@ -209,9 +189,7 @@ describe("GET /api/products", function () {
});

it("should can get products using tag", async () => {
const result = await supertest(web)
.get("/api/products")
.query({ tag: "tag" });
const result = await request.get("/api/products").query({ tag: "tag" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -222,9 +200,7 @@ describe("GET /api/products", function () {
});

it("should can get products using category", async () => {
const result = await supertest(web)
.get("/api/products")
.query({ category: "foo" });
const result = await request.get("/api/products").query({ category: "foo" });

expect(result.status).toBe(200);
expect(result.body.data).toBeDefined();
Expand All @@ -235,10 +211,8 @@ describe("GET /api/products", function () {
});

it("should can get products using cursor", async () => {
const product = await supertest(web).get("/api/products/pizza-5");
const result = await supertest(web)
.get("/api/products")
.query({ cursor: product.body.data.id });
const product = await request.get("/api/products/pizza-5");
const result = await request.get("/api/products").query({ cursor: product.body.data.id });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -249,8 +223,8 @@ describe("GET /api/products", function () {
});

it("should can get products using cursor, name, category and tag", async () => {
const product = await supertest(web).get("/api/products/pizza-1");
const result = await supertest(web).get("/api/products").query({
const product = await request.get("/api/products/pizza-1");
const result = await request.get("/api/products").query({
name: "1",
category: "foo",
tag: "tag",
Expand All @@ -276,18 +250,70 @@ describe("GET /api/products/best-rated", function () {
});

it("should can get best rated products", async () => {
const result = await supertest(web).get("/api/products/best-rated");
const result = await request.get("/api/products/best-rated");

expect(result.status).toBe(200);
expect(result.body.data.length).toBeLessThan(6);
});

it("should can get best rated products with category drink", async () => {
const result = await supertest(web)
.get("/api/products/best-rated")
.query({ category: "drink" });
const result = await request.get("/api/products/best-rated").query({ category: "drink" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBeLessThan(6);
});
});

describe("PUT /api/products", function () {
beforeEach(async () => {
await createTestUser();
});

afterEach(async () => {
await removeTestUser();
});

it("should can update product", async () => {
const product = await request.get("/api/products/pizza-1");

const tags = [1, 2, 3].filter((id) => id !== product.body.data.tags[0].tagId);
const categorySlug = product.body.data.categorySlug === "food" ? "drink" : "food";
const result = await request
.put("/api/products")
.send({
name: "Updated Product",
description: "Updated",
slug: product.body.data.slug,
ingredients: "Updated",
categorySlug,
price: 1,
tags,
})
.set("Authorization", token);

expect(result.status).toBe(200);
expect(result.body.data.name).toBe("Updated Product");
expect(result.body.data.categorySlug).toBe(categorySlug);
expect(result.body.data.description).toBe("Updated");
expect(result.body.data.ingredients).toBe("Updated");
expect(result.body.data.price).toBe(1);
expect(result.body.data.tags.length).toBe(tags.length);
});

it("should reject if token is invalid", async () => {
const product = await request.get("/api/products/pizza-1");
const result = await request.put("/api/products").send({
name: "Updated Product",
description: "Updated",
slug: product.body.data.slug,
ingredients: "Updated",
categorySlug: product.body.data.categorySlug,
price: 1,
tags: [1, 2, 3],
});

expect(result.status).toBe(401);
expect(result.body.data).toBeUndefined();
expect(result.body.errors).toBeDefined();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ CREATE TABLE `tags` (

-- CreateTable
CREATE TABLE `tags_on_products` (
`productId` INTEGER NOT NULL,
`id` INTEGER NOT NULL AUTO_INCREMENT,
`productId` INTEGER NULL,
`tagId` INTEGER NOT NULL,
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),

INDEX `tags_on_products_productId_idx`(`productId`),
INDEX `tags_on_products_tagId_idx`(`tagId`),
PRIMARY KEY (`productId`, `tagId`)
UNIQUE INDEX `tags_on_products_productId_tagId_key`(`productId`, `tagId`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
Expand Down
7 changes: 4 additions & 3 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,14 @@ model Tag {
}

model TagOnProduct {
product Product @relation(fields: [productId], references: [id])
productId Int
id Int @id() @default(autoincrement())
product Product? @relation(fields: [productId], references: [id])
productId Int?
tag Tag @relation(fields: [tagId], references: [id])
tagId Int
createdAt DateTime @default(now())
@@id([productId, tagId])
@@unique([productId, tagId])
@@index([productId])
@@index([tagId])
@@map("tags_on_products")
Expand Down
16 changes: 15 additions & 1 deletion src/controllers/product-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,18 @@ const getBestRated = async (req, res, next) => {
}
};

export default { get, search, infinite, getBestRated };
const update = async (req, res, next) => {
try {
const request = {
...req.body,
};

const result = await productService.update(request);

res.status(200).json({ data: result });
} catch (error) {
next(error);
}
};

export default { get, search, infinite, getBestRated, update };
20 changes: 16 additions & 4 deletions src/routes/api.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import express from "express";
import cartController from "../controllers/cart-controller.js";
import userController from "../controllers/user-controller.js";
import { authMiddleware } from "../middleware/auth-middleware.js";
import cartItemController from "../controllers/cart-item-controller.js";
import reviewController from "../controllers/review-controller.js";
import likeProductController from "../controllers/like-product-controller.js";
import orderController from "../controllers/order-controller.js";
import productController from "../controllers/product-controller.js";
import { authMiddleware } from "../middleware/auth-middleware.js";

const userRouter = new express.Router();

Expand All @@ -17,19 +18,30 @@ userRouter.delete("/api/users/logout", userController.logout);
userRouter.get("/api/users/current/carts", cartController.get);

userRouter.get("/api/users/current/carts/items", cartItemController.get);
userRouter.get("/api/users/current/carts/items/:productSlug", cartItemController.find);
userRouter.get(
"/api/users/current/carts/items/:productSlug",
cartItemController.find
);
userRouter.put("/api/users/current/carts/items", cartItemController.upsert);
userRouter.delete("/api/users/current/carts/items/:itemId", cartItemController.remove);
userRouter.delete(
"/api/users/current/carts/items/:itemId",
cartItemController.remove
);

userRouter.post("/api/products/reviews", reviewController.create);
userRouter.put("/api/products/reviews", reviewController.update);

userRouter.post("/api/products/:productSlug/like", likeProductController.like);
userRouter.delete("/api/products/:productSlug/like", likeProductController.neutral);
userRouter.delete(
"/api/products/:productSlug/like",
likeProductController.neutral
);

userRouter.post("/api/orders", orderController.create);
userRouter.get("/api/orders/:orderId", orderController.get);
userRouter.post("/api/orders/checkout", orderController.checkout);
userRouter.post("/api/orders/:orderId/cancel", orderController.cancel);

userRouter.put("/api/products", productController.update);

export { userRouter };
Loading

0 comments on commit 97cee82

Please sign in to comment.