fix(medusa): category list api bug where limit skews results (#3914)

* chore: fix category list api bug where limit skews results

* chore: add limits to integration test
This commit is contained in:
Riqwan Thamir authored and GitHub committed 2023-04-24 19:16:58 +02:00
1 parent 88a224e42a
commit 935abeae68
4 files changed
+60 -40

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
fix(medusa): fix category list api bug where limit skews results
@@ -179,14 +179,14 @@ describe("/admin/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/admin/product-categories`, `/admin/product-categories?limit=7`,
adminHeaders adminHeaders
) )
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
expect(response.data.count).toEqual(7) expect(response.data.count).toEqual(7)
expect(response.data.offset).toEqual(0) expect(response.data.offset).toEqual(0)
expect(response.data.limit).toEqual(100) expect(response.data.limit).toEqual(7)
expect(response.data.product_categories).toEqual( expect(response.data.product_categories).toEqual(
[ [
@@ -296,7 +296,7 @@ describe("/admin/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/admin/product-categories?is_internal=true`, `/admin/product-categories?is_internal=true&limit=7`,
adminHeaders, adminHeaders,
) )
@@ -309,7 +309,7 @@ describe("/admin/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/admin/product-categories?handle=${productCategory.handle}`, `/admin/product-categories?handle=${productCategory.handle}&limit=2`,
adminHeaders, adminHeaders,
) )
@@ -322,7 +322,7 @@ describe("/admin/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/admin/product-categories?q=men`, `/admin/product-categories?q=men&limit=1`,
adminHeaders, adminHeaders,
) )
@@ -335,7 +335,7 @@ describe("/admin/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/admin/product-categories?parent_category_id=${productCategoryParent.id}`, `/admin/product-categories?parent_category_id=${productCategoryParent.id}&limit=7`,
adminHeaders, adminHeaders,
) )
@@ -357,7 +357,7 @@ describe("/admin/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/admin/product-categories?parent_category_id=null&include_descendants_tree=true`, `/admin/product-categories?parent_category_id=null&include_descendants_tree=true&limit=7`,
adminHeaders adminHeaders
) )
@@ -178,13 +178,13 @@ describe("/store/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/store/product-categories`, `/store/product-categories?limit=10`,
) )
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
expect(response.data.count).toEqual(4) expect(response.data.count).toEqual(4)
expect(response.data.offset).toEqual(0) expect(response.data.offset).toEqual(0)
expect(response.data.limit).toEqual(100) expect(response.data.limit).toEqual(10)
expect(response.data.product_categories).toEqual( expect(response.data.product_categories).toEqual(
[ [
@@ -239,7 +239,7 @@ describe("/store/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/store/product-categories?parent_category_id=null&include_descendants_tree=true`, `/store/product-categories?parent_category_id=null&include_descendants_tree=true&limit=10`,
) )
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
@@ -280,7 +280,7 @@ describe("/store/product-categories", () => {
const api = useApi() const api = useApi()
const error = await api.get( const error = await api.get(
`/store/product-categories?is_internal=true`, `/store/product-categories?is_internal=true&limit=10`,
).catch(e => e) ).catch(e => e)
expect(error.response.status).toEqual(400) expect(error.response.status).toEqual(400)
@@ -292,7 +292,7 @@ describe("/store/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/store/product-categories?q=category-parent`, `/store/product-categories?q=category-parent&limit=10`,
) )
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
@@ -304,7 +304,7 @@ describe("/store/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/store/product-categories?handle=${productCategory.handle}`, `/store/product-categories?handle=${productCategory.handle}&limit=10`,
) )
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
@@ -316,7 +316,7 @@ describe("/store/product-categories", () => {
const api = useApi() const api = useApi()
const response = await api.get( const response = await api.get(
`/store/product-categories?parent_category_id=${productCategory.id}`, `/store/product-categories?parent_category_id=${productCategory.id}&limit=10`,
) )
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
@@ -51,7 +51,9 @@ export const ProductCategoryRepository = dataSource
const modelColumns = this.metadata.ownColumns.map( const modelColumns = this.metadata.ownColumns.map(
(column) => column.propertyName (column) => column.propertyName
) )
const selectColumns = columnsSelected.length ? columnsSelected : modelColumns const selectColumns = columnsSelected.length
? columnsSelected
: modelColumns
return selectColumns.map((column) => { return selectColumns.map((column) => {
return `${relationName}.${column}` return `${relationName}.${column}`
@@ -69,13 +71,16 @@ export const ProductCategoryRepository = dataSource
delete options_.where?.name delete options_.where?.name
delete options_.where?.handle delete options_.where?.handle
options_.where = [{ options_.where = [
...options_.where, {
name: ILike(`%${q}%`) ...options_.where,
}, { name: ILike(`%${q}%`),
...options_.where, },
handle: ILike(`%${q}%`) {
}] ...options_.where,
handle: ILike(`%${q}%`),
},
]
} }
queryBuilder.where(options_.where) queryBuilder.where(options_.where)
@@ -97,8 +102,6 @@ export const ProductCategoryRepository = dataSource
treeScope treeScope
) )
.addSelect(fetchSelectColumns(treeRelation)) .addSelect(fetchSelectColumns(treeRelation))
.addOrderBy(`${treeRelation}.rank`, "ASC")
.addOrderBy(`${treeRelation}.handle`, "ASC")
}) })
const nonTreeRelations: string[] = relationsSelected.filter( const nonTreeRelations: string[] = relationsSelected.filter(
@@ -111,15 +114,15 @@ export const ProductCategoryRepository = dataSource
let [categories, count] = await queryBuilder.getManyAndCount() let [categories, count] = await queryBuilder.getManyAndCount()
if (includeTree) { categories = await Promise.all(
categories = await Promise.all( categories.map(async (productCategory) => {
categories.map(async (productCategory) => { if (includeTree) {
productCategory = await this.findDescendantsTree(productCategory) productCategory = await this.findDescendantsTree(productCategory)
}
return sortChildren(productCategory, treeScope) return sortChildren(productCategory, treeScope)
}) })
) )
}
return [categories, count] return [categories, count]
}, },
@@ -166,13 +169,15 @@ const scopeChildren = (
return category return category
} }
category.category_children = category.category_children.filter( if (category.category_children) {
(categoryChild) => { category.category_children = category.category_children.filter(
return !Object.entries(treeScope).some( (categoryChild) => {
([attribute, value]) => categoryChild[attribute] !== value return !Object.entries(treeScope).some(
) ([attribute, value]) => categoryChild[attribute] !== value
} )
) }
)
}
return category return category
} }
@@ -182,13 +187,23 @@ const sortChildren = (
treeScope: QuerySelector<ProductCategory> = {} treeScope: QuerySelector<ProductCategory> = {}
): ProductCategory => { ): ProductCategory => {
if (category.category_children) { if (category.category_children) {
category.category_children = category?.category_children category.category_children = category.category_children
.map( .map(
// Before we sort the children, we need scope the children // Before we sort the children, we need scope the children
// to conform to treeScope conditions // to conform to treeScope conditions
(child) => sortChildren(scopeChildren(child, treeScope), treeScope) (child) => sortChildren(scopeChildren(child, treeScope), treeScope)
) )
.sort((a, b) => a.rank - b.rank) .sort((a, b) => {
// Sort by rank first
const rankDiff = a.rank - b.rank
// If the ranks are the same, sort by handle in ascending order
if (rankDiff === 0) {
return a.handle.localeCompare(b.handle)
}
return rankDiff
})
} }
return category return category