feat(product, types, utils): tags, types, options, categories and collections for product module (#4535)
* Feat: create product with product module * feat: create product wip * feat: create product wip * feat: update product relation and generate image migration * lint * conitnue implementation * continue implementation and add integration tests for produceService.create * Add integration tests for product creation at the module level for the complete flow * only use persist since write operations are always wrapped in a transaction which will be committed and flushed * simplify the transaction wrapper to make future changes easier * feat: move some utils to the utils package to simplify its usage * tests: fix unit tests * feat: create variants along side the product * Add more integration tests an update migrations * chore: Update actions workflow to include packages integration tests * small types and utils cleanup * chore: Add support for database debug option * chore: Add missing types in package.json from types and util, validate that all the models are sync with medusa * expose retrieve method * fix types issues * fix unit tests and move integration tests workflow with the plugins integration tests * chore: remove migration function export from the definition to prevent them to be ran by the medusa cli just in case * fix package.json script * chore: workflows * feat: start creating the create product workflow * feat: add empty step for prices and sales channel * tests: update scripts and action envs * fix imports * feat: Add proper soft deleted support + add product deletion service public api * chore: update migrations * chore: update migrations * chore: update todo * feat: Add product deletion to the create-product workflow as compensation * chore: cleanup product utils * feat: Add support for cascade soft-remove * feat: refactor repository to take into account withDeleted * fix integration tests * Add support for force delete -> delete, cleanup repositories and improvements * Add support for restoring a product and add integration tests * cleaup + tests * types * fix integration tests * remove unnecessary comments * move specific mikro orm usage to the DAL * Cleanup workflow functions * Make deleted_at optional at the property level and add url index for the images * address feedback + cleanup * fix export * merge migrations into one * feat(product, types): added missing product variant methods (#4475) * chore: added missing product variant methods * chore: address PR feedback * chore: catch undefined case for retrieve + specs for variant service * chore: align TEntity + add changeset * chore: revert changeset, TEntity to ProductVariant * chore: write tests for pagination, unskip the test * Create chilled-mice-deliver.md * update integration fixtuers * update pipeline node version * rename github action * fix pipeline * feat(medusa, types): added missing category tests and service methods (#4499) * chore: added missing category tests and service methods * chore: added type changes to module service * chore: address pr feedback * update repositories manager usage and serialisation from the write public API * move serializisation to the DAL * rename template args * chore: added collection methods for module and collection service (#4505) * chore: added collection methods for module and collection service * Create fresh-islands-teach.md * chore: move retrieve entity to utils package * chore: make products optional in DTO type --------- Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> * feat(product): Apply transaction decorators to the services (#4512) * chore: added tags and types methods for product module * chore: remove console log * chore: fork managers on every repository call * chore: add forked manager decorator * chore: rename to inject manager from inject forked manager * chore: added product tag and type create/update/delete * chore: added collection create/update/delete * chore: fix naming * update injectManager and related behaviour * simplify get active manager * chore: reset package.json * makes the base repository methods related to manager generic * makes some wrapper generic enough * add some todos * chore: added options CRUD * clean up * chore: fix issue with deleted_at not being updated * wip * chore: added categories write operations * chore: remove async nature of injection decorator * chore: added changeset * chore: reset package.json * chore: add manager injection to all contextable methods * chore: fix unit tests --------- Co-authored-by: adrien2p <adrien.deperetti@gmail.com> Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
43 files changed
+4218
-229
No files matched your search
@@ -2,7 +2,7 @@ export const productCategoriesData = [
|
||||
{
|
||||
id: "category-0",
|
||||
name: "category 0",
|
||||
parent_category_id: null
|
||||
parent_category_id: null,
|
||||
},
|
||||
{
|
||||
id: "category-1",
|
||||
@@ -26,3 +26,43 @@ export const productCategoriesData = [
|
||||
parent_category_id: "category-1-b"
|
||||
},
|
||||
]
|
||||
|
||||
export const productCategoriesRankData = [
|
||||
{
|
||||
id: "category-0-0",
|
||||
name: "category 0 0",
|
||||
parent_category_id: null,
|
||||
rank: 0,
|
||||
},
|
||||
{
|
||||
id: "category-0-1",
|
||||
name: "category 0 1",
|
||||
parent_category_id: null,
|
||||
rank: 1,
|
||||
},
|
||||
{
|
||||
id: "category-0-2",
|
||||
name: "category 0 2",
|
||||
parent_category_id: null,
|
||||
rank: 2,
|
||||
},
|
||||
{
|
||||
id: "category-0-0-0",
|
||||
name: "category 0 0-0",
|
||||
parent_category_id: "category-0-0",
|
||||
rank: 0,
|
||||
},
|
||||
{
|
||||
id: "category-0-0-1",
|
||||
name: "category 0 0-1",
|
||||
parent_category_id: "category-0-0",
|
||||
rank: 1,
|
||||
},
|
||||
{
|
||||
id: "category-0-0-2",
|
||||
name: "category 0 0-2",
|
||||
parent_category_id: "category-0-0",
|
||||
rank: 2,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -30,6 +30,24 @@ export async function createProductAndTags(
|
||||
return products
|
||||
}
|
||||
|
||||
export async function createProductAndTypes(
|
||||
manager: SqlEntityManager,
|
||||
data: {
|
||||
id?: string
|
||||
title: string
|
||||
status: ProductTypes.ProductStatus
|
||||
type?: { id: string; value: string }
|
||||
}[]
|
||||
) {
|
||||
const products: any[] = data.map((productData) => {
|
||||
return manager.create(Product, productData)
|
||||
})
|
||||
|
||||
await manager.persistAndFlush(products)
|
||||
|
||||
return products
|
||||
}
|
||||
|
||||
export async function createProductVariants(
|
||||
manager: SqlEntityManager,
|
||||
data: any[]
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ProductCategoryRepository } from "@repositories"
|
||||
import { ProductCategoryService } from "@services"
|
||||
|
||||
import { createProductCategories } from "../../../__fixtures__/product-category"
|
||||
import { productCategoriesData } from "../../../__fixtures__/product-category/data"
|
||||
import { productCategoriesData, productCategoriesRankData } from "../../../__fixtures__/product-category/data"
|
||||
import { TestDatabase } from "../../../utils"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
@@ -24,7 +24,7 @@ describe("Product category Service", () => {
|
||||
manager: repositoryManager,
|
||||
})
|
||||
|
||||
service = new ProductCategoryService({
|
||||
service = new ProductCategoryService<ProductCategory>({
|
||||
productCategoryRepository,
|
||||
})
|
||||
})
|
||||
@@ -560,4 +560,287 @@ describe("Product category Service", () => {
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("should create a category successfully", async () => {
|
||||
await service.create({
|
||||
name: "New Category",
|
||||
parent_category_id: null,
|
||||
})
|
||||
|
||||
const [productCategory] = await service.list({
|
||||
name: "New Category"
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategory).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "New Category",
|
||||
rank: "0",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should append rank from an existing category depending on parent", async () => {
|
||||
await service.create({
|
||||
name: "New Category",
|
||||
parent_category_id: null,
|
||||
rank: 0
|
||||
})
|
||||
|
||||
await service.create({
|
||||
name: "New Category 2",
|
||||
parent_category_id: null,
|
||||
})
|
||||
|
||||
const [productCategoryNew] = await service.list({
|
||||
name: "New Category 2"
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategoryNew).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "New Category 2",
|
||||
rank: "1",
|
||||
})
|
||||
)
|
||||
|
||||
await service.create({
|
||||
name: "New Category 2.1",
|
||||
parent_category_id: productCategoryNew.id,
|
||||
})
|
||||
|
||||
const [productCategoryWithParent] = await service.list({
|
||||
name: "New Category 2.1"
|
||||
}, {
|
||||
select: ["name", "rank", "parent_category_id"]
|
||||
})
|
||||
|
||||
expect(productCategoryWithParent).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "New Category 2.1",
|
||||
parent_category_id: productCategoryNew.id,
|
||||
rank: "0",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
let productCategoryZero
|
||||
let productCategoryOne
|
||||
let productCategoryTwo
|
||||
let productCategoryZeroZero
|
||||
let productCategoryZeroOne
|
||||
let productCategoryZeroTwo
|
||||
let categories
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
categories = await createProductCategories(
|
||||
testManager,
|
||||
productCategoriesRankData
|
||||
)
|
||||
|
||||
productCategoryZero = categories[0]
|
||||
productCategoryOne = categories[1]
|
||||
productCategoryTwo = categories[2]
|
||||
productCategoryZeroZero = categories[3]
|
||||
productCategoryZeroOne = categories[4]
|
||||
productCategoryZeroTwo = categories[5]
|
||||
})
|
||||
|
||||
it("should update the name of the category successfully", async () => {
|
||||
await service.update(productCategoryZero.id, {
|
||||
name: "New Category"
|
||||
})
|
||||
|
||||
const productCategory = await service.retrieve(productCategoryZero.id, {
|
||||
select: ["name"]
|
||||
})
|
||||
|
||||
expect(productCategory.name).toEqual("New Category")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.update("does-not-exist", {
|
||||
name: "New Category"
|
||||
})
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
|
||||
})
|
||||
|
||||
it("should reorder rank successfully in the same parent", async () => {
|
||||
await service.update(productCategoryTwo.id, {
|
||||
rank: 0,
|
||||
})
|
||||
|
||||
const productCategories = await service.list({
|
||||
parent_category_id: null
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZero.id,
|
||||
rank: "1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryOne.id,
|
||||
rank: "2",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should reorder rank successfully when changing parent", async () => {
|
||||
await service.update(productCategoryTwo.id, {
|
||||
rank: 0,
|
||||
parent_category_id: productCategoryZero.id
|
||||
})
|
||||
|
||||
const productCategories = await service.list({
|
||||
parent_category_id: productCategoryZero.id
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroZero.id,
|
||||
rank: "1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroOne.id,
|
||||
rank: "2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroTwo.id,
|
||||
rank: "3",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should reorder rank successfully when changing parent and in first position", async () => {
|
||||
await service.update(productCategoryTwo.id, {
|
||||
rank: 0,
|
||||
parent_category_id: productCategoryZero.id
|
||||
})
|
||||
|
||||
const productCategories = await service.list({
|
||||
parent_category_id: productCategoryZero.id
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroZero.id,
|
||||
rank: "1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroOne.id,
|
||||
rank: "2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroTwo.id,
|
||||
rank: "3",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
let productCategoryZero
|
||||
let productCategoryOne
|
||||
let productCategoryTwo
|
||||
let categories
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
categories = await createProductCategories(
|
||||
testManager,
|
||||
productCategoriesRankData
|
||||
)
|
||||
|
||||
productCategoryZero = categories[0]
|
||||
productCategoryOne = categories[1]
|
||||
productCategoryTwo = categories[2]
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.delete("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
|
||||
})
|
||||
|
||||
it("should throw an error when it has children", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.delete(productCategoryZero.id)
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`Deleting ProductCategory (category-0-0) with category children is not allowed`)
|
||||
})
|
||||
|
||||
it("should reorder siblings rank successfully on deleting", async () => {
|
||||
await service.delete(productCategoryOne.id)
|
||||
|
||||
const productCategories = await service.list({
|
||||
parent_category_id: null
|
||||
}, {
|
||||
select: ["id", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryZero.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "1",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -273,4 +273,90 @@ describe("Product collection Service", () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
const collectionId = "collection-1"
|
||||
const collectionData = {
|
||||
id: collectionId,
|
||||
title: "collection 1",
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
await createCollections(testManager, [collectionData])
|
||||
})
|
||||
|
||||
it("should delete the product collection given an ID successfully", async () => {
|
||||
await service.delete(
|
||||
[collectionId],
|
||||
)
|
||||
|
||||
const collections = await service.list({
|
||||
id: collectionId
|
||||
})
|
||||
|
||||
expect(collections).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
const collectionId = "collection-1"
|
||||
const collectionData = {
|
||||
id: collectionId,
|
||||
title: "collection 1",
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
await createCollections(testManager, [collectionData])
|
||||
})
|
||||
|
||||
it("should update the value of the collection successfully", async () => {
|
||||
await service.update(
|
||||
[{
|
||||
id: collectionId,
|
||||
title: "New Collection"
|
||||
}]
|
||||
)
|
||||
|
||||
const productCollection = await service.retrieve(collectionId)
|
||||
|
||||
expect(productCollection.title).toEqual("New Collection")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.update([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
title: "New Collection"
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductCollection with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("should create a collection successfully", async () => {
|
||||
await service.create(
|
||||
[{
|
||||
title: "New Collection"
|
||||
}]
|
||||
)
|
||||
|
||||
const [productCollection] = await service.list({
|
||||
title: "New Collection"
|
||||
})
|
||||
|
||||
expect(productCollection.title).toEqual("New Collection")
|
||||
})
|
||||
})
|
||||
})
|
||||
+287
-1
@@ -6,6 +6,7 @@ import { ProductTypes } from "@medusajs/types"
|
||||
import { initialize } from "../../../../src"
|
||||
import { DB_URL, TestDatabase } from "../../../utils"
|
||||
import { createProductCategories } from "../../../__fixtures__/product-category"
|
||||
import { productCategoriesRankData } from "../../../__fixtures__/product-category/data"
|
||||
|
||||
describe("ProductModuleService product categories", () => {
|
||||
let service: IProductModuleService
|
||||
@@ -201,7 +202,9 @@ describe("ProductModuleService product categories", () => {
|
||||
|
||||
describe("retrieveCategory", () => {
|
||||
it("should return the requested category", async () => {
|
||||
const result = await service.retrieveCategory(productCategoryOne.id)
|
||||
const result = await service.retrieveCategory(productCategoryOne.id, {
|
||||
select: ["id", "name"]
|
||||
})
|
||||
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -244,5 +247,288 @@ describe("ProductModuleService product categories", () => {
|
||||
expect(error.message).toEqual("ProductCategory with id: does-not-exist was not found")
|
||||
})
|
||||
})
|
||||
|
||||
describe("createCategory", () => {
|
||||
it("should create a category successfully", async () => {
|
||||
await service.createCategory({
|
||||
name: "New Category",
|
||||
parent_category_id: productCategoryOne.id,
|
||||
})
|
||||
|
||||
const [productCategory] = await service.listCategories({
|
||||
name: "New Category"
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategory).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "New Category",
|
||||
rank: "0",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should append rank from an existing category depending on parent", async () => {
|
||||
await service.createCategory({
|
||||
name: "New Category",
|
||||
parent_category_id: productCategoryOne.id,
|
||||
rank: 0
|
||||
})
|
||||
|
||||
await service.createCategory({
|
||||
name: "New Category 2",
|
||||
parent_category_id: productCategoryOne.id,
|
||||
})
|
||||
|
||||
const [productCategoryNew] = await service.listCategories({
|
||||
name: "New Category 2"
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategoryNew).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "New Category 2",
|
||||
rank: "1",
|
||||
})
|
||||
)
|
||||
|
||||
await service.createCategory({
|
||||
name: "New Category 2.1",
|
||||
parent_category_id: productCategoryNew.id,
|
||||
})
|
||||
|
||||
const [productCategoryWithParent] = await service.listCategories({
|
||||
name: "New Category 2.1"
|
||||
}, {
|
||||
select: ["name", "rank", "parent_category_id"]
|
||||
})
|
||||
|
||||
expect(productCategoryWithParent).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "New Category 2.1",
|
||||
parent_category_id: productCategoryNew.id,
|
||||
rank: "0",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateCategory", () => {
|
||||
let productCategoryZero
|
||||
let productCategoryOne
|
||||
let productCategoryTwo
|
||||
let productCategoryZeroZero
|
||||
let productCategoryZeroOne
|
||||
let productCategoryZeroTwo
|
||||
let categories
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
categories = await createProductCategories(
|
||||
testManager,
|
||||
productCategoriesRankData
|
||||
)
|
||||
|
||||
productCategoryZero = categories[0]
|
||||
productCategoryOne = categories[1]
|
||||
productCategoryTwo = categories[2]
|
||||
productCategoryZeroZero = categories[3]
|
||||
productCategoryZeroOne = categories[4]
|
||||
productCategoryZeroTwo = categories[5]
|
||||
})
|
||||
|
||||
it("should update the name of the category successfully", async () => {
|
||||
await service.updateCategory(productCategoryZero.id, {
|
||||
name: "New Category"
|
||||
})
|
||||
|
||||
const productCategory = await service.retrieveCategory(productCategoryZero.id, {
|
||||
select: ["name"]
|
||||
})
|
||||
|
||||
expect(productCategory.name).toEqual("New Category")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.updateCategory("does-not-exist", {
|
||||
name: "New Category"
|
||||
})
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
|
||||
})
|
||||
|
||||
it("should reorder rank successfully in the same parent", async () => {
|
||||
await service.updateCategory(productCategoryTwo.id, {
|
||||
rank: 0,
|
||||
})
|
||||
|
||||
const productCategories = await service.listCategories({
|
||||
parent_category_id: null
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZero.id,
|
||||
rank: "1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryOne.id,
|
||||
rank: "2",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should reorder rank successfully when changing parent", async () => {
|
||||
await service.updateCategory(productCategoryTwo.id, {
|
||||
rank: 0,
|
||||
parent_category_id: productCategoryZero.id
|
||||
})
|
||||
|
||||
const productCategories = await service.listCategories({
|
||||
parent_category_id: productCategoryZero.id
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroZero.id,
|
||||
rank: "1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroOne.id,
|
||||
rank: "2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroTwo.id,
|
||||
rank: "3",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should reorder rank successfully when changing parent and in first position", async () => {
|
||||
await service.updateCategory(productCategoryTwo.id, {
|
||||
rank: 0,
|
||||
parent_category_id: productCategoryZero.id
|
||||
})
|
||||
|
||||
const productCategories = await service.listCategories({
|
||||
parent_category_id: productCategoryZero.id
|
||||
}, {
|
||||
select: ["name", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroZero.id,
|
||||
rank: "1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroOne.id,
|
||||
rank: "2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryZeroTwo.id,
|
||||
rank: "3",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleteCategory", () => {
|
||||
let productCategoryZero
|
||||
let productCategoryOne
|
||||
let productCategoryTwo
|
||||
let categories
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
categories = await createProductCategories(
|
||||
testManager,
|
||||
productCategoriesRankData
|
||||
)
|
||||
|
||||
productCategoryZero = categories[0]
|
||||
productCategoryOne = categories[1]
|
||||
productCategoryTwo = categories[2]
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.deleteCategory("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
|
||||
})
|
||||
|
||||
it("should throw an error when it has children", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.deleteCategory(productCategoryZero.id)
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`Deleting ProductCategory (category-0-0) with category children is not allowed`)
|
||||
})
|
||||
|
||||
it("should reorder siblings rank successfully on deleting", async () => {
|
||||
await service.deleteCategory(productCategoryOne.id)
|
||||
|
||||
const productCategories = await service.listCategories({
|
||||
parent_category_id: null
|
||||
}, {
|
||||
select: ["id", "rank"]
|
||||
})
|
||||
|
||||
expect(productCategories).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: productCategoryZero.id,
|
||||
rank: "0",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: productCategoryTwo.id,
|
||||
rank: "1",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+66
@@ -246,5 +246,71 @@ describe("ProductModuleService product collections", () => {
|
||||
expect(error.message).toEqual("ProductCollection with id: does-not-exist was not found")
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleteCollections", () => {
|
||||
const collectionId = "test-1"
|
||||
|
||||
it("should delete the product collection given an ID successfully", async () => {
|
||||
await service.deleteCollections(
|
||||
[collectionId],
|
||||
)
|
||||
|
||||
const collections = await service.listCollections({
|
||||
id: collectionId
|
||||
})
|
||||
|
||||
expect(collections).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateCollections", () => {
|
||||
const collectionId = "test-1"
|
||||
|
||||
it("should update the value of the collection successfully", async () => {
|
||||
await service.updateCollections(
|
||||
[{
|
||||
id: collectionId,
|
||||
title: "New Collection"
|
||||
}]
|
||||
)
|
||||
|
||||
const productCollection = await service.retrieveCollection(collectionId)
|
||||
|
||||
expect(productCollection.title).toEqual("New Collection")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.updateCollections([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
title: "New Collection"
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductCollection with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("createCollections", () => {
|
||||
it("should create a collection successfully", async () => {
|
||||
const res = await service.createCollections(
|
||||
[{
|
||||
title: "New Collection"
|
||||
}]
|
||||
)
|
||||
|
||||
const [productCollection] = await service.listCollections({
|
||||
title: "New Collection"
|
||||
})
|
||||
|
||||
expect(productCollection.title).toEqual("New Collection")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
import { initialize } from "../../../../src"
|
||||
import { DB_URL, TestDatabase } from "../../../utils"
|
||||
import { IProductModuleService } from "@medusajs/types"
|
||||
import { Product, ProductOption } from "@models"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
|
||||
describe("ProductModuleService product options", () => {
|
||||
let service: IProductModuleService
|
||||
let testManager: SqlEntityManager
|
||||
let repositoryManager: SqlEntityManager
|
||||
let optionOne: ProductOption
|
||||
let optionTwo: ProductOption
|
||||
let productOne: Product
|
||||
let productTwo: Product
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestDatabase.setupDatabase()
|
||||
repositoryManager = await TestDatabase.forkManager()
|
||||
|
||||
service = await initialize({
|
||||
database: {
|
||||
clientUrl: DB_URL,
|
||||
schema: process.env.MEDUSA_PRODUCT_DB_SCHEMA,
|
||||
},
|
||||
})
|
||||
|
||||
testManager = await TestDatabase.forkManager()
|
||||
productOne = testManager.create(Product, {
|
||||
id: "product-1",
|
||||
title: "product 1",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
})
|
||||
|
||||
productTwo = testManager.create(Product, {
|
||||
id: "product-2",
|
||||
title: "product 2",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
})
|
||||
|
||||
optionOne = testManager.create(ProductOption, {
|
||||
id: "option-1",
|
||||
title: "option 1",
|
||||
product: productOne,
|
||||
})
|
||||
|
||||
optionTwo = testManager.create(ProductOption, {
|
||||
id: "option-2",
|
||||
title: "option 1",
|
||||
product: productTwo,
|
||||
})
|
||||
|
||||
await testManager.persistAndFlush([optionOne, optionTwo])
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await TestDatabase.clearDatabase()
|
||||
})
|
||||
|
||||
describe("listOptions", () => {
|
||||
it("should return options and count queried by ID", async () => {
|
||||
const options = await service.listOptions({
|
||||
id: optionOne.id,
|
||||
})
|
||||
|
||||
expect(options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: optionOne.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return options and count based on the options and filter parameter", async () => {
|
||||
let options = await service.listOptions(
|
||||
{
|
||||
id: optionOne.id,
|
||||
},
|
||||
{
|
||||
take: 1,
|
||||
}
|
||||
)
|
||||
|
||||
expect(options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: optionOne.id,
|
||||
}),
|
||||
])
|
||||
|
||||
options = await service.listOptions({}, { take: 1, skip: 1 })
|
||||
|
||||
expect(options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: optionTwo.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return only requested fields and relations for options", async () => {
|
||||
const options = await service.listOptions(
|
||||
{
|
||||
id: optionOne.id,
|
||||
},
|
||||
{
|
||||
select: ["title", "product.id"],
|
||||
relations: ["product"],
|
||||
take: 1
|
||||
}
|
||||
)
|
||||
|
||||
expect(options).toEqual([
|
||||
{
|
||||
id: optionOne.id,
|
||||
title: optionOne.title,
|
||||
product_id: productOne.id,
|
||||
product: {
|
||||
id: productOne.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("listAndCountOptions", () => {
|
||||
it("should return options and count queried by ID", async () => {
|
||||
const [options, count] = await service.listAndCountOptions({
|
||||
id: optionOne.id,
|
||||
})
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: optionOne.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return options and count based on the options and filter parameter", async () => {
|
||||
let [options, count] = await service.listAndCountOptions(
|
||||
{
|
||||
id: optionOne.id,
|
||||
},
|
||||
{
|
||||
take: 1,
|
||||
}
|
||||
)
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: optionOne.id,
|
||||
}),
|
||||
])
|
||||
|
||||
;[options, count] = await service.listAndCountOptions({}, { take: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
|
||||
;[options, count] = await service.listAndCountOptions({}, { take: 1, skip: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: optionTwo.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return only requested fields and relations for options", async () => {
|
||||
const [options, count] = await service.listAndCountOptions(
|
||||
{
|
||||
id: optionOne.id,
|
||||
},
|
||||
{
|
||||
select: ["title", "product.id"],
|
||||
relations: ["product"],
|
||||
take: 1
|
||||
}
|
||||
)
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(options).toEqual([{
|
||||
id: optionOne.id,
|
||||
title: optionOne.title,
|
||||
product_id: productOne.id,
|
||||
product: {
|
||||
id: productOne.id,
|
||||
},
|
||||
}])
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieveOption", () => {
|
||||
it("should return the requested option", async () => {
|
||||
const option = await service.retrieveOption(optionOne.id)
|
||||
|
||||
expect(option).toEqual(
|
||||
expect.objectContaining({
|
||||
id: optionOne.id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("should return requested attributes when requested through config", async () => {
|
||||
const option = await service.retrieveOption(
|
||||
optionOne.id,
|
||||
{
|
||||
select: ["id", "product.title"],
|
||||
relations: ["product"],
|
||||
}
|
||||
)
|
||||
|
||||
expect(option).toEqual(
|
||||
expect.objectContaining({
|
||||
id: optionOne.id,
|
||||
product: {
|
||||
id: "product-1",
|
||||
title: "product 1",
|
||||
},
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when a option with ID does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieveOption("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual("ProductOption with id: does-not-exist was not found")
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleteOptions", () => {
|
||||
const optionId = "option-1"
|
||||
|
||||
it("should delete the product option given an ID successfully", async () => {
|
||||
await service.deleteOptions(
|
||||
[optionId],
|
||||
)
|
||||
|
||||
const options = await service.listOptions({
|
||||
id: optionId
|
||||
})
|
||||
|
||||
expect(options).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateOptions", () => {
|
||||
const optionId = "option-1"
|
||||
|
||||
it("should update the title of the option successfully", async () => {
|
||||
await service.updateOptions(
|
||||
[{
|
||||
id: optionId,
|
||||
title: "new test"
|
||||
}]
|
||||
)
|
||||
|
||||
const productOption = await service.retrieveOption(optionId)
|
||||
|
||||
expect(productOption.title).toEqual("new test")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.updateOptions([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductOption with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("createOptions", () => {
|
||||
it("should create a option successfully", async () => {
|
||||
const res = await service.createOptions([{
|
||||
title: "test",
|
||||
product_id: productOne.id
|
||||
}])
|
||||
|
||||
const productOption = await service.listOptions({
|
||||
title: "test"
|
||||
})
|
||||
|
||||
expect(productOption[0]?.title).toEqual("test")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
import { initialize } from "../../../../src"
|
||||
import { DB_URL, TestDatabase } from "../../../utils"
|
||||
import { IProductModuleService } from "@medusajs/types"
|
||||
import { Product, ProductTag } from "@models"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
|
||||
describe("ProductModuleService product tags", () => {
|
||||
let service: IProductModuleService
|
||||
let testManager: SqlEntityManager
|
||||
let repositoryManager: SqlEntityManager
|
||||
let tagOne: ProductTag
|
||||
let tagTwo: ProductTag
|
||||
let productOne: Product
|
||||
let productTwo: Product
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestDatabase.setupDatabase()
|
||||
repositoryManager = await TestDatabase.forkManager()
|
||||
|
||||
service = await initialize({
|
||||
database: {
|
||||
clientUrl: DB_URL,
|
||||
schema: process.env.MEDUSA_PRODUCT_DB_SCHEMA,
|
||||
},
|
||||
})
|
||||
|
||||
testManager = await TestDatabase.forkManager()
|
||||
productOne = testManager.create(Product, {
|
||||
id: "product-1",
|
||||
title: "product 1",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
})
|
||||
|
||||
productTwo = testManager.create(Product, {
|
||||
id: "product-2",
|
||||
title: "product 2",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
})
|
||||
|
||||
tagOne = testManager.create(ProductTag, {
|
||||
id: "tag-1",
|
||||
value: "tag 1",
|
||||
products: [productOne],
|
||||
})
|
||||
|
||||
tagTwo = testManager.create(ProductTag, {
|
||||
id: "tag-2",
|
||||
value: "tag",
|
||||
products: [productTwo],
|
||||
})
|
||||
|
||||
await testManager.persistAndFlush([tagOne, tagTwo])
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await TestDatabase.clearDatabase()
|
||||
})
|
||||
|
||||
describe("listTags", () => {
|
||||
it("should return tags and count queried by ID", async () => {
|
||||
const tags = await service.listTags({
|
||||
id: tagOne.id,
|
||||
})
|
||||
|
||||
expect(tags).toEqual([
|
||||
expect.objectContaining({
|
||||
id: tagOne.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return tags and count based on the options and filter parameter", async () => {
|
||||
let tags = await service.listTags(
|
||||
{
|
||||
id: tagOne.id,
|
||||
},
|
||||
{
|
||||
take: 1,
|
||||
}
|
||||
)
|
||||
|
||||
expect(tags).toEqual([
|
||||
expect.objectContaining({
|
||||
id: tagOne.id,
|
||||
}),
|
||||
])
|
||||
|
||||
tags = await service.listTags({}, { take: 1, skip: 1 })
|
||||
|
||||
expect(tags).toEqual([
|
||||
expect.objectContaining({
|
||||
id: tagTwo.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return only requested fields and relations for tags", async () => {
|
||||
const tags = await service.listTags(
|
||||
{
|
||||
id: tagOne.id,
|
||||
},
|
||||
{
|
||||
select: ["value", "products.id"],
|
||||
relations: ["products"],
|
||||
take: 1
|
||||
}
|
||||
)
|
||||
|
||||
expect(tags).toEqual([
|
||||
{
|
||||
id: tagOne.id,
|
||||
value: tagOne.value,
|
||||
products: [{
|
||||
id: productOne.id,
|
||||
}],
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("listAndCountTags", () => {
|
||||
it("should return tags and count queried by ID", async () => {
|
||||
const [tags, count] = await service.listAndCountTags({
|
||||
id: tagOne.id,
|
||||
})
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(tags).toEqual([
|
||||
expect.objectContaining({
|
||||
id: tagOne.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return tags and count based on the options and filter parameter", async () => {
|
||||
let [tags, count] = await service.listAndCountTags(
|
||||
{
|
||||
id: tagOne.id,
|
||||
},
|
||||
{
|
||||
take: 1,
|
||||
}
|
||||
)
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(tags).toEqual([
|
||||
expect.objectContaining({
|
||||
id: tagOne.id,
|
||||
}),
|
||||
])
|
||||
|
||||
;[tags, count] = await service.listAndCountTags({}, { take: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
|
||||
;[tags, count] = await service.listAndCountTags({}, { take: 1, skip: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(tags).toEqual([
|
||||
expect.objectContaining({
|
||||
id: tagTwo.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return only requested fields and relations for tags", async () => {
|
||||
const [tags, count] = await service.listAndCountTags(
|
||||
{
|
||||
id: tagOne.id,
|
||||
},
|
||||
{
|
||||
select: ["value", "products.id"],
|
||||
relations: ["products"],
|
||||
take: 1
|
||||
}
|
||||
)
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(tags).toEqual([
|
||||
{
|
||||
id: tagOne.id,
|
||||
value: tagOne.value,
|
||||
products: [{
|
||||
id: productOne.id,
|
||||
}],
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieveTag", () => {
|
||||
it("should return the requested tag", async () => {
|
||||
const tag = await service.retrieveTag(tagOne.id)
|
||||
|
||||
expect(tag).toEqual(
|
||||
expect.objectContaining({
|
||||
id: tagOne.id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("should return requested attributes when requested through config", async () => {
|
||||
const tag = await service.retrieveTag(
|
||||
tagOne.id,
|
||||
{
|
||||
select: ["id", "value", "products.title"],
|
||||
relations: ["products"],
|
||||
}
|
||||
)
|
||||
|
||||
expect(tag).toEqual(
|
||||
expect.objectContaining({
|
||||
id: tagOne.id,
|
||||
value: tagOne.value,
|
||||
products: [{
|
||||
id: "product-1",
|
||||
title: "product 1",
|
||||
}],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when a tag with ID does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieveTag("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual("ProductTag with id: does-not-exist was not found")
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleteTags", () => {
|
||||
const tagId = "tag-1"
|
||||
|
||||
it("should delete the product tag given an ID successfully", async () => {
|
||||
await service.deleteTags(
|
||||
[tagId],
|
||||
)
|
||||
|
||||
const tags = await service.listTags({
|
||||
id: tagId
|
||||
})
|
||||
|
||||
expect(tags).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateTags", () => {
|
||||
const tagId = "tag-1"
|
||||
|
||||
it("should update the value of the tag successfully", async () => {
|
||||
await service.updateTags(
|
||||
[{
|
||||
id: tagId,
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const productTag = await service.retrieveTag(tagId)
|
||||
|
||||
expect(productTag.value).toEqual("UK")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.updateTags([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
value: "UK"
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductTag with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("createTags", () => {
|
||||
it("should create a tag successfully", async () => {
|
||||
const res = await service.createTags(
|
||||
[{
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const productTag = await service.listTags({
|
||||
value: "UK"
|
||||
})
|
||||
|
||||
expect(productTag[0]?.value).toEqual("UK")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
import { initialize } from "../../../../src"
|
||||
import { DB_URL, TestDatabase } from "../../../utils"
|
||||
import { IProductModuleService } from "@medusajs/types"
|
||||
import { ProductType } from "@models"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
|
||||
describe("ProductModuleService product types", () => {
|
||||
let service: IProductModuleService
|
||||
let testManager: SqlEntityManager
|
||||
let repositoryManager: SqlEntityManager
|
||||
let typeOne: ProductType
|
||||
let typeTwo: ProductType
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestDatabase.setupDatabase()
|
||||
repositoryManager = await TestDatabase.forkManager()
|
||||
|
||||
service = await initialize({
|
||||
database: {
|
||||
clientUrl: DB_URL,
|
||||
schema: process.env.MEDUSA_PRODUCT_DB_SCHEMA,
|
||||
},
|
||||
})
|
||||
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
typeOne = testManager.create(ProductType, {
|
||||
id: "type-1",
|
||||
value: "type 1",
|
||||
})
|
||||
|
||||
typeTwo = testManager.create(ProductType, {
|
||||
id: "type-2",
|
||||
value: "type",
|
||||
})
|
||||
|
||||
await testManager.persistAndFlush([typeOne, typeTwo])
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await TestDatabase.clearDatabase()
|
||||
})
|
||||
|
||||
describe("listTypes", () => {
|
||||
it("should return types and count queried by ID", async () => {
|
||||
const types = await service.listTypes({
|
||||
id: typeOne.id,
|
||||
})
|
||||
|
||||
expect(types).toEqual([
|
||||
expect.objectContaining({
|
||||
id: typeOne.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return types and count based on the options and filter parameter", async () => {
|
||||
let types = await service.listTypes(
|
||||
{
|
||||
id: typeOne.id,
|
||||
},
|
||||
{
|
||||
take: 1,
|
||||
}
|
||||
)
|
||||
|
||||
expect(types).toEqual([
|
||||
expect.objectContaining({
|
||||
id: typeOne.id,
|
||||
}),
|
||||
])
|
||||
|
||||
types = await service.listTypes({}, { take: 1, skip: 1 })
|
||||
|
||||
expect(types).toEqual([
|
||||
expect.objectContaining({
|
||||
id: typeTwo.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return only requested fields for types", async () => {
|
||||
const types = await service.listTypes(
|
||||
{
|
||||
id: typeOne.id,
|
||||
},
|
||||
{
|
||||
select: ["value"],
|
||||
take: 1
|
||||
}
|
||||
)
|
||||
|
||||
expect(types).toEqual([
|
||||
{
|
||||
id: typeOne.id,
|
||||
value: typeOne.value,
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("listAndCountTypes", () => {
|
||||
it("should return types and count queried by ID", async () => {
|
||||
const [types, count] = await service.listAndCountTypes({
|
||||
id: typeOne.id,
|
||||
})
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(types).toEqual([
|
||||
expect.objectContaining({
|
||||
id: typeOne.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return types and count based on the options and filter parameter", async () => {
|
||||
let [types, count] = await service.listAndCountTypes(
|
||||
{
|
||||
id: typeOne.id,
|
||||
},
|
||||
{
|
||||
take: 1,
|
||||
}
|
||||
)
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(types).toEqual([
|
||||
expect.objectContaining({
|
||||
id: typeOne.id,
|
||||
}),
|
||||
])
|
||||
|
||||
;[types, count] = await service.listAndCountTypes({}, { take: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
|
||||
;[types, count] = await service.listAndCountTypes({}, { take: 1, skip: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(types).toEqual([
|
||||
expect.objectContaining({
|
||||
id: typeTwo.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return only requested fields for types", async () => {
|
||||
const [types, count] = await service.listAndCountTypes(
|
||||
{
|
||||
id: typeOne.id,
|
||||
},
|
||||
{
|
||||
select: ["value"],
|
||||
take: 1
|
||||
}
|
||||
)
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(types).toEqual([
|
||||
{
|
||||
id: typeOne.id,
|
||||
value: typeOne.value,
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieveType", () => {
|
||||
it("should return the requested type", async () => {
|
||||
const type = await service.retrieveType(typeOne.id)
|
||||
|
||||
expect(type).toEqual(
|
||||
expect.objectContaining({
|
||||
id: typeOne.id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("should return requested attributes when requested through config", async () => {
|
||||
const type = await service.retrieveType(
|
||||
typeOne.id,
|
||||
{
|
||||
select: ["id", "value"],
|
||||
}
|
||||
)
|
||||
|
||||
expect(type).toEqual(
|
||||
{
|
||||
id: typeOne.id,
|
||||
value: typeOne.value,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when a type with ID does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieveType("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual("ProductType with id: does-not-exist was not found")
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleteTypes", () => {
|
||||
const typeId = "type-1"
|
||||
|
||||
it("should delete the product type given an ID successfully", async () => {
|
||||
await service.deleteTypes(
|
||||
[typeId],
|
||||
)
|
||||
|
||||
const types = await service.listTypes({
|
||||
id: typeId
|
||||
})
|
||||
|
||||
expect(types).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateTypes", () => {
|
||||
const typeId = "type-1"
|
||||
|
||||
it("should update the value of the type successfully", async () => {
|
||||
await service.updateTypes(
|
||||
[{
|
||||
id: typeId,
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const productType = await service.retrieveType(typeId)
|
||||
|
||||
expect(productType.value).toEqual("UK")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.updateTypes([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
value: "UK"
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductType with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("createTypes", () => {
|
||||
it("should create a type successfully", async () => {
|
||||
const res = await service.createTypes(
|
||||
[{
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const productType = await service.listTypes({
|
||||
value: "UK"
|
||||
})
|
||||
|
||||
expect(productType[0]?.value).toEqual("UK")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
|
||||
import { ProductOptionService } from "@services"
|
||||
import { ProductOptionRepository } from "@repositories"
|
||||
import { Product } from "@models"
|
||||
|
||||
import { TestDatabase } from "../../../utils"
|
||||
import { createOptions } from "../../../__fixtures__/product"
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("ProductOption Service", () => {
|
||||
let service: ProductOptionService
|
||||
let testManager: SqlEntityManager
|
||||
let repositoryManager: SqlEntityManager
|
||||
let productOne: Product
|
||||
let productTwo: Product
|
||||
let data!: Product[]
|
||||
|
||||
const productOneData = {
|
||||
id: "product-1",
|
||||
title: "product 1",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
}
|
||||
|
||||
const productTwoData = {
|
||||
id: "product-2",
|
||||
title: "product 2",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestDatabase.setupDatabase()
|
||||
repositoryManager = await TestDatabase.forkManager()
|
||||
|
||||
const productOptionRepository = new ProductOptionRepository({
|
||||
manager: repositoryManager,
|
||||
})
|
||||
|
||||
service = new ProductOptionService({
|
||||
productOptionRepository,
|
||||
})
|
||||
|
||||
testManager = await TestDatabase.forkManager()
|
||||
productOne = testManager.create(Product, productOneData)
|
||||
productTwo = testManager.create(Product, productTwoData)
|
||||
|
||||
data = await createOptions(testManager, [
|
||||
{
|
||||
id: "option-1",
|
||||
title: "Option 1",
|
||||
product: productOne,
|
||||
},
|
||||
{
|
||||
id: "option-2",
|
||||
title: "Option 2",
|
||||
product: productOne,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await TestDatabase.clearDatabase()
|
||||
})
|
||||
|
||||
describe("list", () => {
|
||||
it("list product option", async () => {
|
||||
const optionResults = await service.list()
|
||||
|
||||
expect(optionResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-1",
|
||||
title: "Option 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "option-2",
|
||||
title: "Option 2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("list product option by id", async () => {
|
||||
const optionResults = await service.list({ id: "option-2" })
|
||||
|
||||
expect(optionResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-2",
|
||||
title: "Option 2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("list product option by title matching string", async () => {
|
||||
const optionResults = await service.list({ title: "Option 1" })
|
||||
|
||||
expect(optionResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-1",
|
||||
title: "Option 1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("listAndCount", () => {
|
||||
it("should return product option and count", async () => {
|
||||
const [optionResults, count] = await service.listAndCount()
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(optionResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-1",
|
||||
title: "Option 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "option-2",
|
||||
title: "Option 2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return product option and count when filtered", async () => {
|
||||
const [optionResults, count] = await service.listAndCount({ id: "option-2" })
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(optionResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return product option and count when using skip and take", async () => {
|
||||
const [optionResults, count] = await service.listAndCount({}, { skip: 1, take: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(optionResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return requested fields", async () => {
|
||||
const [optionResults, count] = await service.listAndCount({}, {
|
||||
take: 1,
|
||||
select: ["title"],
|
||||
})
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(optionResults))
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(serialized).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "option-1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieve", () => {
|
||||
const optionId = "option-1"
|
||||
const optionValue = "Option 1"
|
||||
|
||||
it("should return option for the given id", async () => {
|
||||
const option = await service.retrieve(
|
||||
optionId,
|
||||
)
|
||||
|
||||
expect(option).toEqual(
|
||||
expect.objectContaining({
|
||||
id: optionId
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when option with id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieve("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductOption with id: does-not-exist was not found')
|
||||
})
|
||||
|
||||
it("should throw an error when an id is not provided", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieve(undefined as unknown as string)
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('"productOptionId" must be defined')
|
||||
})
|
||||
|
||||
it("should return option based on config select param", async () => {
|
||||
const option = await service.retrieve(
|
||||
optionId,
|
||||
{
|
||||
select: ["id", "title"],
|
||||
}
|
||||
)
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(option))
|
||||
|
||||
expect(serialized).toEqual(
|
||||
{
|
||||
id: optionId,
|
||||
title: optionValue,
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
const optionId = "option-1"
|
||||
|
||||
it("should delete the product option given an ID successfully", async () => {
|
||||
|
||||
await service.delete(
|
||||
[optionId],
|
||||
)
|
||||
|
||||
const options = await service.list({
|
||||
id: optionId
|
||||
})
|
||||
|
||||
expect(options).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
const optionId = "option-1"
|
||||
|
||||
it("should update the title of the option successfully", async () => {
|
||||
await service.update(
|
||||
[{
|
||||
id: optionId,
|
||||
title: "UK",
|
||||
}]
|
||||
)
|
||||
|
||||
const productOption = await service.retrieve(optionId)
|
||||
|
||||
expect(productOption.title).toEqual("UK")
|
||||
})
|
||||
|
||||
it("should update the relationship of the option successfully", async () => {
|
||||
await service.update(
|
||||
[{
|
||||
id: optionId,
|
||||
product_id: productTwo.id,
|
||||
}]
|
||||
)
|
||||
|
||||
const productOption = await service.retrieve(optionId, {
|
||||
relations: ["product"]
|
||||
})
|
||||
|
||||
expect(productOption).toEqual(
|
||||
expect.objectContaining({
|
||||
id: optionId,
|
||||
product: expect.objectContaining({
|
||||
id: productTwo.id
|
||||
})
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.update([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
title: "UK",
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductOption with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("should create a option successfully", async () => {
|
||||
await service.create(
|
||||
[{
|
||||
title: "UK",
|
||||
product: productOne
|
||||
}]
|
||||
)
|
||||
|
||||
const [productOption] = await service.list({
|
||||
title: "UK"
|
||||
}, {
|
||||
relations: ["product"],
|
||||
})
|
||||
|
||||
|
||||
expect(productOption).toEqual(
|
||||
expect.objectContaining({
|
||||
title: "UK",
|
||||
product: expect.objectContaining({
|
||||
id: productOne.id
|
||||
})
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -10,12 +10,45 @@ import { TestDatabase } from "../../../utils"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("Product tag Service", () => {
|
||||
describe("ProductTag Service", () => {
|
||||
let service: ProductTagService
|
||||
let testManager: SqlEntityManager
|
||||
let repositoryManager: SqlEntityManager
|
||||
let data!: Product[]
|
||||
|
||||
const productsData = [
|
||||
{
|
||||
id: "test-1",
|
||||
title: "product 1",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
tags: [
|
||||
{
|
||||
id: "tag-1",
|
||||
value: "France",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "test-2",
|
||||
title: "product",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
tags: [
|
||||
{
|
||||
id: "tag-2",
|
||||
value: "Germany",
|
||||
},
|
||||
{
|
||||
id: "tag-3",
|
||||
value: "United States",
|
||||
},
|
||||
{
|
||||
id: "tag-4",
|
||||
value: "United Kingdom",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestDatabase.setupDatabase()
|
||||
repositoryManager = await TestDatabase.forkManager()
|
||||
@@ -27,6 +60,10 @@ describe("Product tag Service", () => {
|
||||
service = new ProductTagService({
|
||||
productTagRepository,
|
||||
})
|
||||
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
data = await createProductAndTags(testManager, productsData)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -34,45 +71,6 @@ describe("Product tag Service", () => {
|
||||
})
|
||||
|
||||
describe("list", () => {
|
||||
const productsData = [
|
||||
{
|
||||
id: "test-1",
|
||||
title: "product 1",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
tags: [
|
||||
{
|
||||
id: "tag-1",
|
||||
value: "France",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "test-2",
|
||||
title: "product",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
tags: [
|
||||
{
|
||||
id: "tag-2",
|
||||
value: "Germany",
|
||||
},
|
||||
{
|
||||
id: "tag-3",
|
||||
value: "United States",
|
||||
},
|
||||
{
|
||||
id: "tag-4",
|
||||
value: "United Kingdom",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
beforeEach(async () => {
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
data = await createProductAndTags(testManager, productsData)
|
||||
})
|
||||
|
||||
it("list product tags", async () => {
|
||||
const tagsResults = await service.list()
|
||||
|
||||
@@ -118,4 +116,223 @@ describe("Product tag Service", () => {
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("listAndCount", () => {
|
||||
it("should return product tags and count", async () => {
|
||||
const [tagsResults, count] = await service.listAndCount()
|
||||
|
||||
expect(count).toEqual(4)
|
||||
expect(tagsResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "tag-1",
|
||||
value: "France",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "tag-2",
|
||||
value: "Germany",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "tag-3",
|
||||
value: "United States",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "tag-4",
|
||||
value: "United Kingdom",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return product tags and count when filtered", async () => {
|
||||
const [tagsResults, count] = await service.listAndCount({ id: data[0].tags![0].id })
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(tagsResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "tag-1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return product tags and count when using skip and take", async () => {
|
||||
const [tagsResults, count] = await service.listAndCount({}, { skip: 1, take: 2 })
|
||||
|
||||
expect(count).toEqual(4)
|
||||
expect(tagsResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "tag-2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "tag-3",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return requested fields and relations", async () => {
|
||||
const [tagsResults, count] = await service.listAndCount({}, {
|
||||
take: 1,
|
||||
select: ["value", "products.id"],
|
||||
relations: ["products"]
|
||||
})
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(tagsResults))
|
||||
|
||||
expect(count).toEqual(4)
|
||||
expect(serialized).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "tag-1",
|
||||
products: [{
|
||||
id: "test-1"
|
||||
}]
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieve", () => {
|
||||
const tagId = "tag-1"
|
||||
const tagValue = "France"
|
||||
const productId = "test-1"
|
||||
|
||||
it("should return tag for the given id", async () => {
|
||||
const tag = await service.retrieve(
|
||||
tagId,
|
||||
)
|
||||
|
||||
expect(tag).toEqual(
|
||||
expect.objectContaining({
|
||||
id: tagId
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when tag with id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieve("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductTag with id: does-not-exist was not found')
|
||||
})
|
||||
|
||||
it("should throw an error when an id is not provided", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieve(undefined as unknown as string)
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('"productTagId" must be defined')
|
||||
})
|
||||
|
||||
it("should return tag based on config select param", async () => {
|
||||
const tag = await service.retrieve(
|
||||
tagId,
|
||||
{
|
||||
select: ["id", "value"],
|
||||
}
|
||||
)
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(tag))
|
||||
|
||||
expect(serialized).toEqual(
|
||||
{
|
||||
id: tagId,
|
||||
value: tagValue,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("should return tag based on config relation param", async () => {
|
||||
const tag = await service.retrieve(
|
||||
tagId,
|
||||
{
|
||||
select: ["id", "value", "products.id"],
|
||||
relations: ["products"]
|
||||
}
|
||||
)
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(tag))
|
||||
|
||||
expect(serialized).toEqual(
|
||||
{
|
||||
id: tagId,
|
||||
value: tagValue,
|
||||
products: [{
|
||||
id: productId
|
||||
}]
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
const tagId = "tag-1"
|
||||
|
||||
it("should delete the product tag given an ID successfully", async () => {
|
||||
await service.delete(
|
||||
[tagId],
|
||||
)
|
||||
|
||||
const tags = await service.list({
|
||||
id: tagId
|
||||
})
|
||||
|
||||
expect(tags).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
const tagId = "tag-1"
|
||||
|
||||
it("should update the value of the tag successfully", async () => {
|
||||
await service.update(
|
||||
[{
|
||||
id: tagId,
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const productTag = await service.retrieve(tagId)
|
||||
|
||||
expect(productTag.value).toEqual("UK")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.update([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
value: "UK"
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductTag with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("should create a tag successfully", async () => {
|
||||
await service.create(
|
||||
[{
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const [productTag] = await service.list({
|
||||
value: "UK"
|
||||
})
|
||||
|
||||
expect(productTag.value).toEqual("UK")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,280 @@
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
|
||||
import { ProductTypeService } from "@services"
|
||||
import { ProductTypeRepository } from "@repositories"
|
||||
import { Product } from "@models"
|
||||
|
||||
import { TestDatabase } from "../../../utils"
|
||||
import { createProductAndTypes } from "../../../__fixtures__/product"
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("ProductType Service", () => {
|
||||
let service: ProductTypeService
|
||||
let testManager: SqlEntityManager
|
||||
let repositoryManager: SqlEntityManager
|
||||
let data!: Product[]
|
||||
|
||||
const productsData = [
|
||||
{
|
||||
id: "product-1",
|
||||
title: "product 1",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
type: {
|
||||
id: "type-1",
|
||||
value: "Type 1",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "product-2",
|
||||
title: "product",
|
||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||
type: {
|
||||
id: "type-2",
|
||||
value: "Type 2",
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestDatabase.setupDatabase()
|
||||
repositoryManager = await TestDatabase.forkManager()
|
||||
|
||||
const productTypeRepository = new ProductTypeRepository({
|
||||
manager: repositoryManager,
|
||||
})
|
||||
|
||||
service = new ProductTypeService({
|
||||
productTypeRepository,
|
||||
})
|
||||
|
||||
testManager = await TestDatabase.forkManager()
|
||||
|
||||
data = await createProductAndTypes(testManager, productsData)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await TestDatabase.clearDatabase()
|
||||
})
|
||||
|
||||
describe("list", () => {
|
||||
it("list product type", async () => {
|
||||
const typeResults = await service.list()
|
||||
|
||||
expect(typeResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-1",
|
||||
value: "Type 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "type-2",
|
||||
value: "Type 2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("list product type by id", async () => {
|
||||
const typeResults = await service.list({ id: data[0].type.id })
|
||||
|
||||
expect(typeResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-1",
|
||||
value: "Type 1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("list product type by value matching string", async () => {
|
||||
const typeResults = await service.list({ value: "Type 1" })
|
||||
|
||||
expect(typeResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-1",
|
||||
value: "Type 1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("listAndCount", () => {
|
||||
it("should return product type and count", async () => {
|
||||
const [typeResults, count] = await service.listAndCount()
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(typeResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-1",
|
||||
value: "Type 1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "type-2",
|
||||
value: "Type 2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return product type and count when filtered", async () => {
|
||||
const [typeResults, count] = await service.listAndCount({ id: data[0].type.id })
|
||||
|
||||
expect(count).toEqual(1)
|
||||
expect(typeResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return product type and count when using skip and take", async () => {
|
||||
const [typeResults, count] = await service.listAndCount({}, { skip: 1, take: 1 })
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(typeResults).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-2",
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should return requested fields", async () => {
|
||||
const [typeResults, count] = await service.listAndCount({}, {
|
||||
take: 1,
|
||||
select: ["value"],
|
||||
})
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(typeResults))
|
||||
|
||||
expect(count).toEqual(2)
|
||||
expect(serialized).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "type-1",
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieve", () => {
|
||||
const typeId = "type-1"
|
||||
const typeValue = "Type 1"
|
||||
|
||||
it("should return type for the given id", async () => {
|
||||
const type = await service.retrieve(
|
||||
typeId,
|
||||
)
|
||||
|
||||
expect(type).toEqual(
|
||||
expect.objectContaining({
|
||||
id: typeId
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when type with id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieve("does-not-exist")
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductType with id: does-not-exist was not found')
|
||||
})
|
||||
|
||||
it("should throw an error when an id is not provided", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.retrieve(undefined as unknown as string)
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('"productTypeId" must be defined')
|
||||
})
|
||||
|
||||
it("should return type based on config select param", async () => {
|
||||
const type = await service.retrieve(
|
||||
typeId,
|
||||
{
|
||||
select: ["id", "value"],
|
||||
}
|
||||
)
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(type))
|
||||
|
||||
expect(serialized).toEqual(
|
||||
{
|
||||
id: typeId,
|
||||
value: typeValue,
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
const typeId = "type-1"
|
||||
|
||||
it("should delete the product type given an ID successfully", async () => {
|
||||
await service.delete(
|
||||
[typeId],
|
||||
)
|
||||
|
||||
const types = await service.list({
|
||||
id: typeId
|
||||
})
|
||||
|
||||
expect(types).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
const typeId = "type-1"
|
||||
|
||||
it("should update the value of the type successfully", async () => {
|
||||
await service.update(
|
||||
[{
|
||||
id: typeId,
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const productType = await service.retrieve(typeId)
|
||||
|
||||
expect(productType.value).toEqual("UK")
|
||||
})
|
||||
|
||||
it("should throw an error when an id does not exist", async () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.update([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
value: "UK"
|
||||
}
|
||||
])
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
expect(error.message).toEqual('ProductType with id "does-not-exist" not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("should create a type successfully", async () => {
|
||||
await service.create(
|
||||
[{
|
||||
value: "UK"
|
||||
}]
|
||||
)
|
||||
|
||||
const [productType] = await service.list({
|
||||
value: "UK"
|
||||
})
|
||||
|
||||
expect(productType.value).toEqual("UK")
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user