diff --git a/cypress/e2e/swap.test.ts b/cypress/e2e/swap.test.ts index e05a317550..d6ccb0bbc3 100644 --- a/cypress/e2e/swap.test.ts +++ b/cypress/e2e/swap.test.ts @@ -1,13 +1,57 @@ +import { SupportedChainId, WETH9 } from '@uniswap/sdk-core' + +import { getTestSelector } from '../utils' + describe('Swap', () => { + const verifyAmount = (field: 'input' | 'output', amountText: string | null) => { + if (amountText === null) { + cy.get(`#swap-currency-${field} .token-amount-input`).should('not.have.value') + } else { + cy.get(`#swap-currency-${field} .token-amount-input`).should('have.value', amountText) + } + } + + const verifyToken = (field: 'input' | 'output', tokenSymbol: string | null) => { + if (tokenSymbol === null) { + cy.get(`#swap-currency-${field} .token-symbol-container`).should('contain.text', 'Select token') + } else { + cy.get(`#swap-currency-${field} .token-symbol-container`).should('contain.text', tokenSymbol) + } + } + + const selectOutput = (tokenSymbol: string) => { + // open token selector... + cy.contains('Select token').click() + // select token... + cy.contains(tokenSymbol).click() + + cy.get('body') + .then(($body) => { + if ($body.find(getTestSelector('TokenSafetyWrapper')).length) { + return 'I understand' + } + + return 'no-op' // Don't click on anything, a no-op + }) + .then((content) => { + if (content !== 'no-op') { + cy.contains(content).click() + } + }) + + // token selector should close... + cy.contains('Search name or paste address').should('not.exist') + } + before(() => { cy.visit('/swap') }) it('starts with ETH selected by default', () => { - cy.get('#swap-currency-input .token-amount-input').should('have.value', '') - cy.get('#swap-currency-input .token-symbol-container').should('contain.text', 'ETH') - cy.get('#swap-currency-output .token-amount-input').should('not.have.value') - cy.get('#swap-currency-output .token-symbol-container').should('contain.text', 'Select token') + verifyAmount('input', '') + verifyToken('input', 'ETH') + verifyAmount('output', null) + verifyToken('output', null) }) it('can enter an amount into input', () => { @@ -30,24 +74,64 @@ describe('Swap', () => { cy.get('#swap-currency-output .token-amount-input').clear().type('0.0').should('have.value', '0.0') }) - it.skip('can swap ETH for DAI', () => { - cy.get('#swap-currency-output .open-currency-select-button').click() - cy.get('.token-item-0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735').click() - cy.get('#swap-currency-input .token-amount-input').clear().type('0.0000001') - cy.get('#swap-currency-output .token-amount-input').should('not.equal', '') - cy.get('#swap-button').click() - cy.get('#confirm-swap-or-send').should('contain', 'Confirm Swap') - cy.get('[data-cy="confirmation-close-icon"]').click() + it('should have the correct default input/output and token selection should work', () => { + cy.visit('/swap') + verifyToken('input', 'ETH') + verifyToken('output', null) + + selectOutput('WETH') + cy.get(getTestSelector('swap-currency-button')).first().click() + + verifyToken('input', 'WETH') + verifyToken('output', 'ETH') }) - it('add a recipient does not exist unless in expert mode', () => { - cy.get('#add-recipient-button').should('not.exist') + it('should have the correct default input from URL params ', () => { + cy.visit(`/swap?inputCurrency=${WETH9[SupportedChainId.GOERLI].address}`) + + verifyToken('input', 'WETH') + verifyToken('output', null) + + selectOutput('Ether') + cy.get(getTestSelector('swap-currency-button')).first().click() + + verifyToken('input', 'ETH') + verifyToken('output', 'WETH') }) - it.skip('ETH to wETH is same value (wrapped swaps have no price impact)', () => { - cy.get('#swap-currency-output .open-currency-select-button').click() - cy.get('.token-item-0xc778417E063141139Fce010982780140Aa0cD5Ab').click() + it('should have the correct default output from URL params ', () => { + cy.visit(`/swap?outputCurrency=${WETH9[SupportedChainId.GOERLI].address}`) + + verifyToken('input', null) + verifyToken('output', 'WETH') + + cy.get(getTestSelector('swap-currency-button')).first().click() + verifyToken('input', 'WETH') + verifyToken('output', null) + + selectOutput('Ether') + cy.get(getTestSelector('swap-currency-button')).first().click() + + verifyToken('input', 'ETH') + verifyToken('output', 'WETH') + }) + + it('ETH to wETH is same value (wrapped swaps have no price impact)', () => { + cy.visit('/swap') + selectOutput('WETH') cy.get('#swap-currency-input .token-amount-input').clear().type('0.01') cy.get('#swap-currency-output .token-amount-input').should('have.value', '0.01') }) + + it('Opens and closes the settings menu', () => { + cy.visit('/swap') + cy.contains('Settings').should('not.exist') + cy.get(getTestSelector('swap-settings-button')).click() + cy.contains('Slippage tolerance').should('exist') + cy.contains('Transaction deadline').should('exist') + cy.contains('Auto Router API').should('exist') + cy.contains('Expert Mode').should('exist') + cy.get(getTestSelector('swap-settings-button')).click() + cy.contains('Settings').should('not.exist') + }) }) diff --git a/cypress/e2e/token-details.test.ts b/cypress/e2e/token-details.test.ts index 622d155af9..5971dc50e9 100644 --- a/cypress/e2e/token-details.test.ts +++ b/cypress/e2e/token-details.test.ts @@ -1,4 +1,6 @@ -import { getTestSelector } from '../utils' +import { getClassContainsSelector, getTestSelector } from '../utils' + +const UNI_ADDRESS = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984' describe('Token details', () => { before(() => { @@ -7,7 +9,7 @@ describe('Token details', () => { it('Uniswap token should have all information populated', () => { // Uniswap token - cy.visit('/tokens/ethereum/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984') + cy.visit(`/tokens/ethereum/${UNI_ADDRESS}`) // Price chart should be filled in cy.get('[data-cy="chart-header"]').should('include.text', '$') @@ -28,18 +30,16 @@ describe('Token details', () => { // Links section should link out to Etherscan, More analytics, Website, Twitter cy.get('[data-cy="resources-container"]').within(() => { - cy.contains('Etherscan') - .should('have.attr', 'href') - .and('include', 'etherscan.io/address/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984') + cy.contains('Etherscan').should('have.attr', 'href').and('include', `etherscan.io/address/${UNI_ADDRESS}`) cy.contains('More analytics') .should('have.attr', 'href') - .and('include', 'info.uniswap.org/#/tokens/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984') + .and('include', `info.uniswap.org/#/tokens/${UNI_ADDRESS}`) cy.contains('Website').should('have.attr', 'href').and('include', 'uniswap.org') cy.contains('Twitter').should('have.attr', 'href').and('include', 'twitter.com/Uniswap') }) // Contract address should be displayed - cy.contains('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984').should('exist') + cy.contains(UNI_ADDRESS).should('exist') // Swap widget should have this token pre-selected as the “destination” token cy.get(getTestSelector('token-select')).should('include.text', 'UNI') @@ -89,4 +89,28 @@ describe('Token details', () => { .should('include.text', 'Warning') .and('include.text', "This token isn't traded on leading U.S. centralized exchanges") }) + + describe('Swap on Token Detail Page', () => { + const verifyOutputToken = (outputText: string) => { + cy.get(getClassContainsSelector('TokenButtonRow')).last().contains(outputText) + } + + beforeEach(() => { + // On mobile widths, we just link back to /swap instead of rendering the swap component. + cy.viewport(1200, 800) + cy.visit(`/tokens/goerli/${UNI_ADDRESS}`).then(() => { + cy.wait('@eth_blockNumber') + }) + }) + + it('should have the expected output for a tokens detail page', () => { + verifyOutputToken('UNI') + }) + + it('should not share swap state with the main swap page', () => { + verifyOutputToken('UNI') + cy.visit('/swap') + cy.contains('UNI').should('not.exist') + }) + }) }) diff --git a/src/components/Settings/index.tsx b/src/components/Settings/index.tsx index 35c8a3d819..cf4d2a7d1e 100644 --- a/src/components/Settings/index.tsx +++ b/src/components/Settings/index.tsx @@ -186,7 +186,7 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa id="open-settings-dialog-button" aria-label={t`Transaction Settings`} > - + {expertMode ? ( diff --git a/src/pages/Swap/index.tsx b/src/pages/Swap/index.tsx index ff6ca4c298..1cf9f2a828 100644 --- a/src/pages/Swap/index.tsx +++ b/src/pages/Swap/index.tsx @@ -552,6 +552,7 @@ export default function Swap({ className }: { className?: string }) { element={InterfaceElementName.SWAP_TOKENS_REVERSE_ARROW_BUTTON} > { onSwitchTokens() }}