From 9576de2be401f1dd3b4042291df9dbfa768af6d7 Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Thu, 6 Jun 2024 17:14:40 +0200 Subject: [PATCH] feat: emit product tags events (#7636) **What** emit product tags events **note** Stil does not take into consideration non overriden method, delete and soft delete emits event under the hood and we will have to migrate that at the end --- .../product-tags.spec.ts | 104 +++++++++++++++++- .../src/services/product-module-service.ts | 21 ++++ 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/packages/modules/product/integration-tests/__tests__/product-module-service/product-tags.spec.ts b/packages/modules/product/integration-tests/__tests__/product-module-service/product-tags.spec.ts index f825a570b0..87a8dc38fe 100644 --- a/packages/modules/product/integration-tests/__tests__/product-module-service/product-tags.spec.ts +++ b/packages/modules/product/integration-tests/__tests__/product-module-service/product-tags.spec.ts @@ -1,14 +1,32 @@ import { Modules } from "@medusajs/modules-sdk" import { IProductModuleService } from "@medusajs/types" -import { ProductStatus } from "@medusajs/utils" +import { + CommonEvents, + composeMessage, + ProductEvents, + ProductStatus, +} from "@medusajs/utils" import { Product, ProductTag } from "@models" -import { moduleIntegrationTestRunner } from "medusa-test-utils" +import { + MockEventBusService, + moduleIntegrationTestRunner, +} from "medusa-test-utils" jest.setTimeout(30000) moduleIntegrationTestRunner({ moduleName: Modules.PRODUCT, testSuite: ({ MikroOrmWrapper, service }) => { + let eventBusEmitSpy + + beforeEach(() => { + eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit") + }) + + afterEach(() => { + jest.clearAllMocks() + }) + describe("ProductModuleService product tags", () => { let tagOne: ProductTag let tagTwo: ProductTag @@ -255,6 +273,16 @@ moduleIntegrationTestRunner({ const productTag = await service.retrieveTag(tagId) expect(productTag.value).toEqual("UK") + + expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1) + expect(eventBusEmitSpy).toHaveBeenCalledWith([ + composeMessage(ProductEvents.product_tag_updated, { + data: { id: productTag.id }, + object: "product_tag", + service: Modules.PRODUCT, + action: CommonEvents.UPDATED, + }), + ]) }) it("should throw an error when an id does not exist", async () => { @@ -276,7 +304,7 @@ moduleIntegrationTestRunner({ describe("createTags", () => { it("should create a tag successfully", async () => { - const res = await service.createTags([ + await service.createTags([ { value: "UK", }, @@ -287,6 +315,76 @@ moduleIntegrationTestRunner({ }) expect(productTag[0]?.value).toEqual("UK") + + expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1) + expect(eventBusEmitSpy).toHaveBeenCalledWith([ + composeMessage(ProductEvents.product_tag_created, { + data: { id: productTag[0].id }, + object: "product_tag", + service: Modules.PRODUCT, + action: CommonEvents.CREATED, + }), + ]) + }) + }) + + describe("upsertTags", () => { + it("should upsert tags successfully", async () => { + await service.createTags([ + { + value: "UK", + }, + ]) + + let productTags = await service.listTags({ + value: "UK", + }) + + const tagsData = [ + { + ...productTags[0], + value: "updated", + }, + { + value: "new", + }, + ] + + jest.clearAllMocks() + + await service.upsertTags(tagsData) + + productTags = await service.listTags() + + expect(productTags).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + value: "updated", + }), + expect.objectContaining({ + value: "new", + }), + ]) + ) + + const newTag = productTags.find((t) => t.value === "new")! + const updatedTag = productTags.find((t) => t.value === "updated")! + + expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2) + expect(eventBusEmitSpy).toHaveBeenCalledWith([ + composeMessage(ProductEvents.product_tag_created, { + data: { id: newTag.id }, + object: "product_tag", + service: Modules.PRODUCT, + action: CommonEvents.CREATED, + }), + composeMessage(ProductEvents.product_tag_updated, { + data: { id: updatedTag.id }, + object: "product_tag", + service: Modules.PRODUCT, + action: CommonEvents.UPDATED, + }), + ]) }) }) }) diff --git a/packages/modules/product/src/services/product-module-service.ts b/packages/modules/product/src/services/product-module-service.ts index 5f1f84cced..df083d8ec3 100644 --- a/packages/modules/product/src/services/product-module-service.ts +++ b/packages/modules/product/src/services/product-module-service.ts @@ -422,6 +422,7 @@ export default class ProductModuleService< ): Promise @InjectManager("baseRepository_") + @EmitEvents() async createTags( data: ProductTypes.CreateProductTagDTO[] | ProductTypes.CreateProductTagDTO, @MedusaContext() sharedContext: Context = {} @@ -434,6 +435,11 @@ export default class ProductModuleService< ProductTypes.ProductTagDTO[] >(tags) + eventBuilders.createdProductTag({ + data: createdTags, + sharedContext, + }) + return Array.isArray(data) ? createdTags : createdTags[0] } @@ -447,6 +453,7 @@ export default class ProductModuleService< ): Promise @InjectTransactionManager("baseRepository_") + @EmitEvents() async upsertTags( data: ProductTypes.UpsertProductTagDTO[] | ProductTypes.UpsertProductTagDTO, @MedusaContext() sharedContext: Context = {} @@ -462,9 +469,17 @@ export default class ProductModuleService< if (forCreate.length) { created = await this.productTagService_.create(forCreate, sharedContext) + eventBuilders.createdProductTag({ + data: created, + sharedContext, + }) } if (forUpdate.length) { updated = await this.productTagService_.update(forUpdate, sharedContext) + eventBuilders.updatedProductTag({ + data: updated, + sharedContext, + }) } const result = [...created, ...updated] @@ -487,6 +502,7 @@ export default class ProductModuleService< ): Promise @InjectManager("baseRepository_") + @EmitEvents() async updateTags( idOrSelector: string | ProductTypes.FilterableProductTagProps, data: ProductTypes.UpdateProductTagDTO, @@ -519,6 +535,11 @@ export default class ProductModuleService< ProductTypes.ProductTagDTO[] >(tags) + eventBuilders.updatedProductTag({ + data: updatedTags, + sharedContext, + }) + return isString(idOrSelector) ? updatedTags[0] : updatedTags }