@getclave/lifi-sdk
Version:
LI.FI Any-to-Any Cross-Chain-Swap SDK
224 lines (223 loc) • 11.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const fixtures_1 = require("../tests/fixtures");
const setup_1 = require("../tests/setup");
const StatusManager_1 = require("./StatusManager");
const executionState_1 = require("./executionState");
// Note: using structuredClone when passing objects to the StatusManager shall make sure that we are not facing any unknown call-by-reference-issues anymore
(0, vitest_1.beforeAll)(setup_1.setupTestEnvironment);
(0, vitest_1.describe)('StatusManager', () => {
let statusManager;
let updateRouteHookMock;
let route;
let step;
const expectCallbacksToHaveBeenCalledWith = (route) => {
(0, vitest_1.expect)(updateRouteHookMock).toHaveBeenCalledWith(route);
};
const initializeStatusManager = ({ includingExecution, }) => {
step = (0, fixtures_1.buildStepObject)({ includingExecution });
route = (0, fixtures_1.buildRouteObject)({ step });
executionState_1.executionState.create({
route,
executionOptions: {
updateRouteHook: updateRouteHookMock,
},
});
return new StatusManager_1.StatusManager(route.id);
};
(0, vitest_1.beforeEach)(() => {
updateRouteHookMock = vitest_1.vi.fn();
vitest_1.vi.spyOn(Date, 'now').mockImplementation(() => fixtures_1.SOME_DATE);
});
(0, vitest_1.describe)('initExecutionObject', () => {
(0, vitest_1.describe)('when no execution is defined yet', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: false });
statusManager.initExecutionObject(step);
});
(0, vitest_1.it)('should create an empty execution & call the callbacks with the updated route', () => {
const updatedStep = Object.assign({}, step, {
execution: {
status: 'PENDING',
process: [],
startedAt: fixtures_1.SOME_DATE,
},
});
const updatedRoute = Object.assign({}, route, {
steps: [updatedStep],
});
expectCallbacksToHaveBeenCalledWith(updatedRoute);
});
});
(0, vitest_1.describe)('when an execution is already defined', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: true });
statusManager.initExecutionObject(structuredClone(step));
});
(0, vitest_1.it)('should not call the callbacks', () => {
(0, vitest_1.expect)(updateRouteHookMock).not.toHaveBeenCalled();
});
});
});
(0, vitest_1.describe)('updateExecution', () => {
(0, vitest_1.beforeEach)(() => {
vitest_1.vi.spyOn(Date, 'now').mockImplementation(() => fixtures_1.SOME_DATE + 10);
});
(0, vitest_1.describe)('when no execution is defined yet', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: false });
});
(0, vitest_1.it)('should throw an error', () => {
// function has to be wrapped into a function https://jestjs.io/docs/expect#tothrowerror
(0, vitest_1.expect)(() => statusManager.updateExecution(structuredClone(step), 'DONE')).toThrow("Can't update empty execution.");
});
});
(0, vitest_1.describe)('when an execution is defined', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: true });
statusManager.updateExecution(structuredClone(step), 'DONE', {
fromAmount: '123',
toAmount: '312',
});
});
(0, vitest_1.it)('should update the execution & call the callbacks with the updated route', () => {
const updatedExecution = Object.assign({}, step.execution, {
fromAmount: '123',
toAmount: '312',
status: 'DONE',
});
const updatedStep = Object.assign({}, step, {
execution: updatedExecution,
});
const updatedRoute = Object.assign({}, route, {
steps: [updatedStep],
});
expectCallbacksToHaveBeenCalledWith(updatedRoute);
});
});
});
(0, vitest_1.describe)('findOrCreateProcess', () => {
(0, vitest_1.describe)('when no execution is defined yet', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: false });
});
(0, vitest_1.it)('should throw an error', () => {
(0, vitest_1.expect)(() => statusManager.findOrCreateProcess({
step: structuredClone(step),
type: 'SWAP',
})).toThrow("Execution hasn't been initialized.");
});
});
(0, vitest_1.describe)('when an execution is defined', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: true });
});
(0, vitest_1.describe)('and the process already exists', () => {
(0, vitest_1.it)('should return the process and not call the callbacks', () => {
const process = statusManager.findOrCreateProcess({
step: structuredClone(step),
type: 'TOKEN_ALLOWANCE',
});
(0, vitest_1.expect)(process).toEqual(step.execution?.process[0]);
(0, vitest_1.expect)(updateRouteHookMock).not.toHaveBeenCalled();
});
});
(0, vitest_1.describe)("and the process doesn't exist", () => {
(0, vitest_1.it)('should create a process and call the callbacks with the updated route', () => {
const process = statusManager.findOrCreateProcess({
step: structuredClone(step),
type: 'CROSS_CHAIN',
});
(0, vitest_1.expect)(process.type).toEqual('CROSS_CHAIN');
(0, vitest_1.expect)(process.status).toEqual('STARTED');
(0, vitest_1.expect)(process.message).toEqual('Preparing bridge transaction');
const updatedExecution = Object.assign({}, step.execution, {
process: [...step.execution.process, process],
});
const updatedStep = Object.assign({}, step, {
execution: updatedExecution,
});
const updatedRoute = Object.assign({}, route, {
steps: [updatedStep],
});
expectCallbacksToHaveBeenCalledWith(updatedRoute);
});
});
});
});
(0, vitest_1.describe)('updateProcess', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: true });
});
(0, vitest_1.describe)('when no process can be found', () => {
(0, vitest_1.it)('should throw an error', () => {
(0, vitest_1.expect)(() => statusManager.updateProcess(structuredClone(step), 'CROSS_CHAIN', 'CANCELLED')).toThrow("Can't find a process for the given type.");
});
});
(0, vitest_1.describe)('when a process is found', () => {
const statuses = [
{ status: 'ACTION_REQUIRED' },
{ status: 'PENDING' },
{ status: 'FAILED', doneAt: true },
{ status: 'DONE', doneAt: true },
{ status: 'CANCELLED', doneAt: true },
];
for (const { status, doneAt } of statuses) {
(0, vitest_1.describe)(`and the status is ${status}`, () => {
(0, vitest_1.it)('should update the process and call the callbacks', () => {
const process = statusManager.updateProcess(structuredClone(step), 'SWAP', status);
(0, vitest_1.expect)(process.type).toEqual('SWAP');
(0, vitest_1.expect)(process.status).toEqual(status);
// expect(process.message).toEqual(
// getProcessMessage('SWAP', status as Status)
// )
doneAt
? (0, vitest_1.expect)(process.doneAt).toBeDefined()
: (0, vitest_1.expect)(process.doneAt).toBeUndefined();
const notUpdateableStatus = status === 'DONE' || status === 'CANCELLED';
const updatedExecution = Object.assign({}, step.execution, {
process: [step.execution.process[0], process],
status: notUpdateableStatus
? step.execution.status
: status,
});
const updatedStep = { ...step, execution: updatedExecution };
const updatedRoute = Object.assign({}, route, {
steps: [updatedStep],
});
expectCallbacksToHaveBeenCalledWith(updatedRoute);
});
});
}
});
});
(0, vitest_1.describe)('removeProcess', () => {
(0, vitest_1.describe)('when no execution is defined yet', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: false });
});
(0, vitest_1.it)('should throw an error', () => {
(0, vitest_1.expect)(() => statusManager.removeProcess(structuredClone(step), 'TOKEN_ALLOWANCE')).toThrow("Execution hasn't been initialized.");
});
});
(0, vitest_1.describe)('when an execution is defined', () => {
(0, vitest_1.beforeEach)(() => {
statusManager = initializeStatusManager({ includingExecution: true });
statusManager.removeProcess(structuredClone(step), 'TOKEN_ALLOWANCE');
});
(0, vitest_1.it)('should remove the process and call the callbacks', () => {
const updatedExecution = Object.assign({}, step.execution, {
process: [step.execution.process[1]],
});
const updatedStep = Object.assign({}, step, {
execution: updatedExecution,
});
const updatedRoute = Object.assign({}, route, {
steps: [updatedStep],
});
expectCallbacksToHaveBeenCalledWith(updatedRoute);
});
});
});
});