import React from 'react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { fireEvent, waitFor } from '@testing-library/react'; import mockState from '../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../test/jest/rendering'; import { KeyringType } from '../../../../shared/constants/keyring'; import { CHAIN_IDS } from '../../../../shared/constants/network'; import { SelectActionModal } from '.'; // Mock BUYABLE_CHAINS_MAP jest.mock('../../../../shared/constants/network', () => ({ ...jest.requireActual('../../../../shared/constants/network'), BUYABLE_CHAINS_MAP: { // MAINNET '0x1': { nativeCurrency: 'ETH', network: 'ethereum', }, // POLYGON '0x89': { nativeCurrency: 'MATIC', network: 'polygon', }, }, })); let openTabSpy; describe('Select Action Modal', () => { beforeAll(() => { jest.clearAllMocks(); Object.defineProperty(global, 'platform', { value: { openTab: jest.fn(), }, }); openTabSpy = jest.spyOn(global.platform, 'openTab'); }); beforeEach(() => { openTabSpy.mockClear(); }); const mockStore = { metamask: { providerConfig: { type: 'test', chainId: CHAIN_IDS.MAINNET, }, cachedBalances: { '0x1': { '0x1': '0x1F4', }, }, preferences: { useNativeCurrencyAsPrimaryCurrency: true, }, useCurrencyRateCheck: true, conversionRate: 2, identities: { '0x1': { address: '0x1', }, }, accounts: { '0x1': { address: '0x1', balance: '0x1F4', }, }, selectedAddress: '0x1', keyrings: [ { type: KeyringType.imported, accounts: ['0x1', '0x2'], }, { type: KeyringType.ledger, accounts: [], }, ], contractExchangeRates: {}, }, }; const store = configureMockStore([thunk])(mockState); it('should render correctly', () => { const { getByTestId } = renderWithProvider(, store); expect(getByTestId('select-action-modal')).toBeDefined(); }); it('should have the Buy native token enabled if chain id is part of supported buyable chains', () => { const mockedStoreWithBuyableChainId = { metamask: { ...mockStore.metamask, providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( mockedStoreWithBuyableChainId, ); const { queryByText } = renderWithProvider( , mockedStore, ); expect(queryByText('Buy')).toBeInTheDocument(); }); it('should open the Buy native token URI when clicking on Buy button for a buyable chain ID', async () => { const mockedStoreWithBuyableChainId = { metamask: { ...mockStore.metamask, providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( mockedStoreWithBuyableChainId, ); const onClose = jest.fn(); const { queryByText } = renderWithProvider( , mockedStore, ); const buyButton = queryByText('Buy'); expect(buyButton).toBeInTheDocument(); expect(buyButton).not.toBeDisabled(); fireEvent.click(buyButton); expect(onClose).toHaveBeenCalledTimes(1); expect(openTabSpy).toHaveBeenCalledTimes(1); await waitFor(() => expect(openTabSpy).toHaveBeenCalledWith({ url: expect.stringContaining(`/buy?metamaskEntry=ext_buy_button`), }), ); }); it('should not have the Buy native token button if chain id is not part of supported buyable chains', () => { const mockedStoreWithUnbuyableChainId = { metamask: { ...mockStore.metamask, providerConfig: { type: 'test', chainId: CHAIN_IDS.FANTOM }, }, }; const mockedStore = configureMockStore([thunk])( mockedStoreWithUnbuyableChainId, ); const { queryByText } = renderWithProvider( , mockedStore, ); const buyButton = queryByText('Buy'); expect(buyButton).not.toBeInTheDocument(); }); it('should have the Bridge button if chain id is a part of supported chains', () => { const mockedAvalancheStore = { ...mockStore, metamask: { ...mockStore.metamask, providerConfig: { ...mockStore.metamask.providerConfig, chainId: '0xa86a', }, }, }; const mockedStore = configureMockStore([thunk])(mockedAvalancheStore); const { queryByText } = renderWithProvider( , mockedStore, ); const bridgeButton = queryByText('Bridge'); expect(bridgeButton).toBeInTheDocument(); }); it('should open the Bridge URI when clicking on Bridge button on supported network', async () => { const onClose = jest.fn(); const mockedAvalancheStore = { ...mockStore, metamask: { ...mockStore.metamask, providerConfig: { ...mockStore.metamask.providerConfig, chainId: '0xa86a', }, }, }; const mockedStore = configureMockStore([thunk])(mockedAvalancheStore); const { queryByText } = renderWithProvider( , mockedStore, ); const bridgeButton = queryByText('Bridge'); expect(bridgeButton).toBeInTheDocument(); fireEvent.click(bridgeButton); expect(onClose).toHaveBeenCalledTimes(1); expect(openTabSpy).toHaveBeenCalledTimes(1); await waitFor(() => expect(openTabSpy).toHaveBeenCalledWith({ url: expect.stringContaining('/bridge?metamaskEntry=ext_bridge_button'), }), ); }); it('should not have the Bridge button if chain id is not part of supported chains', () => { const mockedFantomStore = { ...mockStore, metamask: { ...mockStore.metamask, providerConfig: { ...mockStore.metamask.providerConfig, chainId: '0xfa', }, }, }; const mockedStore = configureMockStore([thunk])(mockedFantomStore); const { queryByText } = renderWithProvider( , mockedStore, ); const buyButton = queryByText('Bridge'); expect(buyButton).not.toBeInTheDocument(); }); it('should have the Swap button if chain id is part of supported buyable chains', () => { const mockedStoreWithSwapableChainId = { metamask: { ...mockStore.metamask, providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( mockedStoreWithSwapableChainId, ); const { queryByText } = renderWithProvider( , mockedStore, ); expect(queryByText('Swap')).toBeInTheDocument(); }); it('should have the Send button if chain id is part of supported buyable chains', () => { const mockedStoreWithSendChainId = { metamask: { ...mockStore.metamask, providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])(mockedStoreWithSendChainId); const { queryByText } = renderWithProvider( , mockedStore, ); expect(queryByText('Send')).toBeInTheDocument(); }); });