import { beforeEach, describe, expect, it, vi } from "vitest"; import mockRequire from "mock-require"; const gqlRequestMock = { request: vi.fn() }; const getPaymentTypeMock = vi.fn(() => "Visa"); const handlePaymentValidationErrorMock = vi.fn(); let handleInvoiceBasedPayment; beforeEach(() => { vi.resetModules(); vi.clearAllMocks(); mockRequire("../../../graphql-client/graphql-client", { client: gqlRequestMock }); mockRequire("../getPaymentType", getPaymentTypeMock); mockRequire("../handlePaymentValidationError", handlePaymentValidationErrorMock); handleInvoiceBasedPayment = require("../handleInvoiceBasedPayment"); gqlRequestMock.request .mockResolvedValueOnce({ jobs: [ { id: "job123", bodyshop: { id: "shop123", intellipay_config: { payment_map: { visa: "Visa" } } } } ] }) .mockResolvedValueOnce({ id: "payment123" }) .mockResolvedValueOnce({ insert_payment_response: { returning: [{ id: "response123" }] } }); }); describe("handleInvoiceBasedPayment", () => { const mockLogger = { log: vi.fn() }; const mockRes = { sendStatus: vi.fn() }; const values = { merchantid: "m123", invoice: "INV-001", total: 100.0, authcode: "AUTH123", cardtype: "visa", paymentid: "P789" }; const logMeta = { op: "abc123" }; it("processes a valid invoice-based payment", async () => { await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); expect(gqlRequestMock.request).toHaveBeenCalledTimes(3); expect(getPaymentTypeMock).toHaveBeenCalledWith({ visa: "Visa" }, "visa"); expect(mockRes.sendStatus).toHaveBeenCalledWith(200); expect(handlePaymentValidationErrorMock).not.toHaveBeenCalled(); }); it("handles missing merchantid with validation error", async () => { const invalidValues = { ...values, merchantid: undefined }; await handleInvoiceBasedPayment(invalidValues, mockLogger, logMeta, mockRes); expect(handlePaymentValidationErrorMock).toHaveBeenCalledWith( mockRes, mockLogger, "intellipay-postback-no-merchantid", "Merchant ID is missing", logMeta ); expect(gqlRequestMock.request).not.toHaveBeenCalled(); }); it("handles job not found with validation error", async () => { gqlRequestMock.request.mockReset(); gqlRequestMock.request.mockResolvedValueOnce({ jobs: [] }); await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); expect(handlePaymentValidationErrorMock).toHaveBeenCalledWith( mockRes, mockLogger, "intellipay-postback-job-not-found", "Job not found", logMeta, 200 ); }); it("handles missing bodyshop with validation error", async () => { gqlRequestMock.request.mockReset(); gqlRequestMock.request.mockResolvedValueOnce({ jobs: [{ id: "job123", bodyshop: null }] }); await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); expect(handlePaymentValidationErrorMock).toHaveBeenCalledWith( mockRes, mockLogger, "intellipay-postback-bodyshop-not-found", "Bodyshop not found", logMeta ); }); it("logs all expected stages of the process", async () => { await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); const logTags = mockLogger.log.mock.calls.map(([tag]) => tag); expect(logTags).toContain("intellipay-postback-invoice-job-fetched"); expect(logTags).toContain("intellipay-postback-invoice-payment-success"); expect(logTags).toContain("intellipay-postback-invoice-response-success"); }); });