From 4b80ba8a356806da3c92634e40e8946da25e35ee Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Wed, 2 Aug 2023 13:44:53 +0200 Subject: [PATCH] fix(product, integration-tests): Fix integration tests (#4674) * fix(product, integration-tests): Fix integration tests * improve test * Create dirty-eagles-shop.md --- .changeset/dirty-eagles-shop.md | 6 + .../plugins/__tests__/product/admin/index.ts | 14 +- integration-tests/plugins/medusa-config.js | 9 +- packages/modules-sdk/src/definitions.ts | 127 +++++++++--------- .../src/services/product-module-service.ts | 115 +++++++++------- 5 files changed, 158 insertions(+), 113 deletions(-) create mode 100644 .changeset/dirty-eagles-shop.md diff --git a/.changeset/dirty-eagles-shop.md b/.changeset/dirty-eagles-shop.md new file mode 100644 index 0000000000..9c98058467 --- /dev/null +++ b/.changeset/dirty-eagles-shop.md @@ -0,0 +1,6 @@ +--- +"@medusajs/modules-sdk": patch +"@medusajs/product": patch +--- + +fix(product, integration-tests): Fix integration tests diff --git a/integration-tests/plugins/__tests__/product/admin/index.ts b/integration-tests/plugins/__tests__/product/admin/index.ts index aeab952e3a..17af7f87b4 100644 --- a/integration-tests/plugins/__tests__/product/admin/index.ts +++ b/integration-tests/plugins/__tests__/product/admin/index.ts @@ -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) diff --git a/integration-tests/plugins/medusa-config.js b/integration-tests/plugins/medusa-config.js index 59ec9bed54..bd0b5b268b 100644 --- a/integration-tests/plugins/medusa-config.js +++ b/integration-tests/plugins/medusa-config.js @@ -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", diff --git a/packages/modules-sdk/src/definitions.ts b/packages/modules-sdk/src/definitions.ts index 35cba19fc9..742c17d0da 100644 --- a/packages/modules-sdk/src/definitions.ts +++ b/packages/modules-sdk/src/definitions.ts @@ -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) diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index 8309135396..b6282534b4 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -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 = {}, @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 { + async create( + data: ProductTypes.CreateProductDTO[], + sharedContext?: Context + ): Promise { const products = await this.create_(data, sharedContext) return this.baseRepository_.serialize(products, { @@ -613,9 +619,7 @@ export default class ProductModuleService< ): Promise { const products = await this.update_(data, sharedContext) - return this.baseRepository_.serialize< - ProductTypes.ProductDTO[] - >(products, { + return this.baseRepository_.serialize(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 { - 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( 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 } }