Skip to content

Commit

Permalink
Merge branch 'develop' into chore/oas-response-schema-AtoC
Browse files Browse the repository at this point in the history
  • Loading branch information
olivermrbl authored Jan 12, 2023
2 parents 3ca6e7f + aef8421 commit e7be6ba
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-bulldogs-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---

feat(medusa): emit events on product category mutation
82 changes: 70 additions & 12 deletions packages/medusa/src/services/__tests__/product-category.ts
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -22,6 +30,7 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})

beforeEach(async () => { jest.clearAllMocks() })
Expand Down Expand Up @@ -65,6 +74,7 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})

beforeEach(async () => { jest.clearAllMocks() })
Expand Down Expand Up @@ -99,26 +109,40 @@ 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 () => {
jest.clearAllMocks()
})

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", () => {
Expand All @@ -138,7 +162,7 @@ describe("ProductCategoryService", () => {
}

return Promise.resolve({
id: IdMap.getId("jeans"),
id: IdMap.getId(validProdCategoryId),
category_children: []
})
},
Expand All @@ -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 () => {
Expand All @@ -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", () => {
Expand All @@ -198,16 +236,19 @@ describe("ProductCategoryService", () => {
const productCategoryService = new ProductCategoryService({
manager: MockManager,
productCategoryRepository,
eventBusService,
})

beforeEach(async () => {
jest.clearAllMocks()
})

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({
Expand All @@ -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)
}
)
})
})
})
51 changes: 43 additions & 8 deletions packages/medusa/src/services/product-category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,43 @@ 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,
} from "../types/product-category"

type InjectedDependencies = {
manager: EntityManager
eventBusService: EventBusService
productCategoryRepository: typeof ProductCategoryRepository
}

/**
* 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
}

Expand Down Expand Up @@ -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)

await this.eventBusService_
.withTransaction(manager)
.emit(ProductCategoryService.Events.CREATED, {
id: productCategory.id
})

return await pcRepo.save(productCategoryRecord)
return productCategory
})
}

Expand All @@ -134,15 +155,23 @@ 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])) {
productCategory[key] = productCategoryInput[key]
}
}

return await productCategoryRepo.save(productCategory)
productCategory = await productCategoryRepo.save(productCategory)

await this.eventBusService_
.withTransaction(manager)
.emit(ProductCategoryService.Events.UPDATED, {
id: productCategory.id,
})

return productCategory
})
}

Expand Down Expand Up @@ -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
})
})
}
}
Expand Down

0 comments on commit e7be6ba

Please sign in to comment.