feat: region payment providers management workflows/api (#6864)

This commit is contained in:
Adrien de Peretti
2024-04-04 20:41:34 +02:00
committed by GitHub
parent 12fcb655cd
commit e944a627f0
48 changed files with 1033 additions and 89 deletions

View File

@@ -1,6 +1,7 @@
import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk"
import { IPaymentModuleService, IRegionModuleService } from "@medusajs/types"
import { medusaIntegrationTestRunner } from "medusa-test-utils"
import {ContainerRegistrationKeys} from "@medusajs/utils";
jest.setTimeout(50000)
@@ -20,8 +21,8 @@ medusaIntegrationTestRunner({
appContainer = getContainer()
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT)
remoteQuery = appContainer.resolve("remoteQuery")
remoteLink = appContainer.resolve("remoteLink")
remoteQuery = appContainer.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
remoteLink = appContainer.resolve(ContainerRegistrationKeys.REMOTE_LINK)
})
it("should query region and payment provider link with remote query", async () => {
@@ -73,7 +74,7 @@ medusaIntegrationTestRunner({
])
)
expect(otherLink).toHaveLength(1)
expect(otherLink).toHaveLength(2)
expect(otherLink).toEqual(
expect.arrayContaining([
expect.objectContaining({
@@ -84,6 +85,10 @@ medusaIntegrationTestRunner({
}),
]),
}),
expect.objectContaining({
id: "pp_system_default_2",
regions: []
}),
])
)
})

View File

@@ -47,10 +47,9 @@ medusaIntegrationTestRunner({
metadata: { foo: "bar" },
})
)
expect(created.data.region.countries.map((c) => c.iso_2)).toEqual([
"us",
"ca",
])
expect(
created.data.region.countries.map((c) => c.iso_2).sort()
).toEqual(["ca", "us"])
const updated = await api.post(
`/admin/regions/${created.data.region.id}`,
@@ -96,6 +95,174 @@ medusaIntegrationTestRunner({
expect(deletedRegion.deleted_at).toBeTruthy()
})
it("should create the region with the available payment providers if the providers exists", async () => {
const paymentProviderId = "pp_system_default"
const created = await api.post(
`/admin/regions?fields=*payment_providers`,
{
name: "Test Region",
currency_code: "usd",
countries: ["us", "ca"],
metadata: { foo: "bar" },
payment_providers: [paymentProviderId],
},
adminHeaders
)
expect(created.status).toEqual(200)
expect(created.data.region).toEqual(
expect.objectContaining({
id: created.data.region.id,
name: "Test Region",
currency_code: "usd",
metadata: { foo: "bar" },
payment_providers: [
expect.objectContaining({
id: paymentProviderId,
}),
],
})
)
})
it("should update the region available payment providers", async () => {
const paymentProviderId = "pp_system_default"
const paymentProvider2Id = "pp_system_default_2"
const created = await api.post(
`/admin/regions`,
{
name: "Test Region",
currency_code: "usd",
countries: ["us", "ca"],
metadata: { foo: "bar" },
},
adminHeaders
)
/**
* Assign a new payment provider
*/
await api.post(
`/admin/regions/${created.data.region.id}`,
{
payment_providers: [paymentProviderId],
},
adminHeaders
)
let regionResponse = await api.get(
`/admin/regions/${created.data.region.id}?fields=*payment_providers`,
adminHeaders
)
expect(regionResponse.status).toEqual(200)
expect(regionResponse.data.region.payment_providers).toHaveLength(1)
expect(regionResponse.data.region).toEqual(
expect.objectContaining({
id: regionResponse.data.region.id,
payment_providers: [
expect.objectContaining({
id: paymentProviderId,
}),
],
})
)
/**
* Replace the region payment providers by a new one set of providers
*/
await api.post(
`/admin/regions/${created.data.region.id}`,
{
payment_providers: [paymentProvider2Id],
},
adminHeaders
)
regionResponse = await api.get(
`/admin/regions/${created.data.region.id}?fields=*payment_providers`,
adminHeaders
)
expect(regionResponse.status).toEqual(200)
expect(regionResponse.data.region.payment_providers).toHaveLength(1)
expect(regionResponse.data.region).toEqual(
expect.objectContaining({
id: regionResponse.data.region.id,
payment_providers: [
expect.objectContaining({
id: paymentProvider2Id,
}),
],
})
)
/**
* Replace the region payment providers with both providers
*/
await api.post(
`/admin/regions/${created.data.region.id}`,
{
payment_providers: [paymentProviderId, paymentProvider2Id],
},
adminHeaders
)
regionResponse = await api.get(
`/admin/regions/${created.data.region.id}?fields=*payment_providers`,
adminHeaders
)
expect(regionResponse.status).toEqual(200)
expect(regionResponse.data.region.payment_providers).toHaveLength(2)
expect(regionResponse.data.region).toEqual(
expect.objectContaining({
id: regionResponse.data.region.id,
payment_providers: [
expect.objectContaining({
id: paymentProvider2Id,
}),
expect.objectContaining({
id: paymentProviderId,
}),
],
})
)
})
it("should throw on update if the given payment providers does not exists", async () => {
const created = await api.post(
`/admin/regions`,
{
name: "Test Region",
currency_code: "usd",
countries: ["us", "ca"],
metadata: { foo: "bar" },
},
adminHeaders
)
const updateErr = await api
.post(
`/admin/regions/${created.data.region.id}`,
{
payment_providers: ["test"],
},
adminHeaders
)
.catch((e) => e)
expect(updateErr.response.status).toEqual(404)
expect(updateErr.response.data.message).toEqual(
"Payment providers with ids test not found or not enabled"
)
})
it("should throw on missing required properties in create", async () => {
const err = await api
.post(`/admin/regions`, {}, adminHeaders)

View File

@@ -0,0 +1,148 @@
import { medusaIntegrationTestRunner } from "medusa-test-utils"
import { createRegionsWorkflow } from "@medusajs/core-flows"
import { MedusaContainer, RegionDTO } from "@medusajs/types"
import { createAdminUser } from "../../../../helpers/create-admin-user"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
jest.setTimeout(200000)
const env = { MEDUSA_FF_MEDUSA_V2: true }
const adminHeaders = {
headers: { "x-medusa-access-token": "test_token" },
}
medusaIntegrationTestRunner({
env,
testSuite: ({ dbConnection, getContainer, api }) => {
let container: MedusaContainer
let region: RegionDTO
beforeAll(() => {
container = getContainer()
})
beforeEach(async () => {
await createAdminUser(dbConnection, adminHeaders, container)
})
describe("create region workflow", () => {
it("should create a region", async () => {
const paymentProviderId = "pp_system_default"
const data = {
name: "Test Region",
currency_code: "usd",
countries: ["us", "ca"],
metadata: { foo: "bar" },
payment_providers: [paymentProviderId],
}
let {
result: [createRegion],
} = await createRegionsWorkflow(container).run({
input: {
regions: [data],
},
})
const remoteQuery = container.resolve(
ContainerRegistrationKeys.REMOTE_QUERY
)
;[createRegion] = await remoteQuery(
remoteQueryObjectFromString({
entryPoint: "region",
variables: {
filters: {
id: createRegion.id,
},
},
fields: [
"id",
"name",
"currency_code",
"metadata",
"countries.*",
"payment_providers.*",
],
})
)
expect(createRegion).toEqual(
expect.objectContaining({
id: expect.any(String),
name: data.name,
currency_code: data.currency_code,
countries: expect.arrayContaining(
data.countries.map((iso_2) => expect.objectContaining({ iso_2 }))
),
metadata: data.metadata,
payment_providers: [
expect.objectContaining({
id: paymentProviderId,
}),
],
})
)
})
it("should revert the created region and payment providers", async () => {
const paymentProviderId = "pp_system_default"
const data = {
name: "Test Region",
currency_code: "usd",
countries: ["us", "ca"],
metadata: { foo: "bar" },
payment_providers: [paymentProviderId],
}
const workflow = createRegionsWorkflow(container)
workflow.addAction(
"throw",
{
invoke: async function failStep() {
throw new Error(`Failed to create region`)
},
},
{
noCompensation: true,
}
)
const { errors } = await workflow.run({
input: {
regions: [data],
},
throwOnError: false,
})
expect(errors).toHaveLength(1)
expect(errors[0].error.message).toEqual(`Failed to create region`)
const remoteQuery = container.resolve(
ContainerRegistrationKeys.REMOTE_QUERY
)
const createRegions = await remoteQuery(
remoteQueryObjectFromString({
entryPoint: "region",
fields: [
"id",
"name",
"currency_code",
"metadata",
"countries.*",
"payment_providers.*",
],
})
)
expect(createRegions).toHaveLength(0)
})
})
},
})

View File

@@ -0,0 +1,112 @@
import { medusaIntegrationTestRunner } from "medusa-test-utils"
import { updateRegionsWorkflow } from "@medusajs/core-flows"
import {ContainerLike, MedusaContainer, RegionDTO} from "@medusajs/types"
import { createAdminUser } from "../../../../helpers/create-admin-user"
jest.setTimeout(200000)
const env = { MEDUSA_FF_MEDUSA_V2: true }
const adminHeaders = {
headers: { "x-medusa-access-token": "test_token" },
}
medusaIntegrationTestRunner({
env,
testSuite: ({ dbConnection, getContainer, api }) => {
let container: MedusaContainer
let region: RegionDTO
beforeAll(() => {
container = getContainer()
})
beforeEach(async () => {
await createAdminUser(dbConnection, adminHeaders, container)
region = (
await api.post(
`/admin/regions`,
{
name: "Test Region",
currency_code: "usd",
countries: ["us", "ca"],
metadata: { foo: "bar" },
},
adminHeaders
)
).data.region
})
describe("update region workflow", () => {
it("should update a region", async () => {
const updateData = {
name: "United States update",
}
const {
result: [updatedRegion],
} = await updateRegionsWorkflow(container).run({
input: {
selector: { id: region.id },
update: updateData,
},
})
expect(updatedRegion).toEqual(
expect.objectContaining({
id: region.id,
name: updateData.name,
})
)
})
it("should revert region update and payment providers update when it fails", async () => {
const paymentProviderId = "pp_system_default"
const paymentProvider2Id = "pp_system_default_2"
const updateData = {
name: "United States update",
payment_providers: [paymentProviderId, paymentProvider2Id],
}
const workflow = updateRegionsWorkflow(container)
workflow.addAction(
"throw",
{
invoke: async function failStep() {
throw new Error(`Failed to update region`)
},
},
{
noCompensation: true,
}
)
const { errors } = await workflow.run({
input: {
selector: { id: region.id },
update: updateData,
},
throwOnError: false,
})
expect(errors).toHaveLength(1)
expect(errors[0].error.message).toEqual(`Failed to update region`)
const updatedRegion = (
await api.get(
`/admin/regions/${region.id}?fields=*payment_providers`,
adminHeaders
)
).data.region
expect(updatedRegion).toEqual(
expect.objectContaining({
id: region.id,
name: region.name,
payment_providers: [],
})
)
})
})
},
})

View File

@@ -10,6 +10,17 @@ process.env.LOG_LEVEL = "error"
const enableMedusaV2 = process.env.MEDUSA_FF_MEDUSA_V2 == "true"
const customPaymentProvider = {
resolve: {
services: [require("@medusajs/payment/dist/providers/system").default],
},
options: {
config: {
default_2: {},
},
},
}
module.exports = {
plugins: [],
projectConfig: {
@@ -70,7 +81,13 @@ module.exports = {
[Modules.STORE]: true,
[Modules.TAX]: true,
[Modules.CURRENCY]: true,
[Modules.PAYMENT]: true,
[Modules.PAYMENT]: {
resolve: "@medusajs/payment",
/** @type {import('@medusajs/payment').PaymentModuleOptions}*/
options: {
providers: [customPaymentProvider],
},
},
[Modules.FULFILLMENT]: {
/** @type {import('@medusajs/fulfillment').FulfillmentModuleOptions} */
options: {