feat(medusa): Emit events on product category mutations (#3003)

* chore: added events on product category mutation

* chore: remove duplicates + refactor test
This commit is contained in:
Riqwan Thamir
2023-01-12 09:32:03 +01:00
committed by GitHub
parent 1dc79590b3
commit aef8421235
3 changed files with 118 additions and 20 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
feat(medusa): emit events on product category mutation

View File

@@ -1,5 +1,13 @@
import { IdMap, MockRepository, MockManager } from "medusa-test-utils"
import ProductCategoryService from "../product-category"
import { EventBusService } from "../"
const eventBusService = {
emit: jest.fn(),
withTransaction: function () {
return this
},
} as unknown as EventBusService
describe("ProductCategoryService", () => {
const validProdCategoryId = "skinny-jeans"
@@ -22,6 +30,7 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})
beforeEach(async () => { jest.clearAllMocks() })
@@ -65,6 +74,7 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})
beforeEach(async () => { jest.clearAllMocks() })
@@ -99,12 +109,15 @@ describe("ProductCategoryService", () => {
describe("create", () => {
const productCategoryRepository = MockRepository({
findOne: query => Promise.resolve({ id: IdMap.getId("jeans") }),
findOne: (query) => Promise.resolve({ id: IdMap.getId(validProdCategoryId) }),
create: () => Promise.resolve({ id: IdMap.getId(validProdCategoryId) }),
save: (record) => Promise.resolve(record),
})
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})
beforeEach(async () => {
@@ -112,13 +125,24 @@ describe("ProductCategoryService", () => {
})
it("successfully creates a product category", async () => {
await productCategoryService.create({ name: "jeans" })
await productCategoryService.create({ name: validProdCategoryId })
expect(productCategoryRepository.create).toHaveBeenCalledTimes(1)
expect(productCategoryRepository.create).toHaveBeenCalledWith({
name: "jeans",
name: validProdCategoryId,
})
})
it("emits a message on successful create", async () => {
await productCategoryService.create({ name: validProdCategoryId })
expect(eventBusService.emit).toHaveBeenCalledTimes(1)
expect(eventBusService.emit).toHaveBeenCalledWith(
"product-category.created", {
"id": IdMap.getId(validProdCategoryId)
}
)
})
})
describe("delete", () => {
@@ -138,7 +162,7 @@ describe("ProductCategoryService", () => {
}
return Promise.resolve({
id: IdMap.getId("jeans"),
id: IdMap.getId(validProdCategoryId),
category_children: []
})
},
@@ -150,17 +174,18 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})
beforeEach(async () => { jest.clearAllMocks() })
it("successfully deletes a product category", async () => {
const result = await productCategoryService.delete(
IdMap.getId("jeans")
IdMap.getId(validProdCategoryId)
)
expect(productCategoryRepository.delete).toBeCalledTimes(1)
expect(productCategoryRepository.delete).toBeCalledWith(IdMap.getId("jeans"))
expect(productCategoryRepository.delete).toBeCalledWith(IdMap.getId(validProdCategoryId))
})
it("returns without failure on not-found product category id", async () => {
@@ -179,6 +204,19 @@ describe("ProductCategoryService", () => {
`Deleting ProductCategory (with-children) with category children is not allowed`
)
})
it("emits a message on successful delete", async () => {
const result = await productCategoryService.delete(
IdMap.getId(validProdCategoryId)
)
expect(eventBusService.emit).toHaveBeenCalledTimes(1)
expect(eventBusService.emit).toHaveBeenCalledWith(
"product-category.deleted", {
"id": IdMap.getId(validProdCategoryId)
}
)
})
})
describe("update", () => {
@@ -198,6 +236,7 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})
beforeEach(async () => {
@@ -205,9 +244,11 @@ describe("ProductCategoryService", () => {
})
it("successfully updates a product category", async () => {
await productCategoryService.update(IdMap.getId(validProdCategoryId), {
name: "bathrobes",
})
await productCategoryService.update(
IdMap.getId(validProdCategoryId), {
name: "bathrobes",
}
)
expect(productCategoryRepository.save).toHaveBeenCalledTimes(1)
expect(productCategoryRepository.save).toHaveBeenCalledWith({
@@ -217,13 +258,30 @@ describe("ProductCategoryService", () => {
})
it("fails on not-found Id product category", async () => {
const error = await productCategoryService.update(IdMap.getId(invalidProdCategoryId), {
name: "bathrobes",
}).catch(e => e)
const error = await productCategoryService.update(
IdMap.getId(invalidProdCategoryId), {
name: "bathrobes",
}
).catch(e => e)
expect(error.message).toBe(
`ProductCategory with id: ${IdMap.getId(invalidProdCategoryId)} was not found`
)
})
it("emits a message on successful update", async () => {
const result = await productCategoryService.update(
IdMap.getId(validProdCategoryId), {
name: "bathrobes",
}
)
expect(eventBusService.emit).toHaveBeenCalledTimes(1)
expect(eventBusService.emit).toHaveBeenCalledWith(
"product-category.updated", {
"id": IdMap.getId(validProdCategoryId)
}
)
})
})
})

View File

@@ -5,6 +5,7 @@ import { ProductCategory } from "../models"
import { ProductCategoryRepository } from "../repositories/product-category"
import { FindConfig, Selector, QuerySelector } from "../types/common"
import { buildQuery } from "../utils"
import { EventBusService } from "."
import {
CreateProductCategoryInput,
UpdateProductCategoryInput,
@@ -12,6 +13,7 @@ import {
type InjectedDependencies = {
manager: EntityManager
eventBusService: EventBusService
productCategoryRepository: typeof ProductCategoryRepository
}
@@ -19,15 +21,27 @@ type InjectedDependencies = {
* Provides layer to manipulate product categories.
*/
class ProductCategoryService extends TransactionBaseService {
protected manager_: EntityManager
protected readonly productCategoryRepo_: typeof ProductCategoryRepository
protected readonly eventBusService_: EventBusService
protected transactionManager_: EntityManager | undefined
protected manager_: EntityManager
constructor({ manager, productCategoryRepository }: InjectedDependencies) {
static Events = {
CREATED: "product-category.created",
UPDATED: "product-category.updated",
DELETED: "product-category.deleted",
}
constructor({
manager,
productCategoryRepository,
eventBusService,
}: InjectedDependencies) {
// eslint-disable-next-line prefer-rest-params
super(arguments[0])
this.manager_ = manager
this.manager_ = manager
this.eventBusService_ = eventBusService
this.productCategoryRepo_ = productCategoryRepository
}
@@ -109,13 +123,20 @@ class ProductCategoryService extends TransactionBaseService {
* @return created product category
*/
async create(
productCategory: CreateProductCategoryInput
productCategoryInput: CreateProductCategoryInput
): Promise<ProductCategory> {
return await this.atomicPhase_(async (manager) => {
const pcRepo = manager.getCustomRepository(this.productCategoryRepo_)
const productCategoryRecord = pcRepo.create(productCategory)
let productCategory = pcRepo.create(productCategoryInput)
productCategory = await pcRepo.save(productCategory)
return await pcRepo.save(productCategoryRecord)
await this.eventBusService_
.withTransaction(manager)
.emit(ProductCategoryService.Events.CREATED, {
id: productCategory.id
})
return productCategory
})
}
@@ -134,7 +155,7 @@ class ProductCategoryService extends TransactionBaseService {
this.productCategoryRepo_
)
const productCategory = await this.retrieve(productCategoryId)
let productCategory = await this.retrieve(productCategoryId)
for (const key in productCategoryInput) {
if (isDefined(productCategoryInput[key])) {
@@ -142,7 +163,15 @@ class ProductCategoryService extends TransactionBaseService {
}
}
return await productCategoryRepo.save(productCategory)
productCategory = await productCategoryRepo.save(productCategory)
await this.eventBusService_
.withTransaction(manager)
.emit(ProductCategoryService.Events.UPDATED, {
id: productCategory.id,
})
return productCategory
})
}
@@ -173,6 +202,12 @@ class ProductCategoryService extends TransactionBaseService {
}
await productCategoryRepository.delete(productCategory.id)
await this.eventBusService_
.withTransaction(manager)
.emit(ProductCategoryService.Events.DELETED, {
id: productCategory.id
})
})
}
}