feat: /store api product types (#2552)
## What Allow users to fetch ProductTypes from the storefront API. ## Why This endpoint will allow developers to implement better faceted product search in Medusa without the need for search plugin. Developers will be able to use this to render refinement lists based on types, like this:  ## How Endpoint `GET /store/products/types` and `GET /store/product-types` (use [product types listing in admin](https://github.com/medusajs/medusa/blob/master/packages/medusa/src/api/routes/admin/products/list-types.ts) as reference) Support added in @medusajs/medusa-js Support added in medusa-react ## Testing Similar automated tests as `GET /admin/products/types` and `GET /admin/product-types` --- Resolves CORE-699
This commit is contained in:
@@ -55,11 +55,7 @@ describe("/admin/product-types", () => {
|
||||
it("returns a list of product types", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api
|
||||
.get("/admin/product-types", adminReqConfig)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
const res = await api.get("/admin/product-types", adminReqConfig)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
|
||||
@@ -74,11 +70,10 @@ describe("/admin/product-types", () => {
|
||||
it("returns a list of product types matching free text search param", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api
|
||||
.get("/admin/product-types?q=test-type-new", adminReqConfig)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
const res = await api.get(
|
||||
"/admin/product-types?q=test-type-new",
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`/store/product-types GET /store/product-types returns a list of product types 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"id": "test-type-new",
|
||||
"updated_at": Any<String>,
|
||||
"value": "test-type-new",
|
||||
},
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"value": "test-type",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`/store/product-types GET /store/product-types returns a list of product types matching free text search param 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"id": "test-type-new",
|
||||
"updated_at": Any<String>,
|
||||
"value": "test-type-new",
|
||||
},
|
||||
]
|
||||
`;
|
||||
154
integration-tests/api/__tests__/store/product-type.js
Normal file
154
integration-tests/api/__tests__/store/product-type.js
Normal file
@@ -0,0 +1,154 @@
|
||||
const path = require("path")
|
||||
|
||||
const { IdMap } = require("medusa-test-utils")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const productSeeder = require("../../helpers/product-seeder")
|
||||
const {
|
||||
DiscountRuleType,
|
||||
AllocationType,
|
||||
DiscountConditionType,
|
||||
DiscountConditionOperator,
|
||||
} = require("@medusajs/medusa")
|
||||
const { simpleDiscountFactory } = require("../../factories")
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
describe("/store/product-types", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /store/product-types", () => {
|
||||
beforeEach(async () => {
|
||||
await productSeeder(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("returns a list of product types", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api.get("/store/product-types")
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
|
||||
const typeMatch = {
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}
|
||||
|
||||
expect(res.data.product_types).toMatchSnapshot([typeMatch, typeMatch])
|
||||
})
|
||||
|
||||
it("returns a list of product types matching free text search param", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api.get("/store/product-types?q=test-type-new")
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
|
||||
const typeMatch = {
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
}
|
||||
|
||||
// The value of the type should match the search param
|
||||
expect(res.data.product_types.map((pt) => pt.value)).toEqual([
|
||||
"test-type-new",
|
||||
])
|
||||
|
||||
// Should only return one type as there is only one match to the search param
|
||||
expect(res.data.product_types).toMatchSnapshot([typeMatch])
|
||||
})
|
||||
|
||||
it("returns a list of product type filtered by discount condition id", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const resTypes = await api.get("/store/product-types")
|
||||
|
||||
const type1 = resTypes.data.product_types[0]
|
||||
const type2 = resTypes.data.product_types[1]
|
||||
|
||||
const buildDiscountData = (code, conditionId, types) => {
|
||||
return {
|
||||
code,
|
||||
rule: {
|
||||
type: DiscountRuleType.PERCENTAGE,
|
||||
value: 10,
|
||||
allocation: AllocationType.TOTAL,
|
||||
conditions: [
|
||||
{
|
||||
id: conditionId,
|
||||
type: DiscountConditionType.PRODUCT_TYPES,
|
||||
operator: DiscountConditionOperator.IN,
|
||||
product_types: types,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const discountConditionId = IdMap.getId("discount-condition-type-1")
|
||||
await simpleDiscountFactory(
|
||||
dbConnection,
|
||||
buildDiscountData("code-1", discountConditionId, [type1.id])
|
||||
)
|
||||
|
||||
const discountConditionId2 = IdMap.getId("discount-condition-type-2")
|
||||
await simpleDiscountFactory(
|
||||
dbConnection,
|
||||
buildDiscountData("code-2", discountConditionId2, [type2.id])
|
||||
)
|
||||
|
||||
let res = await api.get(
|
||||
`/store/product-types?discount_condition_id=${discountConditionId}`
|
||||
)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.product_types).toHaveLength(1)
|
||||
expect(res.data.product_types).toEqual(
|
||||
expect.arrayContaining([expect.objectContaining({ id: type1.id })])
|
||||
)
|
||||
|
||||
res = await api.get(
|
||||
`/store/product-types?discount_condition_id=${discountConditionId2}`
|
||||
)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.product_types).toHaveLength(1)
|
||||
expect(res.data.product_types).toEqual(
|
||||
expect.arrayContaining([expect.objectContaining({ id: type2.id })])
|
||||
)
|
||||
|
||||
res = await api.get(`/store/product-types`)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.product_types).toHaveLength(2)
|
||||
expect(res.data.product_types).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: type1.id }),
|
||||
expect.objectContaining({ id: type2.id }),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user