From 7ac5c8111f1cea88aa880d2a843ea232cae84c33 Mon Sep 17 00:00:00 2001 From: jahabeebs <47253537+jahabeebs@users.noreply.github.com> Date: Fri, 20 Sep 2024 19:05:43 -0500 Subject: [PATCH] feat: add tests Signed-off-by: jahabeebs <47253537+jahabeebs@users.noreply.github.com> --- .../src/services/eboActor.ts | 1 - .../tests/exceptions/errorFactory.spec.ts | 58 +++++++++++ .../tests/services/eboActor.spec.ts | 97 +++++++++++++++++++ 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 packages/automated-dispute/tests/exceptions/errorFactory.spec.ts diff --git a/packages/automated-dispute/src/services/eboActor.ts b/packages/automated-dispute/src/services/eboActor.ts index 174522e..a33cad6 100644 --- a/packages/automated-dispute/src/services/eboActor.ts +++ b/packages/automated-dispute/src/services/eboActor.ts @@ -300,7 +300,6 @@ export class EboActor { blockNumber, registry: this.registry, }); - await ErrorHandler.handle(customError, { terminateActor: () => { throw customError; diff --git a/packages/automated-dispute/tests/exceptions/errorFactory.spec.ts b/packages/automated-dispute/tests/exceptions/errorFactory.spec.ts new file mode 100644 index 0000000..6bdc433 --- /dev/null +++ b/packages/automated-dispute/tests/exceptions/errorFactory.spec.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from "vitest"; + +import { CustomContractError } from "../../src/exceptions/customContractError"; +import { ErrorFactory } from "../../src/exceptions/errorFactory"; + +describe("ErrorFactory", () => { + it("creates a CustomContractError with the correct name and strategy for known errors", () => { + const errorName = "ValidatorLib_InvalidResponseBody"; + const error = ErrorFactory.createError(errorName); + + expect(error).toBeInstanceOf(CustomContractError); + expect(error.name).toBe(errorName); + expect(error.strategy).toEqual({ + shouldNotify: false, + shouldTerminate: false, + shouldReenqueue: true, + }); + }); + + it("creates a CustomContractError with default strategy for unknown errors", () => { + const errorName = "UnknownError"; + const error = ErrorFactory.createError(errorName); + + expect(error).toBeInstanceOf(CustomContractError); + expect(error.name).toBe(errorName); + expect(error.strategy).toEqual({ + shouldNotify: true, + shouldTerminate: false, + shouldReenqueue: true, + }); + }); + + it("creates a CustomContractError with custom action for specific errors", () => { + const errorName = "BondEscalationModule_InvalidDispute"; + const error = ErrorFactory.createError(errorName); + + expect(error).toBeInstanceOf(CustomContractError); + expect(error.name).toBe(errorName); + expect(error.strategy).toHaveProperty("customAction"); + expect(typeof error.strategy.customAction).toBe("function"); + }); + + it("creates different CustomContractErrors for different error names", () => { + const error1 = ErrorFactory.createError("ValidatorLib_InvalidResponseBody"); + const error2 = ErrorFactory.createError("BondEscalationAccounting_InsufficientFunds"); + + expect(error1.name).not.toBe(error2.name); + expect(error1.strategy).not.toEqual(error2.strategy); + }); + + it("creates CustomContractErrors with consistent strategies for the same error name", () => { + const errorName = "ValidatorLib_InvalidResponseBody"; + const error1 = ErrorFactory.createError(errorName); + const error2 = ErrorFactory.createError(errorName); + + expect(error1.strategy).toEqual(error2.strategy); + }); +}); diff --git a/packages/automated-dispute/tests/services/eboActor.spec.ts b/packages/automated-dispute/tests/services/eboActor.spec.ts index 1a2618e..df7c154 100644 --- a/packages/automated-dispute/tests/services/eboActor.spec.ts +++ b/packages/automated-dispute/tests/services/eboActor.spec.ts @@ -1,7 +1,10 @@ +import { ContractFunctionRevertedError } from "viem"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { ErrorHandler } from "../../src/exceptions/errorHandler.js"; import { CustomContractError, + ErrorFactory, PastEventEnqueueError, RequestMismatch, } from "../../src/exceptions/index.js"; @@ -414,4 +417,98 @@ describe("EboActor", () => { expect(canBeTerminated).toBe(true); }); }); + + describe("onRequestCreated", () => { + it("should handle ContractFunctionRevertedError by creating CustomContractError via ErrorFactory and calling ErrorHandler", async () => { + const { actor } = mocks.buildEboActor(request, logger); + const event: EboEvent<"RequestCreated"> = { + name: "RequestCreated", + blockNumber: 1n, + logIndex: 0, + requestId: request.id, + metadata: { + chainId: request.chainId, + epoch: request.epoch, + requestId: request.id, + request: request.prophetData, + }, + }; + + const errorName = "ContractFunctionRevertedError"; + const contractError = new ContractFunctionRevertedError({ + data: { + errorName: errorName, + }, + } as any); + + actor["proposeResponse"] = vi.fn().mockRejectedValue(contractError); + + const errorFactorySpy = vi.spyOn(ErrorFactory, "createError"); + const customError = new CustomContractError(errorName, { + shouldNotify: false, + shouldTerminate: false, + shouldReenqueue: true, + }); + errorFactorySpy.mockReturnValue(customError); + + const errorHandlerSpy = vi.spyOn(ErrorHandler, "handle").mockResolvedValue(); + + await actor["onRequestCreated"](event); + + expect(errorFactorySpy).toHaveBeenCalledWith(errorName); + expect(customError["context"]).toEqual({ + event, + registry: actor["registry"], + }); + expect(errorHandlerSpy).toHaveBeenCalledWith(customError, { + reenqueueEvent: expect.any(Function), + }); + + errorFactorySpy.mockRestore(); + errorHandlerSpy.mockRestore(); + }); + }); + + describe("settleDispute", () => { + it("should handle ContractFunctionRevertedError and use ErrorFactory in settleDispute", async () => { + const { actor, registry } = mocks.buildEboActor(request, logger); + const response = mocks.buildResponse(request); + const dispute = mocks.buildDispute(request, response); + + const errorName = "ContractFunctionRevertedError"; + const contractError = new ContractFunctionRevertedError({ + data: { + errorName: errorName, + }, + } as any); + + actor["protocolProvider"].settleDispute = vi.fn().mockRejectedValue(contractError); + + const errorFactorySpy = vi.spyOn(ErrorFactory, "createError"); + const customError = new CustomContractError(errorName, { + shouldNotify: true, + shouldTerminate: false, + shouldReenqueue: false, + }); + errorFactorySpy.mockReturnValue(customError); + + const errorHandlerSpy = vi.spyOn(ErrorHandler, "handle").mockResolvedValue(); + + await actor["settleDispute"](request, response, dispute); + + expect(errorFactorySpy).toHaveBeenCalledWith(errorName); + expect(customError["context"]).toEqual({ + request, + response, + dispute, + registry, + }); + expect(errorHandlerSpy).toHaveBeenCalledWith(customError, { + terminateActor: expect.any(Function), + }); + + errorFactorySpy.mockRestore(); + errorHandlerSpy.mockRestore(); + }); + }); });