/** * @jest-environment jsdom */ import "../../../__tests__/test-helpers/dom-polyfill"; import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets"; import { act, renderHook } from "@testing-library/react"; import BigNumber from "bignumber.js"; import { checkAccountSupported } from "../../../account/index"; import ethBridge from "../../../families/evm/bridge/mock"; import { genTokenAccount } from "@ledgerhq/ledger-wallet-framework/mocks/account"; import { genAccount } from "../../../mock/account"; import { useUpdateMaxAmount, ZERO } from "./useUpdateMaxAmount"; // Needs to be mocked since userSupportedCurrencies is initially empty. jest.mock("../../../account/support"); const mockedCheckAccount = jest.mocked(checkAccountSupported); // Mock to use a custom estimate value and test the result. jest.mock("../../../families/evm/bridge/mock"); const mockedEstimateMaxSpendable = jest.mocked(ethBridge.accountBridge.estimateMaxSpendable); const ETH = getCryptoCurrencyById("ethereum"); const USDT = { type: "TokenCurrency" as const, id: "ethereum/erc20/usd_tether__erc20_", name: "Tether USD (ERC-20)", ticker: "USDT", units: [{ name: "Tether USD", code: "USDT", magnitude: 6 }], contractAddress: "0xdac17f958d2ee523a2206206994597c13d831ec7", parentCurrency: ETH, tokenType: "erc20" as const, }; const parentAccount = genAccount("parent-account", { currency: ETH, }); const account = genTokenAccount(1, parentAccount, USDT); describe("updateAmountUsingMax", () => { const setFromAmount = jest.fn(); const defaultProps = { setFromAmount, account, parentAccount, bridge: ethBridge.accountBridge as any, feesStrategy: "slow" as any, }; beforeAll(() => { mockedCheckAccount.mockImplementation(() => null); }); afterAll(() => { mockedCheckAccount.mockReset(); }); beforeEach(() => { setFromAmount.mockClear(); }); it("should toggle the amount", async () => { const amount = new BigNumber(0.5); mockedEstimateMaxSpendable.mockResolvedValue(amount); const { result } = renderHook(useUpdateMaxAmount, { initialProps: defaultProps, }); expect(result.current.isMaxEnabled).toBe(false); expect(setFromAmount).toHaveBeenCalledTimes(0); await act(async () => result.current.toggleMax()); expect(result.current.isMaxEnabled).toBe(true); // Lest resort solution, since waitFor and other helpers will not work here. expect(setFromAmount).toHaveBeenCalledTimes(1); expect(setFromAmount.mock.calls[0][0]).toBe(amount); setFromAmount.mockClear(); await act(async () => result.current.toggleMax()); expect(result.current.isMaxEnabled).toBe(false); expect(setFromAmount).toHaveBeenCalledTimes(1); expect(setFromAmount.mock.calls[0][0]).toBe(ZERO); }); it("should update the max amount whenever the dependencies change", async () => { const { result, rerender } = renderHook(useUpdateMaxAmount, { initialProps: defaultProps, }); const feesGenerator = (function* feesGenerator() { const feesArray = ["medium", "fast", "custom", "slow"]; let index = 0; while (true) { yield feesArray[index]; index = (index + 1) % feesArray.length; } })(); // setFromAmount, account, parentAccount, feesStrategy const propsVariants = [ { ...defaultProps, account: { ...account }, }, { ...defaultProps, parentAccount: { ...parentAccount }, }, { ...defaultProps, feesStrategy: feesGenerator.next().value, }, ]; // Updating dependencies when the toggle is off should not do anything. propsVariants.forEach(rerender); expect(setFromAmount).toHaveBeenCalledTimes(0); mockedEstimateMaxSpendable.mockResolvedValue(new BigNumber(0)); await act(async () => result.current.toggleMax()); // Checking that updating dependencies update the max amount when the toggle is on. let idx = 1; for await (const props of propsVariants) { const amount = new BigNumber(idx); setFromAmount.mockReset(); mockedEstimateMaxSpendable.mockResolvedValue(amount); await act(async () => rerender(props)); expect(setFromAmount).toHaveBeenCalledTimes(1); expect(setFromAmount.mock.calls[0][0]).toBe(amount); idx += 1; } }); });