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:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(medusa): emit events on product category mutation
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
import { IdMap, MockRepository, MockManager } from "medusa-test-utils"
|
import { IdMap, MockRepository, MockManager } from "medusa-test-utils"
|
||||||
import ProductCategoryService from "../product-category"
|
import ProductCategoryService from "../product-category"
|
||||||
|
import { EventBusService } from "../"
|
||||||
|
|
||||||
|
const eventBusService = {
|
||||||
|
emit: jest.fn(),
|
||||||
|
withTransaction: function () {
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
} as unknown as EventBusService
|
||||||
|
|
||||||
describe("ProductCategoryService", () => {
|
describe("ProductCategoryService", () => {
|
||||||
const validProdCategoryId = "skinny-jeans"
|
const validProdCategoryId = "skinny-jeans"
|
||||||
@@ -22,6 +30,7 @@ describe("ProductCategoryService", () => {
|
|||||||
const productCategoryService = new ProductCategoryService({
|
const productCategoryService = new ProductCategoryService({
|
||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
productCategoryRepository,
|
productCategoryRepository,
|
||||||
|
eventBusService,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => { jest.clearAllMocks() })
|
beforeEach(async () => { jest.clearAllMocks() })
|
||||||
@@ -65,6 +74,7 @@ describe("ProductCategoryService", () => {
|
|||||||
const productCategoryService = new ProductCategoryService({
|
const productCategoryService = new ProductCategoryService({
|
||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
productCategoryRepository,
|
productCategoryRepository,
|
||||||
|
eventBusService,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => { jest.clearAllMocks() })
|
beforeEach(async () => { jest.clearAllMocks() })
|
||||||
@@ -99,12 +109,15 @@ describe("ProductCategoryService", () => {
|
|||||||
|
|
||||||
describe("create", () => {
|
describe("create", () => {
|
||||||
const productCategoryRepository = MockRepository({
|
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({
|
const productCategoryService = new ProductCategoryService({
|
||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
productCategoryRepository,
|
productCategoryRepository,
|
||||||
|
eventBusService,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -112,13 +125,24 @@ describe("ProductCategoryService", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("successfully creates a product category", async () => {
|
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).toHaveBeenCalledTimes(1)
|
||||||
expect(productCategoryRepository.create).toHaveBeenCalledWith({
|
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", () => {
|
describe("delete", () => {
|
||||||
@@ -138,7 +162,7 @@ describe("ProductCategoryService", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
id: IdMap.getId("jeans"),
|
id: IdMap.getId(validProdCategoryId),
|
||||||
category_children: []
|
category_children: []
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -150,17 +174,18 @@ describe("ProductCategoryService", () => {
|
|||||||
const productCategoryService = new ProductCategoryService({
|
const productCategoryService = new ProductCategoryService({
|
||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
productCategoryRepository,
|
productCategoryRepository,
|
||||||
|
eventBusService,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => { jest.clearAllMocks() })
|
beforeEach(async () => { jest.clearAllMocks() })
|
||||||
|
|
||||||
it("successfully deletes a product category", async () => {
|
it("successfully deletes a product category", async () => {
|
||||||
const result = await productCategoryService.delete(
|
const result = await productCategoryService.delete(
|
||||||
IdMap.getId("jeans")
|
IdMap.getId(validProdCategoryId)
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(productCategoryRepository.delete).toBeCalledTimes(1)
|
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 () => {
|
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`
|
`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", () => {
|
describe("update", () => {
|
||||||
@@ -198,6 +236,7 @@ describe("ProductCategoryService", () => {
|
|||||||
const productCategoryService = new ProductCategoryService({
|
const productCategoryService = new ProductCategoryService({
|
||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
productCategoryRepository,
|
productCategoryRepository,
|
||||||
|
eventBusService,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -205,9 +244,11 @@ describe("ProductCategoryService", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("successfully updates a product category", async () => {
|
it("successfully updates a product category", async () => {
|
||||||
await productCategoryService.update(IdMap.getId(validProdCategoryId), {
|
await productCategoryService.update(
|
||||||
name: "bathrobes",
|
IdMap.getId(validProdCategoryId), {
|
||||||
})
|
name: "bathrobes",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(productCategoryRepository.save).toHaveBeenCalledTimes(1)
|
expect(productCategoryRepository.save).toHaveBeenCalledTimes(1)
|
||||||
expect(productCategoryRepository.save).toHaveBeenCalledWith({
|
expect(productCategoryRepository.save).toHaveBeenCalledWith({
|
||||||
@@ -217,13 +258,30 @@ describe("ProductCategoryService", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("fails on not-found Id product category", async () => {
|
it("fails on not-found Id product category", async () => {
|
||||||
const error = await productCategoryService.update(IdMap.getId(invalidProdCategoryId), {
|
const error = await productCategoryService.update(
|
||||||
name: "bathrobes",
|
IdMap.getId(invalidProdCategoryId), {
|
||||||
}).catch(e => e)
|
name: "bathrobes",
|
||||||
|
}
|
||||||
|
).catch(e => e)
|
||||||
|
|
||||||
expect(error.message).toBe(
|
expect(error.message).toBe(
|
||||||
`ProductCategory with id: ${IdMap.getId(invalidProdCategoryId)} was not found`
|
`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)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ProductCategory } from "../models"
|
|||||||
import { ProductCategoryRepository } from "../repositories/product-category"
|
import { ProductCategoryRepository } from "../repositories/product-category"
|
||||||
import { FindConfig, Selector, QuerySelector } from "../types/common"
|
import { FindConfig, Selector, QuerySelector } from "../types/common"
|
||||||
import { buildQuery } from "../utils"
|
import { buildQuery } from "../utils"
|
||||||
|
import { EventBusService } from "."
|
||||||
import {
|
import {
|
||||||
CreateProductCategoryInput,
|
CreateProductCategoryInput,
|
||||||
UpdateProductCategoryInput,
|
UpdateProductCategoryInput,
|
||||||
@@ -12,6 +13,7 @@ import {
|
|||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
manager: EntityManager
|
manager: EntityManager
|
||||||
|
eventBusService: EventBusService
|
||||||
productCategoryRepository: typeof ProductCategoryRepository
|
productCategoryRepository: typeof ProductCategoryRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,15 +21,27 @@ type InjectedDependencies = {
|
|||||||
* Provides layer to manipulate product categories.
|
* Provides layer to manipulate product categories.
|
||||||
*/
|
*/
|
||||||
class ProductCategoryService extends TransactionBaseService {
|
class ProductCategoryService extends TransactionBaseService {
|
||||||
protected manager_: EntityManager
|
|
||||||
protected readonly productCategoryRepo_: typeof ProductCategoryRepository
|
protected readonly productCategoryRepo_: typeof ProductCategoryRepository
|
||||||
|
protected readonly eventBusService_: EventBusService
|
||||||
protected transactionManager_: EntityManager | undefined
|
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
|
// eslint-disable-next-line prefer-rest-params
|
||||||
super(arguments[0])
|
super(arguments[0])
|
||||||
this.manager_ = manager
|
|
||||||
|
|
||||||
|
this.manager_ = manager
|
||||||
|
this.eventBusService_ = eventBusService
|
||||||
this.productCategoryRepo_ = productCategoryRepository
|
this.productCategoryRepo_ = productCategoryRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,13 +123,20 @@ class ProductCategoryService extends TransactionBaseService {
|
|||||||
* @return created product category
|
* @return created product category
|
||||||
*/
|
*/
|
||||||
async create(
|
async create(
|
||||||
productCategory: CreateProductCategoryInput
|
productCategoryInput: CreateProductCategoryInput
|
||||||
): Promise<ProductCategory> {
|
): Promise<ProductCategory> {
|
||||||
return await this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const pcRepo = manager.getCustomRepository(this.productCategoryRepo_)
|
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_
|
this.productCategoryRepo_
|
||||||
)
|
)
|
||||||
|
|
||||||
const productCategory = await this.retrieve(productCategoryId)
|
let productCategory = await this.retrieve(productCategoryId)
|
||||||
|
|
||||||
for (const key in productCategoryInput) {
|
for (const key in productCategoryInput) {
|
||||||
if (isDefined(productCategoryInput[key])) {
|
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 productCategoryRepository.delete(productCategory.id)
|
||||||
|
|
||||||
|
await this.eventBusService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(ProductCategoryService.Events.DELETED, {
|
||||||
|
id: productCategory.id
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user