UNPKG

@frak-labs/react-sdk

Version:

React SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.

310 lines (260 loc) 10.3 kB
/** * Tests for useReferralInteraction hook * Tests automatic referral interaction submission */ import { vi } from "vitest"; vi.mock("@frak-labs/core-sdk/actions"); vi.mock("../useFrakClient"); vi.mock("../useWalletStatus"); vi.mock("../utils/useFrakContext"); import type { FrakContext, WalletStatusReturnType } from "@frak-labs/core-sdk"; import { processReferral } from "@frak-labs/core-sdk/actions"; import { ClientNotFound } from "@frak-labs/frame-connector"; import { renderHook, waitFor } from "@testing-library/react"; import { describe, expect, test } from "../../../tests/vitest-fixtures"; import { useFrakClient } from "../useFrakClient"; import { useWalletStatus } from "../useWalletStatus"; import { useFrakContext } from "../utils/useFrakContext"; import { useReferralInteraction } from "./useReferralInteraction"; describe("useReferralInteraction", () => { test("should return processing when wallet status is not available", ({ queryWrapper, mockFrakClient, }) => { vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useFrakContext).mockReturnValue({ frakContext: null, updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: undefined, isSuccess: false, isPending: true, } as ReturnType<typeof useWalletStatus>); const { result } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); // Query is disabled when wallet status is not available, status remains pending expect(result.current).toBe("processing"); }); test("should process referral successfully", async ({ queryWrapper, mockFrakClient, }) => { const mockReferralState = "success"; const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; const mockFrakContext: FrakContext = { r: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useFrakContext).mockReturnValue({ frakContext: mockFrakContext, updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); vi.mocked(processReferral).mockResolvedValue(mockReferralState); const { result } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); await waitFor(() => { expect(result.current).toEqual(mockReferralState); }); expect(processReferral).toHaveBeenCalledWith(mockFrakClient, { walletStatus: mockWalletStatus, frakContext: mockFrakContext, options: undefined, }); }); test("should process referral with options", async ({ queryWrapper, mockFrakClient, }) => { const mockReferralState = "success"; const options = { alwaysAppendUrl: true, }; const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useFrakContext).mockReturnValue({ frakContext: { r: "0x7890123456789012345678901234567890123456" }, updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); vi.mocked(processReferral).mockResolvedValue(mockReferralState); const { result } = renderHook( () => useReferralInteraction({ options }), { wrapper: queryWrapper.wrapper, } ); await waitFor(() => { expect(result.current).toEqual(mockReferralState); }); expect(processReferral).toHaveBeenCalledWith( mockFrakClient, expect.objectContaining({ options, }) ); }); test("should handle processing state", ({ queryWrapper, mockFrakClient, }) => { const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useFrakContext).mockReturnValue({ frakContext: { r: "0x9999999999999999999999999999999999999999" }, updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); // Mock processReferral to never resolve (simulate pending) vi.mocked(processReferral).mockImplementation( () => new Promise(() => {}) ); const { result } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); expect(result.current).toBe("processing"); }); test("should handle errors", async ({ queryWrapper, mockFrakClient }) => { const error = new Error("Referral processing failed"); const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useFrakContext).mockReturnValue({ frakContext: { r: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" }, updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); vi.mocked(processReferral).mockRejectedValue(error); const { result } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); await waitFor(() => { expect(result.current).toEqual(error); }); }); test("should throw ClientNotFound when client is not available", async ({ queryWrapper, }) => { const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(undefined); vi.mocked(useFrakContext).mockReturnValue({ frakContext: { r: "0xcccccccccccccccccccccccccccccccccccccccc" }, updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); const { result } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); await waitFor(() => { expect(result.current).toBeInstanceOf(ClientNotFound); }); }); test("should update query key when referrer changes", async ({ queryWrapper, mockFrakClient, }) => { const mockReferralState = "success"; const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); vi.mocked(processReferral).mockResolvedValue(mockReferralState); // Start with one referrer vi.mocked(useFrakContext).mockReturnValue({ frakContext: { r: "0x1111111111111111111111111111111111111111" }, updateContext: vi.fn(), }); const { rerender } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); await waitFor(() => { expect(processReferral).toHaveBeenCalledTimes(1); }); // Change referrer vi.mocked(useFrakContext).mockReturnValue({ frakContext: { r: "0x2222222222222222222222222222222222222222" }, updateContext: vi.fn(), }); rerender(); // Query should re-run with new referrer await waitFor(() => { expect(processReferral).toHaveBeenCalledTimes(2); }); }); test("should handle no referrer in context", async ({ queryWrapper, mockFrakClient, }) => { const mockReferralState = "success"; const mockWalletStatus: WalletStatusReturnType = { key: "connected", wallet: "0x1234567890123456789012345678901234567890", }; vi.mocked(useFrakClient).mockReturnValue(mockFrakClient); vi.mocked(useFrakContext).mockReturnValue({ frakContext: null, // No referrer updateContext: vi.fn(), }); vi.mocked(useWalletStatus).mockReturnValue({ data: mockWalletStatus, isSuccess: true, isPending: false, } as ReturnType<typeof useWalletStatus>); vi.mocked(processReferral).mockResolvedValue(mockReferralState); const { result } = renderHook(() => useReferralInteraction(), { wrapper: queryWrapper.wrapper, }); await waitFor(() => { expect(result.current).toEqual(mockReferralState); }); expect(processReferral).toHaveBeenCalledWith( mockFrakClient, expect.objectContaining({ frakContext: null, }) ); }); });