import { beforeEach, describe, expect, it, vi } from "vitest"; import mockRequire from "mock-require"; const gqlRequestMock = { request: vi.fn() }; const getPaymentTypeMock = vi.fn(() => "American Express"); const sendPaymentNotificationEmailMock = vi.fn(); let handleCommentBasedPayment; beforeEach(() => { vi.resetModules(); vi.clearAllMocks(); // Mock dependencies using mock-require BEFORE requiring the target module mockRequire("../../../graphql-client/graphql-client", { client: gqlRequestMock }); mockRequire("../getPaymentType", getPaymentTypeMock); mockRequire("../sendPaymentNotificationEmail", sendPaymentNotificationEmailMock); // Now require the module under test handleCommentBasedPayment = require("../handleCommentBasedPayment"); // Chain your GraphQL mocks gqlRequestMock.request .mockResolvedValueOnce({ jobs: [ { id: "c1ffe09c-e7d4-46b3-aac5-f23e39563181", shopid: "bfec8c8c-b7f1-49e0-be4c-524455f4e582" } ] }) .mockResolvedValueOnce({ bodyshops_by_pk: { id: "bfec8c8c-b7f1-49e0-be4c-524455f4e582", intellipay_config: { payment_map: { amex: "American Express" } } } }) .mockResolvedValueOnce({ insert_payments: { returning: [{ id: "5dfda3c4-c0a6-4b09-a73d-176ed0ac6499" }] } }); }); describe("handleCommentBasedPayment", () => { const mockLogger = { log: vi.fn() }; const mockRes = { sendStatus: vi.fn() }; const values = { authcode: "5557301", total: "0.01", origin: "Dejavoo", paymentid: "24294378", cardtype: "Amex" }; const decodedComment = { payments: [{ jobid: "c1ffe09c-e7d4-46b3-aac5-f23e39563181", amount: 0.01 }], userEmail: "test@example.com" }; const logMeta = { op: "xyz123" }; it("processes comment-based payment and returns 200", async () => { await handleCommentBasedPayment(values, decodedComment, mockLogger, logMeta, mockRes); expect(gqlRequestMock.request).toHaveBeenCalledTimes(3); expect(getPaymentTypeMock).toHaveBeenCalledWith({ amex: "American Express" }, "Amex"); expect(sendPaymentNotificationEmailMock).not.toHaveBeenCalled(); expect(mockRes.sendStatus).toHaveBeenCalledWith(200); }); it("sends notification if origin is OneLink and userEmail exists", async () => { const oneLinkValues = { ...values, origin: "OneLink" }; await handleCommentBasedPayment(oneLinkValues, decodedComment, mockLogger, logMeta, mockRes); expect(sendPaymentNotificationEmailMock).toHaveBeenCalledWith( "test@example.com", expect.anything(), expect.anything(), mockLogger, logMeta ); expect(mockRes.sendStatus).toHaveBeenCalledWith(200); }); it("handles decodedComment as a direct array", async () => { const arrayComment = [{ jobid: "c1ffe09c-e7d4-46b3-aac5-f23e39563181", amount: 0.01 }]; await handleCommentBasedPayment(values, arrayComment, mockLogger, logMeta, mockRes); expect(gqlRequestMock.request).toHaveBeenCalledTimes(3); expect(mockRes.sendStatus).toHaveBeenCalledWith(200); }); it("does not send email if origin is OneLink but userEmail is missing", async () => { const commentWithoutEmail = { payments: decodedComment.payments // no userEmail }; const oneLinkValues = { ...values, origin: "OneLink" }; await handleCommentBasedPayment(oneLinkValues, commentWithoutEmail, mockLogger, logMeta, mockRes); expect(sendPaymentNotificationEmailMock).not.toHaveBeenCalled(); expect(mockRes.sendStatus).toHaveBeenCalledWith(200); }); it("logs important stages of the process", async () => { await handleCommentBasedPayment(values, decodedComment, mockLogger, logMeta, mockRes); const logCalls = mockLogger.log.mock.calls.map(([tag]) => tag); expect(logCalls).toContain("intellipay-postback-parsed-comment"); expect(logCalls).toContain("intellipay-postback-payment-success"); }); it("handles missing payment_map safely", async () => { gqlRequestMock.request.mockReset(); // 🧹 Clear previous .mockResolvedValueOnce calls gqlRequestMock.request .mockResolvedValueOnce({ jobs: [{ id: "job1", shopid: "shop1" }] }) .mockResolvedValueOnce({ bodyshops_by_pk: { id: "shop1", intellipay_config: null } }) .mockResolvedValueOnce({ insert_payments: { returning: [{ id: "payment1" }] } }); await handleCommentBasedPayment(values, decodedComment, mockLogger, logMeta, mockRes); expect(getPaymentTypeMock).toHaveBeenCalledWith(undefined, "Amex"); expect(mockRes.sendStatus).toHaveBeenCalledWith(200); }); });