Feat: TO variant creation (#3097)
This commit is contained in:
@@ -7,6 +7,10 @@ import {
|
||||
} from "../../transaction"
|
||||
|
||||
describe("Transaction Orchestrator", () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("Should follow the flow by calling steps in order with the correct payload", async () => {
|
||||
const mocks = {
|
||||
one: jest.fn().mockImplementation((payload) => {
|
||||
@@ -187,7 +191,7 @@ describe("Transaction Orchestrator", () => {
|
||||
expect(actionOrder).toEqual(["one", "two", "three"])
|
||||
})
|
||||
|
||||
it("Should forward step response if flag 'forwardResponse' is set to true", async () => {
|
||||
it("Should store invoke's step response if flag 'saveResponse' is set to true", async () => {
|
||||
const mocks = {
|
||||
one: jest.fn().mockImplementation((data) => {
|
||||
return { abc: 1234 }
|
||||
@@ -195,8 +199,11 @@ describe("Transaction Orchestrator", () => {
|
||||
two: jest.fn().mockImplementation((data) => {
|
||||
return { def: "567" }
|
||||
}),
|
||||
three: jest.fn().mockImplementation((data) => {
|
||||
return { end: true }
|
||||
three: jest.fn().mockImplementation((data, context) => {
|
||||
return { end: true, onePropAbc: context.invoke.firstMethod.abc }
|
||||
}),
|
||||
four: jest.fn().mockImplementation((data) => {
|
||||
return null
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -217,24 +224,36 @@ describe("Transaction Orchestrator", () => {
|
||||
},
|
||||
},
|
||||
thirdMethod: {
|
||||
[TransactionHandlerType.INVOKE]: (data, context) => {
|
||||
return mocks.three(data, context)
|
||||
},
|
||||
},
|
||||
fourthMethod: {
|
||||
[TransactionHandlerType.INVOKE]: (data) => {
|
||||
return mocks.three(data)
|
||||
return mocks.four(data)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return command[actionId][functionHandlerType]({ ...payload.data })
|
||||
return command[actionId][functionHandlerType](
|
||||
payload.data,
|
||||
payload.context
|
||||
)
|
||||
}
|
||||
|
||||
const flow: TransactionStepsDefinition = {
|
||||
next: {
|
||||
action: "firstMethod",
|
||||
forwardResponse: true,
|
||||
saveResponse: true,
|
||||
next: {
|
||||
action: "secondMethod",
|
||||
forwardResponse: true,
|
||||
saveResponse: true,
|
||||
next: {
|
||||
action: "thirdMethod",
|
||||
saveResponse: true,
|
||||
next: {
|
||||
action: "fourthMethod",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -245,18 +264,111 @@ describe("Transaction Orchestrator", () => {
|
||||
const transaction = await strategy.beginTransaction(
|
||||
"transaction_id_123",
|
||||
handler,
|
||||
{
|
||||
prop: 123,
|
||||
}
|
||||
{ prop: 123 }
|
||||
)
|
||||
|
||||
await strategy.resume(transaction)
|
||||
|
||||
expect(mocks.one).toBeCalledWith({ prop: 123 })
|
||||
expect(mocks.two).toBeCalledWith({ prop: 123 })
|
||||
|
||||
expect(mocks.two).toBeCalledWith({ prop: 123, _response: { abc: 1234 } })
|
||||
expect(mocks.three).toBeCalledWith(
|
||||
{ prop: 123 },
|
||||
{
|
||||
invoke: {
|
||||
firstMethod: { abc: 1234 },
|
||||
secondMethod: { def: "567" },
|
||||
thirdMethod: { end: true, onePropAbc: 1234 },
|
||||
},
|
||||
compensate: {},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
expect(mocks.three).toBeCalledWith({ prop: 123, _response: { def: "567" } })
|
||||
it("Should store compensate's step responses if flag 'saveResponse' is set to true", async () => {
|
||||
const mocks = {
|
||||
one: jest.fn().mockImplementation(() => {
|
||||
return 1
|
||||
}),
|
||||
two: jest.fn().mockImplementation(() => {
|
||||
return 2
|
||||
}),
|
||||
compensateOne: jest.fn().mockImplementation((compensateContext) => {
|
||||
return "compensate 1 - 2 = " + compensateContext.secondMethod.two
|
||||
}),
|
||||
compensateTwo: jest.fn().mockImplementation((compensateContext) => {
|
||||
return { two: "isCompensated" }
|
||||
}),
|
||||
}
|
||||
|
||||
async function handler(
|
||||
actionId: string,
|
||||
functionHandlerType: TransactionHandlerType,
|
||||
payload: TransactionPayload
|
||||
) {
|
||||
const command = {
|
||||
firstMethod: {
|
||||
[TransactionHandlerType.INVOKE]: () => {
|
||||
return mocks.one()
|
||||
},
|
||||
[TransactionHandlerType.COMPENSATE]: ({ compensate }) => {
|
||||
return mocks.compensateOne({ ...compensate })
|
||||
},
|
||||
},
|
||||
secondMethod: {
|
||||
[TransactionHandlerType.INVOKE]: () => {
|
||||
return mocks.two()
|
||||
},
|
||||
[TransactionHandlerType.COMPENSATE]: ({ compensate }) => {
|
||||
return mocks.compensateTwo({ ...compensate })
|
||||
},
|
||||
},
|
||||
thirdMethod: {
|
||||
[TransactionHandlerType.INVOKE]: () => {
|
||||
throw new Error("failed")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return command[actionId][functionHandlerType](payload.context)
|
||||
}
|
||||
|
||||
const flow: TransactionStepsDefinition = {
|
||||
next: {
|
||||
action: "firstMethod",
|
||||
saveResponse: true,
|
||||
next: {
|
||||
action: "secondMethod",
|
||||
saveResponse: true,
|
||||
next: {
|
||||
action: "thirdMethod",
|
||||
noCompensation: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const strategy = new TransactionOrchestrator("transaction-name", flow)
|
||||
|
||||
const transaction = await strategy.beginTransaction(
|
||||
"transaction_id_123",
|
||||
handler
|
||||
)
|
||||
|
||||
await strategy.resume(transaction)
|
||||
const resposes = transaction.getContext()
|
||||
|
||||
expect(mocks.compensateTwo).toBeCalledWith({})
|
||||
|
||||
expect(mocks.compensateOne).toBeCalledWith({
|
||||
secondMethod: {
|
||||
two: "isCompensated",
|
||||
},
|
||||
})
|
||||
|
||||
expect(resposes.compensate.firstMethod).toEqual(
|
||||
"compensate 1 - 2 = isCompensated"
|
||||
)
|
||||
})
|
||||
|
||||
it("Should continue the exection of next steps without waiting for the execution of all its parents when flag 'noWait' is set to true", async () => {
|
||||
@@ -362,8 +474,10 @@ describe("Transaction Orchestrator", () => {
|
||||
const flow: TransactionStepsDefinition = {
|
||||
next: {
|
||||
action: "firstMethod",
|
||||
maxRetries: 3,
|
||||
next: {
|
||||
action: "secondMethod",
|
||||
maxRetries: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -379,7 +493,7 @@ describe("Transaction Orchestrator", () => {
|
||||
|
||||
expect(transaction.transactionId).toBe("transaction_id_123")
|
||||
expect(mocks.one).toBeCalledTimes(1)
|
||||
expect(mocks.two).toBeCalledTimes(1 + strategy.DEFAULT_RETRIES)
|
||||
expect(mocks.two).toBeCalledTimes(4)
|
||||
expect(transaction.getState()).toBe(TransactionState.REVERTED)
|
||||
expect(mocks.compensateOne).toBeCalledTimes(1)
|
||||
|
||||
@@ -428,6 +542,7 @@ describe("Transaction Orchestrator", () => {
|
||||
const flow: TransactionStepsDefinition = {
|
||||
next: {
|
||||
action: "firstMethod",
|
||||
maxRetries: 1,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -440,7 +555,7 @@ describe("Transaction Orchestrator", () => {
|
||||
|
||||
await strategy.resume(transaction)
|
||||
|
||||
expect(mocks.one).toBeCalledTimes(1 + strategy.DEFAULT_RETRIES)
|
||||
expect(mocks.one).toBeCalledTimes(2)
|
||||
expect(transaction.getState()).toBe(TransactionState.FAILED)
|
||||
})
|
||||
|
||||
@@ -666,4 +781,77 @@ describe("Transaction Orchestrator", () => {
|
||||
|
||||
expect(resumedTransaction.getState()).toBe(TransactionState.REVERTED)
|
||||
})
|
||||
|
||||
it("Should revert a transaction when .cancelTransaction() is called", async () => {
|
||||
const mocks = {
|
||||
one: jest.fn().mockImplementation((payload) => {
|
||||
return payload
|
||||
}),
|
||||
oneCompensate: jest.fn().mockImplementation((payload) => {
|
||||
return payload
|
||||
}),
|
||||
two: jest.fn().mockImplementation((payload) => {
|
||||
return payload
|
||||
}),
|
||||
twoCompensate: jest.fn().mockImplementation((payload) => {
|
||||
return payload
|
||||
}),
|
||||
}
|
||||
|
||||
async function handler(
|
||||
actionId: string,
|
||||
functionHandlerType: TransactionHandlerType,
|
||||
payload: TransactionPayload
|
||||
) {
|
||||
const command = {
|
||||
firstMethod: {
|
||||
[TransactionHandlerType.INVOKE]: () => {
|
||||
mocks.one(payload)
|
||||
},
|
||||
[TransactionHandlerType.COMPENSATE]: () => {
|
||||
mocks.oneCompensate(payload)
|
||||
},
|
||||
},
|
||||
secondMethod: {
|
||||
[TransactionHandlerType.INVOKE]: () => {
|
||||
mocks.two(payload)
|
||||
},
|
||||
[TransactionHandlerType.COMPENSATE]: () => {
|
||||
mocks.twoCompensate(payload)
|
||||
},
|
||||
},
|
||||
}
|
||||
return command[actionId][functionHandlerType](payload)
|
||||
}
|
||||
|
||||
const flow: TransactionStepsDefinition = {
|
||||
next: {
|
||||
action: "firstMethod",
|
||||
next: {
|
||||
action: "secondMethod",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const strategy = new TransactionOrchestrator("transaction-name", flow)
|
||||
|
||||
const transaction = await strategy.beginTransaction(
|
||||
"transaction_id_123",
|
||||
handler
|
||||
)
|
||||
|
||||
await strategy.resume(transaction)
|
||||
|
||||
expect(transaction.getState()).toBe(TransactionState.DONE)
|
||||
expect(mocks.one).toBeCalledTimes(1)
|
||||
expect(mocks.two).toBeCalledTimes(1)
|
||||
|
||||
await strategy.cancelTransaction(transaction)
|
||||
|
||||
expect(transaction.getState()).toBe(TransactionState.REVERTED)
|
||||
expect(mocks.one).toBeCalledTimes(1)
|
||||
expect(mocks.two).toBeCalledTimes(1)
|
||||
expect(mocks.oneCompensate).toBeCalledTimes(1)
|
||||
expect(mocks.twoCompensate).toBeCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user