Skip to content

Commit

Permalink
Merge pull request #17 from zylcom/product-service
Browse files Browse the repository at this point in the history
update search api
  • Loading branch information
zylcom authored Aug 11, 2023
2 parents b10d63d + 6e51f22 commit f03c0cd
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 34 deletions.
85 changes: 73 additions & 12 deletions __test__/product.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ 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 supertest(web)
.get("/api/products/search")
.query({ page: 2 });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -73,8 +75,40 @@ describe("GET /api/products/search", function () {
expect(result.body.paging.hasNextPage).toBe(false);
});

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

console.log(result.body);

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(20);
expect(result.body.paging.page).toBe(1);
expect(result.body.paging.totalPage).toBe(1);
expect(result.body.paging.totalProducts).toBe(20);
expect(result.body.paging.hasNextPage).toBe(false);
});

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);

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(20);
expect(result.body.paging.page).toBe(1);
expect(result.body.paging.totalPage).toBe(1);
expect(result.body.paging.totalProducts).toBe(20);
expect(result.body.paging.hasNextPage).toBe(false);
});

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

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(15);
Expand All @@ -85,7 +119,9 @@ 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 supertest(web)
.get("/api/products/search")
.query({ name: "1" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -96,7 +132,9 @@ 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 supertest(web)
.get("/api/products/search")
.query({ category: "food" });

expect(result.status).toBe(200);
expect(result.body.data).toBeDefined();
Expand All @@ -107,7 +145,9 @@ 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 supertest(web)
.get("/api/products/search")
.query({ tag: "tag" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -118,7 +158,13 @@ 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({ category: "food", name: "pizza", page: 2, size: 15, tag: "tag" });
const result = await supertest(web).get("/api/products/search").query({
category: "food",
name: "pizza",
page: 2,
size: 15,
tag: "tag",
});

expect(result.status).toBe(200);
expect(result.body.data).toBeDefined();
Expand Down Expand Up @@ -150,7 +196,9 @@ 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 supertest(web)
.get("/api/products")
.query({ name: "5" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(2);
Expand All @@ -161,7 +209,9 @@ 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 supertest(web)
.get("/api/products")
.query({ tag: "tag" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -172,7 +222,9 @@ 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 supertest(web)
.get("/api/products")
.query({ category: "foo" });

expect(result.status).toBe(200);
expect(result.body.data).toBeDefined();
Expand All @@ -184,7 +236,9 @@ 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 result = await supertest(web)
.get("/api/products")
.query({ cursor: product.body.data.id });

expect(result.status).toBe(200);
expect(result.body.data.length).toBe(10);
Expand All @@ -196,7 +250,12 @@ 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({ name: "1", category: "foo", tag: "tag", cursor: product.body.data.id });
const result = await supertest(web).get("/api/products").query({
name: "1",
category: "foo",
tag: "tag",
cursor: product.body.data.id,
});

expect(result.status).toBe(200);
expect(result.body.data).toBeDefined();
Expand Down Expand Up @@ -224,7 +283,9 @@ describe("GET /api/products/best-rated", function () {
});

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 supertest(web)
.get("/api/products/best-rated")
.query({ category: "drink" });

expect(result.status).toBe(200);
expect(result.body.data.length).toBeLessThan(6);
Expand Down
33 changes: 29 additions & 4 deletions src/controllers/product-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ const get = async (req, res, next) => {
const slug = req.params.slug;
const result = await productService.get(slug);

res.status(200).set("Cache-Control", "public, max-age=120, s-maxage=1, stale-while-revalidate=30").json({ data: result });
res
.status(200)
.set(
"Cache-Control",
"public, max-age=120, s-maxage=1, stale-while-revalidate=30"
)
.json({ data: result });
} catch (error) {
next(error);
}
Expand All @@ -19,10 +25,17 @@ const search = async (req, res, next) => {
tag: req.query.tag,
size: req.query.size,
page: req.query.page,
getAll: req.query.getAll === "true" ? true : false,
};
const result = await productService.search(request);

res.status(200).set("Cache-Control", "public, max-age=0, s-maxage=1, stale-while-revalidate=30").json({ data: result.data, paging: result.paging });
res
.status(200)
.set(
"Cache-Control",
"public, max-age=0, s-maxage=1, stale-while-revalidate=30"
)
.json({ data: result.data, paging: result.paging });
} catch (error) {
next(error);
}
Expand All @@ -39,7 +52,13 @@ const infinite = async (req, res, next) => {
};
const result = await productService.infinite(request);

res.status(200).set("Cache-Control", "public, max-age=60, s-maxage=1, stale-while-revalidate=30").json({ data: result.data, paging: result.paging });
res
.status(200)
.set(
"Cache-Control",
"public, max-age=60, s-maxage=1, stale-while-revalidate=30"
)
.json({ data: result.data, paging: result.paging });
} catch (error) {
next(error);
}
Expand All @@ -51,7 +70,13 @@ const getBestRated = async (req, res, next) => {

const result = await productService.getBestRated(category);

res.status(200).set("Cache-Control", "public, max-age=0, s-maxage=1, stale-while-revalidate=30").json({ data: result });
res
.status(200)
.set(
"Cache-Control",
"public, max-age=0, s-maxage=1, stale-while-revalidate=30"
)
.json({ data: result });
} catch (error) {
next(error);
}
Expand Down
49 changes: 38 additions & 11 deletions src/services/product-service.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { prismaClient } from "../app/database.js";
import { ResponseError } from "../errors/response-error.js";
import { getBestRatedValidation, getProductValidation, infiniteValidation, searchProductValidation } from "../validation/product-validation.js";
import {
getBestRatedValidation,
getProductValidation,
infiniteValidation,
searchProductValidation,
} from "../validation/product-validation.js";
import validate from "../validation/validation.js";

const get = async (slug) => {
Expand All @@ -9,7 +14,17 @@ const get = async (slug) => {
const product = await prismaClient.product.findUnique({
where: { slug },
include: {
reviews: { include: { user: { select: { username: true, phonenumber: true, profile: { select: { name: true, avatar: true } } } } } },
reviews: {
include: {
user: {
select: {
username: true,
phonenumber: true,
profile: { select: { name: true, avatar: true } },
},
},
},
},
likes: true,
},
});
Expand All @@ -36,7 +51,9 @@ const search = async (request) => {
}

if (request.tag) {
filters.push({ tags: { some: { tag: { slug: { contains: request.tag } } } } });
filters.push({
tags: { some: { tag: { slug: { contains: request.tag } } } },
});
}

const products = await prismaClient.product.findMany({
Expand All @@ -48,21 +65,27 @@ const search = async (request) => {
tags: { select: { tag: { select: { name: true, slug: true } } } },
likes: true,
},
take: request.size,
take: request.getAll ? undefined : request.size,
skip,
});

const totalItems = await prismaClient.product.count({ where: { AND: filters } });
const hasNextPage = await prismaClient.product.count({ where: { AND: filters }, skip: skip + request.size }).then((result) => {
return result > 0;
const totalItems = await prismaClient.product.count({
where: { AND: filters },
});
const hasNextPage = await prismaClient.product
.count({ where: { AND: filters }, skip: skip + request.size })
.then((result) => {
return result > 0 && !request.getAll;
});

const divider = request.getAll ? totalItems : request.size;

return {
data: products,
paging: {
page: request.page,
totalProducts: totalItems,
totalPage: Math.ceil(totalItems / request.size),
totalPage: Math.ceil(totalItems / divider),
hasNextPage,
},
};
Expand Down Expand Up @@ -119,11 +142,11 @@ const infinite = async (request) => {

return {
data: products,
paging: {
paging: {
nextCursor,
totalProducts: totalItems,
totalPage: Math.ceil(totalItems / request.size),
hasNextPage
hasNextPage,
},
};
};
Expand All @@ -132,7 +155,11 @@ const getBestRated = async (category) => {
category = validate(getBestRatedValidation, category);

return await prismaClient.product
.findMany({ where: { category: { slug: { contains: category } } }, orderBy: { averageRating: "desc" }, include: { likes: true } })
.findMany({
where: { category: { slug: { contains: category } } },
orderBy: { averageRating: "desc" },
include: { likes: true },
})
.then((result) => result.slice(0, 5));
};

Expand Down
Loading

0 comments on commit f03c0cd

Please sign in to comment.