test(core-flows): Ensure productVariantUpdated failure compensate the workflow (#12381)
This commit is contained in:
+190
@@ -0,0 +1,190 @@
|
|||||||
|
import { updateProductVariantsWorkflow } from "@medusajs/core-flows"
|
||||||
|
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import { IProductModuleService } from "@medusajs/types"
|
||||||
|
import { MedusaError, Modules } from "@medusajs/utils"
|
||||||
|
|
||||||
|
jest.setTimeout(50000)
|
||||||
|
|
||||||
|
medusaIntegrationTestRunner({
|
||||||
|
env: {},
|
||||||
|
testSuite: ({ getContainer }) => {
|
||||||
|
describe("Workflows: Update product variants", () => {
|
||||||
|
let appContainer
|
||||||
|
let service: IProductModuleService
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
appContainer = getContainer()
|
||||||
|
service = appContainer.resolve(Modules.PRODUCT)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("updateProductVariantsWorkflow", () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
updateProductVariantsWorkflow.hooks.productVariantsUpdated(() => {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
|
"product variants updated hook failed"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("compensation", () => {
|
||||||
|
it("should revert the updated variants using product_variants if the hook fails", async () => {
|
||||||
|
const workflow = updateProductVariantsWorkflow(appContainer)
|
||||||
|
|
||||||
|
const [product1, product2] = await service.createProducts([
|
||||||
|
{
|
||||||
|
title: "test1",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "variant1",
|
||||||
|
sku: "variant1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "test2",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "variant2",
|
||||||
|
sku: "variant2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: {
|
||||||
|
product_variants: [
|
||||||
|
{
|
||||||
|
id: product1.variants[0].id,
|
||||||
|
title: "variant1-updated",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(errors).toEqual([
|
||||||
|
{
|
||||||
|
action: "productVariantsUpdated",
|
||||||
|
handlerType: "invoke",
|
||||||
|
error: expect.objectContaining({
|
||||||
|
message: `product variants updated hook failed`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const products = await service.listProducts(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
relations: ["variants"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(products).toHaveLength(2)
|
||||||
|
expect(products).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product1.title,
|
||||||
|
variants: [
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product1.variants[0].title,
|
||||||
|
sku: product1.variants[0].sku,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product2.title,
|
||||||
|
variants: [
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product2.variants[0].title,
|
||||||
|
sku: product2.variants[0].sku,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should revert the updated variants using selector/update if the hook fails", async () => {
|
||||||
|
const workflow = updateProductVariantsWorkflow(appContainer)
|
||||||
|
|
||||||
|
const [product1, product2] = await service.createProducts([
|
||||||
|
{
|
||||||
|
title: "test1",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "variant1",
|
||||||
|
sku: "variant1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "test2",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "variant2",
|
||||||
|
sku: "variant2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: {
|
||||||
|
selector: {
|
||||||
|
id: product1.variants[0].id,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
title: "variant1-updated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(errors).toEqual([
|
||||||
|
{
|
||||||
|
action: "productVariantsUpdated",
|
||||||
|
handlerType: "invoke",
|
||||||
|
error: expect.objectContaining({
|
||||||
|
message: `product variants updated hook failed`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const products = await service.listProducts(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
relations: ["variants"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(products).toHaveLength(2)
|
||||||
|
expect(products).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product1.title,
|
||||||
|
variants: [
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product1.variants[0].title,
|
||||||
|
sku: product1.variants[0].sku,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product2.title,
|
||||||
|
variants: [
|
||||||
|
expect.objectContaining({
|
||||||
|
title: product2.variants[0].title,
|
||||||
|
sku: product2.variants[0].sku,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,117 +1,54 @@
|
|||||||
import { z } from "zod"
|
import { createStep, createWorkflow, StepResponse, transform } from "./composer"
|
||||||
import {
|
|
||||||
createStep,
|
|
||||||
createWorkflow,
|
|
||||||
StepResponse,
|
|
||||||
WorkflowData,
|
|
||||||
} from "./composer"
|
|
||||||
import { createHook } from "./composer/create-hook"
|
import { createHook } from "./composer/create-hook"
|
||||||
import { WorkflowResponse } from "./composer/helpers/workflow-response"
|
import { WorkflowResponse } from "./composer/helpers/workflow-response"
|
||||||
|
|
||||||
const step1 = createStep("step1", async (input: {}, context) => {
|
const step1 = createStep(
|
||||||
return new StepResponse({ step1: "step1" })
|
"step1",
|
||||||
})
|
() => {
|
||||||
|
return new StepResponse("step1")
|
||||||
type Step2Input = { filters: { id: string[] } } | { filters: { id: string } }
|
},
|
||||||
const step2 = createStep("step2", async (input: Step2Input, context) => {
|
() => {
|
||||||
return new StepResponse({ step2: input })
|
console.log("compensate step1")
|
||||||
})
|
|
||||||
|
|
||||||
const step3 = createStep("step3", async function (_, context) {
|
|
||||||
return new StepResponse({ step3: "step3" })
|
|
||||||
})
|
|
||||||
|
|
||||||
const step4 = createStep("step4", async function (_, context) {
|
|
||||||
return new StepResponse<undefined | { id: number }>({ id: 1 })
|
|
||||||
})
|
|
||||||
|
|
||||||
const step5 = createStep("step5", async function (_, context) {
|
|
||||||
return new StepResponse(void 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
const workflow = createWorkflow(
|
|
||||||
"sub-workflow",
|
|
||||||
function (input: WorkflowData<{ outsideWorkflowData: string }>) {
|
|
||||||
step1()
|
|
||||||
step2({ filters: { id: [] } })
|
|
||||||
|
|
||||||
let somethingHook = createHook(
|
|
||||||
"something",
|
|
||||||
{ id: "1" },
|
|
||||||
{
|
|
||||||
resultValidator: z.object({
|
|
||||||
id: z.number(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const step4Result = step4().config({ name: "foo" })
|
|
||||||
step4Result
|
|
||||||
|
|
||||||
const step5Result = step5().config({ name: "foo" })
|
|
||||||
step5Result
|
|
||||||
|
|
||||||
return new WorkflowResponse(
|
|
||||||
{ r: somethingHook.getResult(), step3: step3() },
|
|
||||||
{ hooks: [somethingHook] }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
workflow.hooks.something((input, context) => {
|
const step2 = createStep(
|
||||||
console.log("input>", input)
|
"step2",
|
||||||
console.log("context>", context)
|
(input: any) => {
|
||||||
return new StepResponse({ id: 2, foo: "bar" })
|
return new StepResponse(input)
|
||||||
})
|
},
|
||||||
|
(input) => {
|
||||||
|
console.log("compensate step2", input)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
workflow.run().then((res) => {
|
const workflow = createWorkflow("workflow", () => {
|
||||||
console.log("res", res)
|
const step1Result = step1()
|
||||||
})
|
|
||||||
|
|
||||||
/*const workflow2 = createWorkflow("workflow", function () {
|
const step2Input = transform({ step1Result }, (input) => {
|
||||||
const step1Res = step1()
|
return input
|
||||||
|
|
||||||
const step3Res = when({ value: true }, ({ value }) => {
|
|
||||||
return value
|
|
||||||
}).then(() => {
|
|
||||||
return step3()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
transform({ step3Res }, ({ step3Res }) => {
|
const step2Result = step2(step2Input)
|
||||||
console.log(step3Res)
|
|
||||||
|
const hook = createHook("hook", {
|
||||||
|
step2Result,
|
||||||
})
|
})
|
||||||
|
|
||||||
const workflowRes = workflow.asStep({ outsideWorkflowData: step1Res.step1 })
|
return new WorkflowResponse(void 0, {
|
||||||
|
hooks: [hook],
|
||||||
return workflowRes
|
})
|
||||||
})*/
|
|
||||||
|
|
||||||
// workflow()
|
|
||||||
// .run({})
|
|
||||||
// .then((res) => {
|
|
||||||
// console.log(res.result)
|
|
||||||
// })
|
|
||||||
|
|
||||||
/*const step1 = createStep("step1", async (input: {}, context) => {
|
|
||||||
return new StepResponse({ step1: ["step1"] })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const step2 = createStep("step2", async (input: string[], context) => {
|
workflow.hooks.hook(() => {
|
||||||
return new StepResponse({ step2: input })
|
throw new Error("hook failed")
|
||||||
})
|
|
||||||
|
|
||||||
const step3 = createStep("step3", async () => {
|
|
||||||
return new StepResponse({ step3: "step3" })
|
|
||||||
})
|
|
||||||
|
|
||||||
const workflow = createWorkflow("workflow", function () {
|
|
||||||
const step1Res = step1()
|
|
||||||
step3()
|
|
||||||
return step2(step1Res.step1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
workflow()
|
workflow()
|
||||||
.run({})
|
.run()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res.result)
|
console.log(res)
|
||||||
})*/
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user