import { fireEvent, render } from '@testing-library/react-native' import * as React from 'react' import { Provider } from 'react-redux' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' import NftsInfoCarousel from 'src/nfts/NftsInfoCarousel' import { NetworkId } from 'src/transactions/types' import networkConfig from 'src/web3/networkConfig' import { createMockStore, getMockStackScreenProps } from 'test/utils' import { mockNftAllFields, mockNftMinimumFields, mockNftNullMetadata } from 'test/values' jest.mock('src/utils/Logger') describe('NftsInfoCarousel', () => { beforeEach(() => { jest.clearAllMocks() }) it('renders correctly with one Nft', () => { const { queryByTestId, getByTestId, getByText } = render( ) // Correct image source should be rendered expect(getByTestId('NftsInfoCarousel/MainVideo').children[0]).toHaveProp( 'source', expect.objectContaining({ uri: mockNftAllFields.media[1].gateway, headers: { origin: networkConfig.nftsAppUrl, }, }) ) expect(getByText(mockNftAllFields.metadata!.name)).toBeTruthy() // The image carousel should not render if there is only one Nft expect(queryByTestId('NftsInfoCarousel/NftImageCarousel')).toBeNull() }) it('renders correctly with two valid Nfts', () => { const nft1Thumbnail = `NftsInfoCarousel/NftThumbnail/${mockNftAllFields.contractAddress}-${mockNftAllFields.tokenId}` const nft2Thumbnail = `NftsInfoCarousel/NftThumbnail/${mockNftMinimumFields.contractAddress}-${mockNftMinimumFields.tokenId}` const { getByTestId, getByText } = render( ) // Carousel should be rendered expect(getByTestId('NftsInfoCarousel/NftImageCarousel')).toBeTruthy() // Correct Nft Video and name should be rendered expect(getByTestId('NftsInfoCarousel/MainVideo').children[0]).toHaveProp( 'source', expect.objectContaining({ uri: mockNftAllFields.media[1].gateway, headers: { origin: networkConfig.nftsAppUrl, }, }) ) expect(getByText(mockNftAllFields.metadata!.name)).toBeTruthy() // Toggle to Second Nft fireEvent.press(getByTestId(nft2Thumbnail)) expect(getByText(mockNftMinimumFields.metadata!.name)).toBeTruthy() expect(getByTestId('NftsInfoCarousel/MainImage')).toHaveProp( 'source', expect.objectContaining({ uri: mockNftMinimumFields.media[0].gateway, headers: { origin: networkConfig.nftsAppUrl, }, }) ) // Return to first Nft fireEvent.press(getByTestId(nft1Thumbnail)) expect(getByText(mockNftAllFields.metadata!.name)).toBeTruthy() expect(getByTestId('NftsInfoCarousel/MainVideo').children[0]).toHaveProp( 'source', expect.objectContaining({ uri: mockNftAllFields.media[1].gateway, headers: { origin: networkConfig.nftsAppUrl, }, }) ) }) it('renders full screen error when no Nft(s)', () => { const { getByTestId, queryByTestId } = render( ) expect(getByTestId('NftsInfoCarousel/NftsLoadErrorScreen')).toBeTruthy() expect(queryByTestId('NftsInfoCarousel')).toBeNull() }) it('renders error image state on Nft null metadata', () => { const { getByText } = render( ) expect(getByText('nftInfoCarousel.nftImageLoadError')).toBeTruthy() }) it('image carousel should render Nfts with null metadata as red info icon', () => { const { getByTestId, getByText, queryByText } = render( ) // The Nft with null metadata will render with an error icon in carousel and display error text when selected expect(queryByText('nftInfoCarousel.nftImageLoadError')).toBeNull() expect(getByTestId('NftsInfoCarousel/ImageErrorIcon')).toBeTruthy() expect(getByTestId('NftsInfoCarousel/NftImageCarousel')).toBeTruthy() fireEvent.press( getByTestId( `NftsInfoCarousel/NftThumbnail/${mockNftNullMetadata.contractAddress}-${mockNftNullMetadata.tokenId}` ) ) expect(getByText('nftInfoCarousel.nftImageLoadError')).toBeTruthy() expect(getByText('nftInfoCarousel.viewOnCeloExplorer')).toBeTruthy() }) it('opens link for Explorer for celo nfts', () => { const { getByTestId } = render( ) fireEvent.press(getByTestId('ViewOnExplorer')) expect(navigate).toHaveBeenCalledWith(Screens.WebViewScreen, { uri: `https://explorer.celo.org/alfajores/token/${mockNftMinimumFields.contractAddress}/instance/${mockNftMinimumFields.tokenId}/metadata`, }) }) it.each([ { testName: 'decimal', tokenIdInNft: '45', tokenIdInUri: '45' }, { testName: 'hex', tokenIdInNft: '0x0000004c', tokenIdInUri: '76' }, { testName: 'large hex', tokenIdInNft: '0x11842BAC5120955D95BFC2FD375F60D2BA881662748B933595554035C0B677C6', tokenIdInUri: '7922843659213713760827004610977604020289089222988994642652878954023871739846', }, ])( 'opens link for Explorer for ethereum nfts and $testName token id', ({ tokenIdInNft, tokenIdInUri }) => { const { getByTestId } = render( ) fireEvent.press(getByTestId('ViewOnExplorer')) expect(navigate).toHaveBeenCalledWith(Screens.WebViewScreen, { uri: `https://sepolia.etherscan.io/nft/${mockNftMinimumFields.contractAddress}/${tokenIdInUri}`, }) } ) it('should not render link to explorer if no token id is provided', () => { const noTokenId = mockNftMinimumFields noTokenId.tokenId = null as unknown as string const { queryByTestId } = render( ) expect(queryByTestId('ViewOnExplorer')).toBeNull() }) })