fix(product, integration-tests): Fix integration tests (#4674)

* fix(product, integration-tests): Fix integration tests

* improve test

* Create dirty-eagles-shop.md
This commit is contained in:
Adrien de Peretti
2023-08-02 13:44:53 +02:00
committed by GitHub
parent 7f1421c218
commit 4b80ba8a35
5 changed files with 158 additions and 113 deletions

View File

@@ -0,0 +1,6 @@
---
"@medusajs/modules-sdk": patch
"@medusajs/product": patch
---
fix(product, integration-tests): Fix integration tests

View File

@@ -8,6 +8,7 @@ import productSeeder from "../../../../helpers/product-seeder"
import { simpleSalesChannelFactory } from "../../../../factories"
import { AxiosInstance } from "axios"
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
jest.setTimeout(50000)
@@ -21,11 +22,14 @@ describe("/admin/products", () => {
let medusaProcess
let dbConnection
let express
let medusaContainer
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd } as any)
const { app, port } = await bootstrapApp({ cwd })
const { app, port, container } = await bootstrapApp({ cwd })
medusaContainer = container
setPort(port)
express = app.listen(port, () => {
process.send?.(port)
@@ -39,6 +43,14 @@ describe("/admin/products", () => {
medusaProcess.kill()
})
it("Should have loaded the product module", function () {
const productRegistrationName =
ModulesDefinition[Modules.PRODUCT].registrationName
expect(
medusaContainer.hasRegistration(productRegistrationName)
).toBeTruthy()
})
describe("POST /admin/products", () => {
beforeEach(async () => {
await productSeeder(dbConnection)

View File

@@ -1,3 +1,4 @@
const { Modules } = require("@medusajs/modules-sdk")
const DB_HOST = process.env.DB_HOST
const DB_USERNAME = process.env.DB_USERNAME
const DB_PASSWORD = process.env.DB_PASSWORD
@@ -31,21 +32,21 @@ module.exports = {
database_extra: { idle_in_transaction_session_timeout: 0 },
},
modules: {
stockLocationService: {
[Modules.STOCK_LOCATION]: {
scope: "internal",
resources: "shared",
resolve: "@medusajs/stock-location",
},
inventoryService: {
[Modules.INVENTORY]: {
scope: "internal",
resources: "shared",
resolve: "@medusajs/inventory",
},
cacheService: {
[Modules.CACHE]: {
resolve: "@medusajs/cache-inmemory",
options: { ttl: 5 },
},
productModuleService: {
[Modules.PRODUCT]: {
scope: "internal",
resources: "shared",
resolve: "@medusajs/product",

View File

@@ -12,74 +12,75 @@ export enum Modules {
PRODUCT = "productService",
}
export const ModulesDefinition: { [key: string]: ModuleDefinition } = {
[Modules.EVENT_BUS]: {
key: Modules.EVENT_BUS,
registrationName: "eventBusModuleService",
defaultPackage: "@medusajs/event-bus-local",
label: "EventBusModuleService",
canOverride: true,
isRequired: true,
dependencies: ["logger"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
{
[Modules.EVENT_BUS]: {
key: Modules.EVENT_BUS,
registrationName: "eventBusModuleService",
defaultPackage: "@medusajs/event-bus-local",
label: "EventBusModuleService",
canOverride: true,
isRequired: true,
dependencies: ["logger"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
},
[Modules.STOCK_LOCATION]: {
key: Modules.STOCK_LOCATION,
registrationName: "stockLocationService",
defaultPackage: false,
label: "StockLocationService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: ["eventBusService"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
[Modules.STOCK_LOCATION]: {
key: Modules.STOCK_LOCATION,
registrationName: "stockLocationService",
defaultPackage: false,
label: "StockLocationService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: ["eventBusService"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
},
[Modules.INVENTORY]: {
key: Modules.INVENTORY,
registrationName: "inventoryService",
defaultPackage: false,
label: "InventoryService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: ["eventBusService"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
[Modules.INVENTORY]: {
key: Modules.INVENTORY,
registrationName: "inventoryService",
defaultPackage: false,
label: "InventoryService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: ["eventBusService"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
},
[Modules.CACHE]: {
key: Modules.CACHE,
registrationName: "cacheService",
defaultPackage: "@medusajs/cache-inmemory",
label: "CacheService",
isRequired: true,
canOverride: true,
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
[Modules.CACHE]: {
key: Modules.CACHE,
registrationName: "cacheService",
defaultPackage: "@medusajs/cache-inmemory",
label: "CacheService",
isRequired: true,
canOverride: true,
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
},
[Modules.PRODUCT]: {
key: Modules.PRODUCT,
registrationName: "productModuleService",
defaultPackage: false,
label: "ProductModuleService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: [],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.EXTERNAL,
[Modules.PRODUCT]: {
key: Modules.PRODUCT,
registrationName: "productModuleService",
defaultPackage: false,
label: "ProductModuleService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: [],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.EXTERNAL,
},
},
},
}
}
export const MODULE_DEFINITIONS: ModuleDefinition[] =
Object.values(ModulesDefinition)

View File

@@ -26,10 +26,12 @@ import {
JoinerServiceConfig,
ProductTypes,
} from "@medusajs/types"
import { serialize } from "@mikro-orm/core"
import ProductImageService from "./product-image"
import { ProductServiceTypes, ProductVariantServiceTypes } from "../types/services"
import {
ProductServiceTypes,
ProductVariantServiceTypes,
} from "../types/services"
import {
InjectManager,
InjectTransactionManager,
@@ -393,11 +395,12 @@ export default class ProductModuleService<
config: FindConfig<ProductTypes.ProductOptionDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[ProductTypes.ProductOptionDTO[], number]> {
const [productOptions, count] = await this.productOptionService_.listAndCount(
filters,
config,
sharedContext
)
const [productOptions, count] =
await this.productOptionService_.listAndCount(
filters,
config,
sharedContext
)
return [JSON.parse(JSON.stringify(productOptions)), count]
}
@@ -599,7 +602,10 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(categories))
}
async create(data: ProductTypes.CreateProductDTO[], sharedContext?: Context): Promise<ProductTypes.ProductDTO[]> {
async create(
data: ProductTypes.CreateProductDTO[],
sharedContext?: Context
): Promise<ProductTypes.ProductDTO[]> {
const products = await this.create_(data, sharedContext)
return this.baseRepository_.serialize<ProductTypes.ProductDTO[]>(products, {
@@ -613,9 +619,7 @@ export default class ProductModuleService<
): Promise<ProductTypes.ProductDTO[]> {
const products = await this.update_(data, sharedContext)
return this.baseRepository_.serialize<
ProductTypes.ProductDTO[]
>(products, {
return this.baseRepository_.serialize<ProductTypes.ProductDTO[]>(products, {
populate: true,
})
}
@@ -659,9 +663,18 @@ export default class ProductModuleService<
productData.discountable = false
}
await this.upsertAndAssignImagesToProductData(productData, sharedContext)
await this.upsertAndAssignProductTagsToProductData(productData, sharedContext)
await this.upsertAndAssignProductTypeToProductData(productData, sharedContext)
await this.upsertAndAssignImagesToProductData(
productData,
sharedContext
)
await this.upsertAndAssignProductTagsToProductData(
productData,
sharedContext
)
await this.upsertAndAssignProductTypeToProductData(
productData,
sharedContext
)
return productData as CreateProductOnlyDTO
})
@@ -679,7 +692,9 @@ export default class ProductModuleService<
const productOptionsData = [...productOptionsMap]
.map(([handle, options]) => {
return options.map((option) => {
const productOptionsData: ProductTypes.CreateProductOptionOnlyDTO = { ...option }
const productOptionsData: ProductTypes.CreateProductOptionOnlyDTO = {
...option,
}
const product = productByHandleMap.get(handle)
const productId = product?.id!
@@ -729,31 +744,29 @@ export default class ProductModuleService<
data: ProductTypes.UpdateProductDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TProduct[]> {
const productIds = data.map(pd => pd.id)
const productIds = data.map((pd) => pd.id)
const existingProductVariants = await this.productVariantService_.list(
{ product_id: productIds },
{},
sharedContext
)
const existingProductVariantsMap = new Map<
string,
ProductVariant[]
>(
const existingProductVariantsMap = new Map<string, ProductVariant[]>(
data.map((productData) => {
const productVariantsForProduct = existingProductVariants
.filter((variant) => variant.product_id === productData.id)
const productVariantsForProduct = existingProductVariants.filter(
(variant) => variant.product_id === productData.id
)
return [
productData.id,
productVariantsForProduct,
]
return [productData.id, productVariantsForProduct]
})
)
const productVariantsMap = new Map<
string,
(ProductTypes.CreateProductVariantDTO | ProductTypes.UpdateProductVariantDTO)[]
(
| ProductTypes.CreateProductVariantDTO
| ProductTypes.UpdateProductVariantDTO
)[]
>()
const productOptionsMap = new Map<
@@ -779,9 +792,18 @@ export default class ProductModuleService<
productData.discountable = false
}
await this.upsertAndAssignImagesToProductData(productData, sharedContext)
await this.upsertAndAssignProductTagsToProductData(productData, sharedContext)
await this.upsertAndAssignProductTypeToProductData(productData, sharedContext)
await this.upsertAndAssignImagesToProductData(
productData,
sharedContext
)
await this.upsertAndAssignProductTagsToProductData(
productData,
sharedContext
)
await this.upsertAndAssignProductTypeToProductData(
productData,
sharedContext
)
return productData as ProductServiceTypes.UpdateProductDTO
})
@@ -797,10 +819,12 @@ export default class ProductModuleService<
)
const productOptionsData = [...productOptionsMap]
.map(([id, options]) => options.map((option) => ({
...option,
product: productByIdMap.get(id)!,
})))
.map(([id, options]) =>
options.map((option) => ({
...option,
product: productByIdMap.get(id)!,
}))
)
.flat()
const productOptions = await this.productOptionService_.create(
@@ -825,7 +849,7 @@ export default class ProductModuleService<
const existingVariants = existingProductVariantsMap.get(productId)
variants.forEach((variant) => {
const isVariantIdDefined = ("id" in variant) && isDefined(variant.id)
const isVariantIdDefined = "id" in variant && isDefined(variant.id)
if (isVariantIdDefined) {
variantsToUpdate.push(variant as ProductTypes.UpdateProductVariantDTO)
@@ -849,13 +873,13 @@ export default class ProductModuleService<
productVariantsToCreateMap.set(productId, variantsToCreate)
productVariantsToUpdateMap.set(productId, variantsToUpdate)
const variantsToUpdateIds = variantsToUpdate.map(v => v?.id) as string[]
const existingVariantIds = existingVariants?.map(v => v.id) || []
const variantsToUpdateIds = variantsToUpdate.map((v) => v?.id) as string[]
const existingVariantIds = existingVariants?.map((v) => v.id) || []
const variantsToUpdateSet = new Set(variantsToUpdateIds)
productVariantIdsToDelete.push(
...new Set(
existingVariantIds.filter(x => !variantsToUpdateSet.has(x))
existingVariantIds.filter((x) => !variantsToUpdateSet.has(x))
)
)
}
@@ -884,7 +908,10 @@ export default class ProductModuleService<
if (productVariantIdsToDelete.length) {
promises.push(
this.productVariantService_.delete(productVariantIdsToDelete, sharedContext)
this.productVariantService_.delete(
productVariantIdsToDelete,
sharedContext
)
)
}
@@ -930,14 +957,12 @@ export default class ProductModuleService<
sharedContext: Context = {}
) {
if (isDefined(productData.type)) {
const productType = (
await this.productTypeService_.upsert(
[productData.type],
sharedContext
)
const productType = await this.productTypeService_.upsert(
[productData.type],
sharedContext
)
productData.type_id = productType?.[0]?.id
productData.type = productType?.[0] as ProductTypes.CreateProductTypeDTO
}
}