|
| 1 | +import { Mockttp } from 'mockttp'; |
| 2 | +import { withFixtures } from '../../framework/fixtures/FixtureHelper'; |
| 3 | +import { LocalNode, LocalNodeType } from '../../framework/types'; |
| 4 | +import { loginToApp } from '../../flows/wallet.flow'; |
| 5 | +import WalletView from '../../page-objects/wallet/WalletView'; |
| 6 | +import QuoteView from '../../page-objects/swaps/QuoteView'; |
| 7 | +import SwapTrendingTokensView from '../../page-objects/swaps/SwapTrendingTokensView'; |
| 8 | +import { Assertions } from '../../framework'; |
| 9 | +import CommonView from '../../page-objects/CommonView'; |
| 10 | +import TokenOverview from '../../page-objects/wallet/TokenOverview'; |
| 11 | +import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; |
| 12 | +import { prepareSwapsTestEnvironment } from '../../helpers/swap/prepareSwapsTestEnvironment'; |
| 13 | +import { testSpecificMock } from '../../helpers/swap/bridge-mocks'; |
| 14 | +import { GET_QUOTE_ETH_USDC_RESPONSE } from '../../helpers/swap/constants'; |
| 15 | +import { getDecodedProxiedURL } from '../notifications/utils/helpers'; |
| 16 | +import { SmokeTrade } from '../../tags'; |
| 17 | +import { AnvilPort } from '../../framework/fixtures/FixtureUtils'; |
| 18 | +import { AnvilManager } from '../../seeder/anvil-manager'; |
| 19 | +import enContent from '../../../locales/languages/en.json'; |
| 20 | +import { createRemoteFeatureFlagsMock } from '../../api-mocking/helpers/remoteFeatureFlagsHelper'; |
| 21 | +import { setupMockRequest } from '../../api-mocking/helpers/mockHelpers'; |
| 22 | + |
| 23 | +const BASE_CHAIN_ID_DECIMAL = '8453'; |
| 24 | + |
| 25 | +const ETHEREUM_TRENDING_ASSET_ID = |
| 26 | + 'eip155:1/erc20:0x1111111111111111111111111111111111111111'; |
| 27 | +const BASE_TRENDING_ASSET_ID = |
| 28 | + 'eip155:8453/erc20:0x2222222222222222222222222222222222222222'; |
| 29 | + |
| 30 | +const TRENDING_ALL_NETWORKS_RESPONSE = [ |
| 31 | + { |
| 32 | + assetId: ETHEREUM_TRENDING_ASSET_ID, |
| 33 | + symbol: 'ETHX', |
| 34 | + name: 'Ethereum Trending', |
| 35 | + decimals: 18, |
| 36 | + price: '10', |
| 37 | + aggregatedUsdVolume: 2000000, |
| 38 | + marketCap: 100000000, |
| 39 | + priceChangePct: { |
| 40 | + h24: '0.2', |
| 41 | + h6: '0.1', |
| 42 | + h1: '0.01', |
| 43 | + m5: '0.001', |
| 44 | + }, |
| 45 | + }, |
| 46 | + { |
| 47 | + assetId: BASE_TRENDING_ASSET_ID, |
| 48 | + symbol: 'BASEX', |
| 49 | + name: 'Base Trending', |
| 50 | + decimals: 18, |
| 51 | + price: '8', |
| 52 | + aggregatedUsdVolume: 3000000, |
| 53 | + marketCap: 200000000, |
| 54 | + priceChangePct: { |
| 55 | + h24: '0.3', |
| 56 | + h6: '0.15', |
| 57 | + h1: '0.02', |
| 58 | + m5: '0.002', |
| 59 | + }, |
| 60 | + }, |
| 61 | +]; |
| 62 | + |
| 63 | +const TRENDING_BASE_ONLY_RESPONSE = [TRENDING_ALL_NETWORKS_RESPONSE[1]]; |
| 64 | + |
| 65 | +const setupSwapsTrendingTokensMock = async (mockServer: Mockttp) => { |
| 66 | + const { response } = createRemoteFeatureFlagsMock({ |
| 67 | + swapsTrendingTokens: true, |
| 68 | + }); |
| 69 | + |
| 70 | + await setupMockRequest( |
| 71 | + mockServer, |
| 72 | + { |
| 73 | + requestMethod: 'GET', |
| 74 | + url: /client-config\.api\.cx\.metamask\.io\/v1\/flags/i, |
| 75 | + response, |
| 76 | + responseCode: 200, |
| 77 | + }, |
| 78 | + 1001, |
| 79 | + ); |
| 80 | +}; |
| 81 | + |
| 82 | +const setupTrendingTokensMock = async (mockServer: Mockttp) => { |
| 83 | + await mockServer |
| 84 | + .forGet('/proxy') |
| 85 | + .matching((request) => { |
| 86 | + const decodedUrl = getDecodedProxiedURL(request.url); |
| 87 | + return /\/v3\/tokens\/trending/.test(decodedUrl); |
| 88 | + }) |
| 89 | + .asPriority(1001) |
| 90 | + .thenCallback((request) => { |
| 91 | + const decodedUrl = getDecodedProxiedURL(request.url); |
| 92 | + const isBaseOnlyRequest = decodedUrl.includes( |
| 93 | + `chainIds=eip155:${BASE_CHAIN_ID_DECIMAL}`, |
| 94 | + ); |
| 95 | + |
| 96 | + return { |
| 97 | + statusCode: 200, |
| 98 | + json: isBaseOnlyRequest |
| 99 | + ? TRENDING_BASE_ONLY_RESPONSE |
| 100 | + : TRENDING_ALL_NETWORKS_RESPONSE, |
| 101 | + }; |
| 102 | + }); |
| 103 | +}; |
| 104 | + |
| 105 | +const setupQuoteFallbackMock = async (mockServer: Mockttp) => { |
| 106 | + await setupMockRequest( |
| 107 | + mockServer, |
| 108 | + { |
| 109 | + requestMethod: 'GET', |
| 110 | + url: /getQuote/i, |
| 111 | + response: GET_QUOTE_ETH_USDC_RESPONSE, |
| 112 | + responseCode: 200, |
| 113 | + }, |
| 114 | + 1000, |
| 115 | + ); |
| 116 | +}; |
| 117 | + |
| 118 | +const openSwapFromWalletActions = async () => { |
| 119 | + await loginToApp(); |
| 120 | + await prepareSwapsTestEnvironment(); |
| 121 | + await WalletView.tapWalletSwapButton(); |
| 122 | +}; |
| 123 | + |
| 124 | +const withBridgeFixtures = async (run: () => Promise<void>) => { |
| 125 | + await withFixtures( |
| 126 | + { |
| 127 | + fixture: ({ localNodes }: { localNodes?: LocalNode[] }) => { |
| 128 | + const node = localNodes?.[0] as unknown as AnvilManager; |
| 129 | + const rpcPort = |
| 130 | + node instanceof AnvilManager |
| 131 | + ? (node.getPort() ?? AnvilPort()) |
| 132 | + : undefined; |
| 133 | + |
| 134 | + return new FixtureBuilder() |
| 135 | + .withNetworkController({ |
| 136 | + providerConfig: { |
| 137 | + chainId: '0x1', |
| 138 | + rpcUrl: `http://localhost:${rpcPort ?? AnvilPort()}`, |
| 139 | + type: 'custom', |
| 140 | + nickname: 'Localhost', |
| 141 | + ticker: 'ETH', |
| 142 | + }, |
| 143 | + }) |
| 144 | + .withDisabledSmartTransactions() |
| 145 | + .build(); |
| 146 | + }, |
| 147 | + localNodeOptions: [ |
| 148 | + { |
| 149 | + type: LocalNodeType.anvil, |
| 150 | + options: { |
| 151 | + chainId: 1, |
| 152 | + }, |
| 153 | + }, |
| 154 | + ], |
| 155 | + restartDevice: true, |
| 156 | + testSpecificMock: async (mockServer: Mockttp) => { |
| 157 | + await testSpecificMock(mockServer); |
| 158 | + await setupSwapsTrendingTokensMock(mockServer); |
| 159 | + await setupTrendingTokensMock(mockServer); |
| 160 | + await setupQuoteFallbackMock(mockServer); |
| 161 | + }, |
| 162 | + }, |
| 163 | + run, |
| 164 | + ); |
| 165 | +}; |
| 166 | + |
| 167 | +describe(SmokeTrade('Swap Trending Tokens (Bridge zero-state)'), () => { |
| 168 | + beforeEach(() => { |
| 169 | + jest.setTimeout(180000); |
| 170 | + }); |
| 171 | + |
| 172 | + it('zero-state trending supports filters then row navigation', async () => { |
| 173 | + await withBridgeFixtures(async () => { |
| 174 | + await openSwapFromWalletActions(); |
| 175 | + |
| 176 | + await SwapTrendingTokensView.expectSectionVisible(); |
| 177 | + await SwapTrendingTokensView.expectNoInnerList(); |
| 178 | + |
| 179 | + await SwapTrendingTokensView.scrollToFilters(); |
| 180 | + |
| 181 | + await SwapTrendingTokensView.openPriceFilter(); |
| 182 | + await SwapTrendingTokensView.expectPriceBottomSheetVisible(); |
| 183 | + await Assertions.expectTextDisplayed(enContent.trending.high_to_low, { |
| 184 | + description: 'Default price change sort should be high to low', |
| 185 | + }); |
| 186 | + await SwapTrendingTokensView.closeBottomSheet(); |
| 187 | + |
| 188 | + await SwapTrendingTokensView.openTimeFilter(); |
| 189 | + await SwapTrendingTokensView.expectTimeBottomSheetVisible(); |
| 190 | + await SwapTrendingTokensView.selectTimeSixHours(); |
| 191 | + |
| 192 | + await SwapTrendingTokensView.openNetworkFilter(); |
| 193 | + await SwapTrendingTokensView.expectNetworkBottomSheetVisible(); |
| 194 | + await SwapTrendingTokensView.selectNetworkByName('Base'); |
| 195 | + |
| 196 | + await SwapTrendingTokensView.expectTokenRowVisible( |
| 197 | + BASE_TRENDING_ASSET_ID, |
| 198 | + ); |
| 199 | + await SwapTrendingTokensView.expectTokenRowNotVisible( |
| 200 | + ETHEREUM_TRENDING_ASSET_ID, |
| 201 | + ); |
| 202 | + |
| 203 | + await SwapTrendingTokensView.tapTokenRow(BASE_TRENDING_ASSET_ID); |
| 204 | + await Assertions.expectElementToBeVisible(TokenOverview.tokenPrice, { |
| 205 | + timeout: 10000, |
| 206 | + description: 'Token details should open from trending token row tap', |
| 207 | + }); |
| 208 | + |
| 209 | + await CommonView.tapBackButton(); |
| 210 | + await SwapTrendingTokensView.expectSectionVisible(); |
| 211 | + |
| 212 | + await QuoteView.tapSourceAmountInput(); |
| 213 | + await QuoteView.enterAmount('1'); |
| 214 | + |
| 215 | + await SwapTrendingTokensView.expectSectionNotVisible(); |
| 216 | + }); |
| 217 | + }); |
| 218 | +}); |
0 commit comments