feat: Event emitting part 1/N (Fulfillment) (#7391)

**What**
Add support for event emitting in the fulfillment module

**NOTE**
It does not include the review of the events for the abstract module factory if the method is not implemented in the module itself and rely on the default implementation
This commit is contained in:
Adrien de Peretti
2024-06-03 08:29:35 +00:00
committed by GitHub
parent 28d2a5347a
commit 9608bf06ef
29 changed files with 1716 additions and 348 deletions
@@ -7,15 +7,15 @@ import {
UpdateFulfillmentSetDTO,
} from "@medusajs/types"
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { moduleIntegrationTestRunner } from "medusa-test-utils"
import { MockEventBusService } from "medusa-test-utils/dist"
import { buildExpectedEventMessageShape } from "../../__fixtures__"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IFulfillmentModuleService>({
moduleName: Modules.FULFILLMENT,
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
@@ -625,6 +625,15 @@ moduleIntegrationTestRunner({
type: updateData.type,
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.updated,
action: "updated",
object: "fulfillment_set",
data: { id: updatedFulfillmentSets.id },
}),
])
})
it("should update a collection of fulfillment sets", async function () {
@@ -655,6 +664,7 @@ moduleIntegrationTestRunner({
})
expect(updatedFulfillmentSets).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(2)
for (const data_ of updateData) {
const currentFullfillmentSet = fullfillmentSets.find(
@@ -668,6 +678,17 @@ moduleIntegrationTestRunner({
type: data_.type,
})
)
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.updated,
action: "updated",
object: "fulfillment_set",
data: { id: currentFullfillmentSet.id },
}),
])
)
}
})
@@ -742,6 +763,46 @@ moduleIntegrationTestRunner({
id: updatedFulfillmentSet.service_zones[0].id,
})
)
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(5)
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.updated,
action: "updated",
object: "fulfillment_set",
data: { id: updatedFulfillmentSet.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_created,
action: "created",
object: "service_zone",
data: { id: updatedFulfillmentSet.service_zones[0].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: {
id: updatedFulfillmentSet.service_zones[0].geo_zones[0].id,
},
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_deleted,
action: "deleted",
object: "service_zone",
data: { id: createdFulfillmentSet.service_zones[0].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_deleted,
action: "deleted",
object: "geo_zone",
data: {
id: createdFulfillmentSet.service_zones[0].geo_zones[0].id,
},
}),
])
)
})
it("should update an existing fulfillment set and add a new service zone", async function () {
@@ -812,6 +873,36 @@ moduleIntegrationTestRunner({
]),
})
)
const createdServiceZone = updatedFulfillmentSet.service_zones.find(
(s) => s.name === "service-zone-test2"
)
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(3)
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.updated,
action: "updated",
object: "fulfillment_set",
data: { id: updatedFulfillmentSet.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_created,
action: "created",
object: "service_zone",
data: { id: createdServiceZone.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: {
id: createdServiceZone.geo_zones[0].id,
},
}),
])
)
})
it("should fail on duplicated fulfillment set name", async function () {
@@ -897,11 +988,16 @@ moduleIntegrationTestRunner({
const updatedFulfillmentSets = await service.update(updateData)
expect(updatedFulfillmentSets).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(10)
for (const data_ of updateData) {
const expectedFulfillmentSet = updatedFulfillmentSets.find(
(f) => f.id === data_.id
)
const originalFulfillmentSet = createdFulfillmentSets.find(
(f) => f.id === data_.id
)
expect(expectedFulfillmentSet).toEqual(
expect.objectContaining({
id: data_.id,
@@ -925,6 +1021,47 @@ moduleIntegrationTestRunner({
]),
})
)
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.updated,
action: "updated",
object: "fulfillment_set",
data: { id: expectedFulfillmentSet.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_created,
action: "created",
object: "service_zone",
data: { id: expectedFulfillmentSet.service_zones[0].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: {
id: expectedFulfillmentSet.service_zones[0].geo_zones[0]
.id,
},
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_deleted,
action: "deleted",
object: "service_zone",
data: { id: originalFulfillmentSet.service_zones[0].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_deleted,
action: "deleted",
object: "geo_zone",
data: {
id: originalFulfillmentSet.service_zones[0].geo_zones[0]
.id,
},
}),
])
)
}
const serviceZones = await service.listServiceZones()
@@ -1002,6 +1139,7 @@ moduleIntegrationTestRunner({
const updatedFulfillmentSets = await service.update(updateData)
expect(updatedFulfillmentSets).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(6)
for (const data_ of updateData) {
const expectedFulfillmentSet = updatedFulfillmentSets.find(
@@ -1033,6 +1171,36 @@ moduleIntegrationTestRunner({
]),
})
)
const createdServiceZone =
expectedFulfillmentSet.service_zones.find((s) =>
s.name.includes(`added-service-zone-test`)
)
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.updated,
action: "updated",
object: "fulfillment_set",
data: { id: expectedFulfillmentSet.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_created,
action: "created",
object: "service_zone",
data: { id: createdServiceZone.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: {
id: createdServiceZone.geo_zones[0].id,
},
}),
])
)
}
const serviceZones = await service.listServiceZones()
@@ -1,11 +1,19 @@
import { resolve } from "path"
import { Modules } from "@medusajs/modules-sdk"
import { IFulfillmentModuleService } from "@medusajs/types"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import {
IFulfillmentModuleService,
UpdateFulfillmentDTO,
} from "@medusajs/types"
import {
MockEventBusService,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import {
buildExpectedEventMessageShape,
generateCreateFulfillmentData,
generateCreateShippingOptionsData,
} from "../../__fixtures__"
import { FulfillmentEvents } from "@medusajs/utils"
jest.setTimeout(100000)
@@ -27,10 +35,20 @@ const moduleOptions = {
const providerId = "fixtures-fulfillment-provider_test-provider"
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IFulfillmentModuleService>({
moduleName: Modules.FULFILLMENT,
moduleOptions: moduleOptions,
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
})
afterEach(() => {
jest.clearAllMocks()
})
describe("Fulfillment Module Service", () => {
describe("read", () => {
it("should list fulfillment", async () => {
@@ -103,6 +121,8 @@ moduleIntegrationTestRunner({
})
)
jest.clearAllMocks()
const fulfillment = await service.createFulfillment(
generateCreateFulfillmentData({
provider_id: providerId,
@@ -136,6 +156,34 @@ moduleIntegrationTestRunner({
],
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_created,
action: "created",
object: "fulfillment",
data: { id: fulfillment.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_address_created,
action: "created",
object: "fulfillment_address",
data: { id: fulfillment.delivery_address.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_item_created,
action: "created",
object: "fulfillment_item",
data: { id: fulfillment.items[0].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_label_created,
action: "created",
object: "fulfillment_label",
data: { id: fulfillment.labels[0].id },
}),
])
})
it("should create a return fulfillment", async () => {
@@ -160,6 +208,8 @@ moduleIntegrationTestRunner({
})
)
jest.clearAllMocks()
const fulfillment = await service.createReturnFulfillment(
generateCreateFulfillmentData({
provider_id: providerId,
@@ -193,6 +243,169 @@ moduleIntegrationTestRunner({
],
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_created,
action: "created",
object: "fulfillment",
data: { id: fulfillment.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_address_created,
action: "created",
object: "fulfillment_address",
data: { id: fulfillment.delivery_address.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_item_created,
action: "created",
object: "fulfillment_item",
data: { id: fulfillment.items[0].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_label_created,
action: "created",
object: "fulfillment_label",
data: { id: fulfillment.labels[0].id },
}),
])
})
})
describe("on update", () => {
it("should update a fulfillment", async () => {
const shippingProfile = await service.createShippingProfiles({
name: "test",
type: "default",
})
const fulfillmentSet = await service.create({
name: "test",
type: "test-type",
})
const serviceZone = await service.createServiceZones({
name: "test",
fulfillment_set_id: fulfillmentSet.id,
})
const shippingOption = await service.createShippingOptions(
generateCreateShippingOptionsData({
provider_id: providerId,
service_zone_id: serviceZone.id,
shipping_profile_id: shippingProfile.id,
})
)
const fulfillment = await service.createFulfillment(
generateCreateFulfillmentData({
provider_id: providerId,
shipping_option_id: shippingOption.id,
labels: [
{
tracking_number: "test-tracking-number-1",
tracking_url: "test-tracking-url-1",
label_url: "test-label-url-1",
},
{
tracking_number: "test-tracking-number-2",
tracking_url: "test-tracking-url-2",
label_url: "test-label-url-2",
},
{
tracking_number: "test-tracking-number-3",
tracking_url: "test-tracking-url-3",
label_url: "test-label-url-3",
},
],
})
)
const label1 = fulfillment.labels.find(
(l) => l.tracking_number === "test-tracking-number-1"
)!
const label2 = fulfillment.labels.find(
(l) => l.tracking_number === "test-tracking-number-2"
)!
const label3 = fulfillment.labels.find(
(l) => l.tracking_number === "test-tracking-number-3"
)!
const updateData: UpdateFulfillmentDTO = {
id: fulfillment.id,
labels: [
{ id: label1.id },
{ ...label2, label_url: "updated-test-label-url-2" },
{
tracking_number: "test-tracking-number-4",
tracking_url: "test-tracking-url-4",
label_url: "test-label-url-4",
},
],
}
jest.clearAllMocks()
const updatedFulfillment = await service.updateFulfillment(
fulfillment.id,
updateData
)
const label4 = updatedFulfillment.labels.find(
(l) => l.tracking_number === "test-tracking-number-4"
)!
expect(updatedFulfillment.labels).toHaveLength(3)
expect(updatedFulfillment).toEqual(
expect.objectContaining({
id: expect.any(String),
labels: expect.arrayContaining([
expect.objectContaining({
tracking_number: "test-tracking-number-1",
tracking_url: "test-tracking-url-1",
label_url: "test-label-url-1",
}),
expect.objectContaining({
tracking_number: "test-tracking-number-2",
tracking_url: "test-tracking-url-2",
label_url: "updated-test-label-url-2",
}),
expect.objectContaining({
tracking_number: "test-tracking-number-4",
tracking_url: "test-tracking-url-4",
label_url: "test-label-url-4",
}),
]),
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_updated,
action: "updated",
object: "fulfillment",
data: { id: updatedFulfillment.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_label_deleted,
action: "deleted",
object: "fulfillment_label",
data: { id: label3.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_label_updated,
action: "updated",
object: "fulfillment_label",
data: { id: label2.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_label_created,
action: "created",
object: "fulfillment_label",
data: { id: label4.id },
}),
])
})
})
@@ -227,6 +440,8 @@ moduleIntegrationTestRunner({
shipping_option_id: shippingOption.id,
})
)
jest.clearAllMocks()
})
it("should cancel a fulfillment successfully", async () => {
@@ -239,6 +454,16 @@ moduleIntegrationTestRunner({
expect(result.canceled_at).not.toBeNull()
expect(idempotentResult.canceled_at).not.toBeNull()
expect(idempotentResult.canceled_at).toEqual(result.canceled_at)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenNthCalledWith(1, [
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.fulfillment_updated,
action: "updated",
object: "fulfillment",
data: { id: fulfillment.id },
}),
])
})
it("should fail to cancel a fulfillment that is already shipped", async () => {
@@ -4,14 +4,28 @@ import {
IFulfillmentModuleService,
UpdateGeoZoneDTO,
} from "@medusajs/types"
import { GeoZoneType } from "@medusajs/utils"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
import {
MockEventBusService,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import { buildExpectedEventMessageShape } from "../../__fixtures__"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IFulfillmentModuleService>({
moduleName: Modules.FULFILLMENT,
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
})
afterEach(() => {
jest.clearAllMocks()
})
describe("Fulfillment Module Service", () => {
describe("read", () => {
it("should list geo zones with a filter", async function () {
@@ -81,6 +95,8 @@ moduleIntegrationTestRunner({
country_code: "fr",
}
jest.clearAllMocks()
const geoZone = await service.createGeoZones(data)
expect(geoZone).toEqual(
@@ -90,6 +106,16 @@ moduleIntegrationTestRunner({
country_code: data.country_code,
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: { id: geoZone.id },
}),
])
})
it("should create a collection of geo zones", async function () {
@@ -115,9 +141,12 @@ moduleIntegrationTestRunner({
},
]
jest.clearAllMocks()
const geoZones = await service.createGeoZones(data)
expect(geoZones).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
let i = 0
for (const data_ of data) {
@@ -128,6 +157,18 @@ moduleIntegrationTestRunner({
country_code: data_.country_code,
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: { id: geoZones[i].id },
}),
])
)
++i
}
})
@@ -213,6 +254,8 @@ moduleIntegrationTestRunner({
country_code: "us",
}
jest.clearAllMocks()
const updatedGeoZone = await service.updateGeoZones(updateData)
expect(updatedGeoZone).toEqual(
@@ -222,6 +265,15 @@ moduleIntegrationTestRunner({
country_code: updateData.country_code,
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_updated,
action: "updated",
object: "geo_zone",
data: { id: updatedGeoZone.id },
}),
])
})
it("should update a collection of geo zones", async function () {
@@ -258,14 +310,18 @@ moduleIntegrationTestRunner({
})
)
jest.clearAllMocks()
const updatedGeoZones = await service.updateGeoZones(updateData)
expect(updatedGeoZones).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
for (const data_ of updateData) {
const expectedGeoZone = updatedGeoZones.find(
(geoZone) => geoZone.id === data_.id
)
)!
expect(expectedGeoZone).toEqual(
expect.objectContaining({
id: data_.id,
@@ -273,6 +329,17 @@ moduleIntegrationTestRunner({
country_code: data_.country_code,
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_updated,
action: "updated",
object: "geo_zone",
data: { id: expectedGeoZone.id },
}),
])
)
}
})
})
@@ -5,14 +5,28 @@ import {
IFulfillmentModuleService,
UpdateServiceZoneDTO,
} from "@medusajs/types"
import { GeoZoneType } from "@medusajs/utils"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
import {
MockEventBusService,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import { buildExpectedEventMessageShape } from "../../__fixtures__"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IFulfillmentModuleService>({
moduleName: Modules.FULFILLMENT,
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
})
afterEach(() => {
jest.clearAllMocks()
})
describe("Fulfillment Module Service", () => {
describe("read", () => {
it("should list service zones with a filter", async function () {
@@ -276,6 +290,14 @@ moduleIntegrationTestRunner({
type: GeoZoneType.COUNTRY,
country_code: "fr",
},
{
type: GeoZoneType.COUNTRY,
country_code: "us",
},
{
type: GeoZoneType.COUNTRY,
country_code: "uk",
},
],
}
@@ -283,35 +305,94 @@ moduleIntegrationTestRunner({
createData
)
const updateData = {
const usGeoZone = createdServiceZone.geo_zones.find(
(geoZone) => geoZone.country_code === "us"
)!
const frGeoZone = createdServiceZone.geo_zones.find(
(geoZone) => geoZone.country_code === "fr"
)!
const ukGeoZone = createdServiceZone.geo_zones.find(
(geoZone) => geoZone.country_code === "uk"
)!
const updateData: UpdateServiceZoneDTO = {
name: "updated-service-zone-test",
geo_zones: [
{
id: createdServiceZone.geo_zones[0].id,
id: usGeoZone.id,
type: GeoZoneType.COUNTRY,
country_code: "us",
country_code: "es",
},
{
type: GeoZoneType.COUNTRY,
country_code: "ch",
},
{ id: frGeoZone.id },
],
}
jest.clearAllMocks()
const updatedServiceZone = await service.updateServiceZones(
createdServiceZone.id,
updateData
)
expect(updatedServiceZone.geo_zones).toHaveLength(3)
expect(updatedServiceZone).toEqual(
expect.objectContaining({
id: createdServiceZone.id,
name: updateData.name,
geo_zones: expect.arrayContaining([
expect.objectContaining({
id: updateData.geo_zones[0].id,
type: updateData.geo_zones[0].type,
country_code: updateData.geo_zones[0].country_code,
id: frGeoZone.id,
}),
expect.objectContaining({
id: usGeoZone.id,
type: GeoZoneType.COUNTRY,
country_code: "es",
}),
expect.objectContaining({
id: expect.any(String),
type: GeoZoneType.COUNTRY,
country_code: "ch",
}),
]),
})
)
const chGeoZone = updatedServiceZone.geo_zones.find(
(geoZone) => geoZone.country_code === "ch"
)!
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_deleted,
action: "deleted",
object: "geo_zone",
data: { id: ukGeoZone.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.service_zone_updated,
action: "updated",
object: "service_zone",
data: { id: updatedServiceZone.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_created,
action: "created",
object: "geo_zone",
data: { id: chGeoZone.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.geo_zone_updated,
action: "updated",
object: "geo_zone",
data: { id: usGeoZone.id },
}),
])
})
it("should fail on duplicated service zone name", async function () {
@@ -413,12 +494,16 @@ moduleIntegrationTestRunner({
})
)
jest.clearAllMocks()
const updatedServiceZones = await service.upsertServiceZones(
updateData
)
expect(updatedServiceZones).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6) // Since the update only calls create and update which are already tested, only check the length
for (const data_ of updateData) {
const expectedServiceZone = updatedServiceZones.find(
(serviceZone) => serviceZone.id === data_.id
@@ -3,12 +3,18 @@ import {
CreateShippingOptionDTO,
IFulfillmentModuleService,
} from "@medusajs/types"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { generateCreateShippingOptionsData } from "../../__fixtures__"
import {
MockEventBusService,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import {
buildExpectedEventMessageShape,
generateCreateShippingOptionsData,
} from "../../__fixtures__"
import { resolve } from "path"
import { FulfillmentProviderService } from "@services"
import { FulfillmentProviderServiceFixtures } from "../../__fixtures__/providers"
import { GeoZoneType } from "@medusajs/utils"
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
import { UpdateShippingOptionDTO } from "@medusajs/types/src"
jest.setTimeout(100000)
@@ -34,10 +40,20 @@ const providerId = FulfillmentProviderService.getRegistrationIdentifier(
"test-provider"
)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IFulfillmentModuleService>({
moduleName: Modules.FULFILLMENT,
moduleOptions,
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
})
afterEach(() => {
jest.clearAllMocks()
})
describe("Fulfillment Module Service", () => {
describe("read", () => {
it("should list shipping options with a filter", async function () {
@@ -432,6 +448,8 @@ moduleIntegrationTestRunner({
provider_id: providerId,
})
jest.clearAllMocks()
const createdShippingOption = await service.createShippingOptions(
createData
)
@@ -462,6 +480,28 @@ moduleIntegrationTestRunner({
]),
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_created,
action: "created",
object: "shipping_option",
data: { id: createdShippingOption.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_type_created,
action: "created",
object: "shipping_option_type",
data: { id: createdShippingOption.type.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_rule_created,
action: "created",
object: "shipping_option_rule",
data: { id: createdShippingOption.rules[0].id },
}),
])
})
it("should create multiple new shipping options", async function () {
@@ -491,11 +531,14 @@ moduleIntegrationTestRunner({
}),
]
jest.clearAllMocks()
const createdShippingOptions = await service.createShippingOptions(
createData
)
expect(createdShippingOptions).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6)
let i = 0
for (const data_ of createData) {
@@ -525,6 +568,30 @@ moduleIntegrationTestRunner({
]),
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_created,
action: "created",
object: "shipping_option",
data: { id: createdShippingOptions[i].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_type_created,
action: "created",
object: "shipping_option_type",
data: { id: createdShippingOptions[i].type.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_rule_created,
action: "created",
object: "shipping_option_rule",
data: { id: createdShippingOptions[i].rules[0].id },
}),
])
)
++i
}
})
@@ -623,6 +690,8 @@ moduleIntegrationTestRunner({
],
}
jest.clearAllMocks()
const updatedShippingOption = await service.updateShippingOptions(
updateData.id!,
updateData
@@ -681,6 +750,42 @@ moduleIntegrationTestRunner({
label: updateData.type.label,
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(5)
expect(eventBusEmitSpy).toHaveBeenCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_updated,
action: "updated",
object: "shipping_option",
data: { id: updatedShippingOption.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_type_deleted,
action: "deleted",
object: "shipping_option_type",
data: { id: shippingOption.type.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_type_created,
action: "created",
object: "shipping_option_type",
data: { id: updatedShippingOption.type.id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_rule_created,
action: "created",
object: "shipping_option_rule",
data: { id: updatedShippingOption.rules[1].id },
}),
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_rule_updated,
action: "updated",
object: "shipping_option_rule",
data: { id: updatedShippingOption.rules[0].id },
}),
])
)
})
it("should update a shipping option without updating the rules or the type", async () => {
@@ -1092,6 +1197,8 @@ moduleIntegrationTestRunner({
shipping_option_id: shippingOption.id,
}
jest.clearAllMocks()
const rule = await service.createShippingOptionRules(ruleData)
expect(rule).toEqual(
@@ -1104,6 +1211,16 @@ moduleIntegrationTestRunner({
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_rule_created,
action: "created",
object: "shipping_option_rule",
data: { id: rule.id },
}),
])
const rules = await service.listShippingOptionRules()
expect(rules).toHaveLength(2)
expect(rules).toEqual(
@@ -1157,6 +1274,8 @@ moduleIntegrationTestRunner({
value: "updated-test",
}
jest.clearAllMocks()
const updatedRule = await service.updateShippingOptionRules(
updateData
)
@@ -1169,6 +1288,15 @@ moduleIntegrationTestRunner({
value: updateData.value,
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_option_rule_updated,
action: "updated",
object: "shipping_option_rule",
data: { id: updatedRule.id },
}),
])
})
it("should fail to update a non-existent shipping option rule", async () => {
@@ -3,13 +3,28 @@ import {
CreateShippingProfileDTO,
IFulfillmentModuleService,
} from "@medusajs/types"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import {
MockEventBusService,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import { buildExpectedEventMessageShape } from "../../__fixtures__"
import { FulfillmentEvents } from "@medusajs/utils"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IFulfillmentModuleService>({
moduleName: Modules.FULFILLMENT,
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
})
afterEach(() => {
jest.clearAllMocks()
})
describe("Fulfillment Module Service", () => {
describe("mutations", () => {
describe("on create", () => {
@@ -29,6 +44,16 @@ moduleIntegrationTestRunner({
type: createData.type,
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_profile_created,
action: "created",
object: "shipping_profile",
data: { id: createdShippingProfile.id },
}),
])
})
it("should create multiple new shipping profiles", async function () {
@@ -47,6 +72,7 @@ moduleIntegrationTestRunner({
await service.createShippingProfiles(createData)
expect(createdShippingProfiles).toHaveLength(2)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
let i = 0
for (const data_ of createData) {
@@ -56,6 +82,18 @@ moduleIntegrationTestRunner({
type: data_.type,
})
)
expect(eventBusEmitSpy).toHaveBeenCalledWith(
expect.arrayContaining([
buildExpectedEventMessageShape({
eventName: FulfillmentEvents.shipping_profile_created,
action: "created",
object: "shipping_profile",
data: { id: createdShippingProfiles[i].id },
}),
])
)
++i
}
})