Commit 5fc4d98f authored by lynn's avatar lynn Committed by GitHub

chore: universal search e2e test (#5839)

* init

* change comments

* init

* done

* charlie comments

* fix lint

* fix explore filter test
parent 8d9ddf36
...@@ -4,62 +4,80 @@ describe('Token explore filter', () => { ...@@ -4,62 +4,80 @@ describe('Token explore filter', () => {
}) })
it('should filter correctly by uni search term', () => { it('should filter correctly by uni search term', () => {
cy.visit('/tokens/ethereum') cy.visit('/tokens')
cy.get('[data-cy="token-name"]').then(($els) => { cy.get('[data-cy="token-name"]').then(($els) => {
const tokenNames = Array.from($els, (el) => el.innerText) const tokenNames = Array.from($els, (el) => el.innerText)
const filteredByUni = tokenNames.filter((tokenName) => tokenName.toLowerCase().includes('uni')) const filteredByUni = tokenNames.filter((tokenName) => tokenName.toLowerCase().includes('uni'))
cy.wrap(filteredByUni).as('filteredByUni') cy.wrap(filteredByUni).as('filteredByUni')
}) })
cy.get('[data-cy="explore-tokens-search-input"]').clear().type('uni').type('{enter}') cy.get('[data-cy="explore-tokens-search-input"]')
cy.get('@filteredByUni').then((filteredByUni) => { .clear()
cy.get('[data-cy="token-name"]').then(($els) => { .type('uni')
const tokenNames = Array.from($els, (el) => el.innerText) .type('{enter}')
expect(tokenNames.length).to.equal(filteredByUni.length) .then(() => {
tokenNames.forEach((tokenName) => { cy.get('[data-cy="token-name"]').its('length').should('be.lt', 100)
expect(filteredByUni).to.include(tokenName) cy.get('@filteredByUni').then((filteredByUni) => {
cy.get('[data-cy="token-name"]').then(($els) => {
const tokenNames = Array.from($els, (el) => el.innerText)
expect(tokenNames.length).to.equal(filteredByUni.length)
tokenNames.forEach((tokenName) => {
expect(filteredByUni).to.include(tokenName)
})
})
}) })
}) })
})
}) })
it('should filter correctly by dao search term', () => { it('should filter correctly by dao search term', () => {
cy.visit('/tokens/ethereum') cy.visit('/tokens')
cy.get('[data-cy="token-name"]').then(($els) => { cy.get('[data-cy="token-name"]').then(($els) => {
const tokenNames = Array.from($els, (el) => el.innerText) const tokenNames = Array.from($els, (el) => el.innerText)
const filteredByDao = tokenNames.filter((tokenName) => tokenName.toLowerCase().includes('dao')) const filteredByDao = tokenNames.filter((tokenName) => tokenName.toLowerCase().includes('dao'))
cy.wrap(filteredByDao).as('filteredByDao') cy.wrap(filteredByDao).as('filteredByDao')
}) })
cy.get('[data-cy="explore-tokens-search-input"]').clear().type('dao').type('{enter}') cy.get('[data-cy="explore-tokens-search-input"]')
cy.get('@filteredByDao').then((filteredByDao) => { .clear()
cy.get('[data-cy="token-name"]').then(($els) => { .type('dao')
const tokenNames = Array.from($els, (el) => el.innerText) .type('{enter}')
expect(tokenNames.length).to.equal(filteredByDao.length) .then(() => {
tokenNames.forEach((tokenName) => { cy.get('[data-cy="token-name"]').its('length').should('be.lt', 100)
expect(filteredByDao).to.include(tokenName) cy.get('@filteredByDao').then((filteredByDao) => {
cy.get('[data-cy="token-name"]').then(($els) => {
const tokenNames = Array.from($els, (el) => el.innerText)
expect(tokenNames.length).to.equal(filteredByDao.length)
tokenNames.forEach((tokenName) => {
expect(filteredByDao).to.include(tokenName)
})
})
}) })
}) })
})
}) })
it('should filter correctly by ax search term', () => { it('should filter correctly by ax search term', () => {
cy.visit('/tokens/ethereum') cy.visit('/tokens')
cy.get('[data-cy="token-name"]').then(($els) => { cy.get('[data-cy="token-name"]').then(($els) => {
const tokenNames = Array.from($els, (el) => el.innerText) const tokenNames = Array.from($els, (el) => el.innerText)
const filteredByAx = tokenNames.filter((tokenName) => tokenName.toLowerCase().includes('ax')) const filteredByAx = tokenNames.filter((tokenName) => tokenName.toLowerCase().includes('ax'))
cy.wrap(filteredByAx).as('filteredByAx') cy.wrap(filteredByAx).as('filteredByAx')
}) })
cy.get('[data-cy="explore-tokens-search-input"]').clear().type('ax').type('{enter}') cy.get('[data-cy="explore-tokens-search-input"]')
cy.get('@filteredByAx').then((filteredByAx) => { .clear()
cy.get('[data-cy="token-name"]').then(($els) => { .type('ax')
const tokenNames = Array.from($els, (el) => el.innerText) .type('{enter}')
expect(tokenNames.length).to.equal(filteredByAx.length) .then(() => {
tokenNames.forEach((tokenName) => { cy.get('[data-cy="token-name"]').its('length').should('be.lt', 100)
expect(filteredByAx).to.include(tokenName) cy.get('@filteredByAx').then((filteredByAx) => {
cy.get('[data-cy="token-name"]').then(($els) => {
const tokenNames = Array.from($els, (el) => el.innerText)
expect(tokenNames.length).to.equal(filteredByAx.length)
tokenNames.forEach((tokenName) => {
expect(filteredByAx).to.include(tokenName)
})
})
}) })
}) })
})
}) })
}) })
import { getTestSelector } from '../utils'
describe('Universal search bar', () => {
before(() => {
cy.visit('/')
cy.get('[data-cy="magnifying-icon"]')
.parent()
.then(($navIcon) => {
$navIcon.click()
})
})
it('should yield no results found when contract address is search term', () => {
// Search for uni token contract address.
cy.get('[data-cy="search-bar-input"]').last().type('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984')
cy.get('[data-cy="search-bar"]')
.should('contain.text', 'No tokens found.')
.and('contain.text', 'No NFT collections found.')
})
it('should yield clickable result for regular token or nft collection search term', () => {
// Search for uni token by name.
cy.get('[data-cy="search-bar-input"]').last().clear().type('uni')
cy.get('[data-cy="searchbar-token-row-UNI"]')
.should('contain.text', 'Uniswap')
.and('contain.text', 'UNI')
.and('contain.text', '$')
.and('contain.text', '%')
cy.get('[data-cy="searchbar-token-row-UNI"]').click()
cy.get('div').contains('Uniswap').should('exist')
// Stats should have: TVL, 24H Volume, 52W low, 52W high.
cy.get(getTestSelector('token-details-stats')).should('exist')
cy.get(getTestSelector('token-details-stats')).within(() => {
cy.get('[data-cy="tvl"]').should('include.text', '$')
cy.get('[data-cy="volume-24h"]').should('include.text', '$')
cy.get('[data-cy="52w-low"]').should('include.text', '$')
cy.get('[data-cy="52w-high"]').should('include.text', '$')
})
// About section should have description of token.
cy.get(getTestSelector('token-details-about-section')).should('exist')
cy.contains('UNI is the governance token for Uniswap').should('exist')
})
it('should show recent tokens and popular tokens with empty search term', () => {
cy.get('[data-cy="magnifying-icon"]')
.parent()
.then(($navIcon) => {
$navIcon.click()
})
// Recently searched UNI token should exist.
cy.get('[data-cy="search-bar-input"]').last().clear()
cy.get('[data-cy="searchbar-dropdown"]')
.contains('[data-cy="searchbar-dropdown"]', 'Recent searches')
.find('[data-cy="searchbar-token-row-UNI"]')
.should('exist')
// Most popular 3 tokens should be shown.
cy.get('[data-cy="searchbar-dropdown"]')
.contains('[data-cy="searchbar-dropdown"]', 'Popular tokens')
.find('[data-cy^="searchbar-token-row"]')
.its('length')
.should('be.eq', 3)
})
it('should show blocked badge when blocked token is searched for', () => {
// Search for mTSLA, which is a blocked token.
cy.get('[data-cy="search-bar-input"]').last().clear().type('mtsla')
cy.get('[data-cy="searchbar-token-row-mTSLA"]').find('[data-cy="blocked-icon"]').should('exist')
})
})
...@@ -148,6 +148,7 @@ export const SearchBar = () => { ...@@ -148,6 +148,7 @@ export const SearchBar = () => {
return ( return (
<Trace section={InterfaceSectionName.NAVBAR_SEARCH}> <Trace section={InterfaceSectionName.NAVBAR_SEARCH}>
<Box <Box
data-cy="search-bar"
position={{ sm: 'fixed', md: 'absolute', xl: 'relative' }} position={{ sm: 'fixed', md: 'absolute', xl: 'relative' }}
width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }} width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }}
ref={searchRef} ref={searchRef}
...@@ -187,6 +188,7 @@ export const SearchBar = () => { ...@@ -187,6 +188,7 @@ export const SearchBar = () => {
render={({ translation }) => ( render={({ translation }) => (
<Box <Box
as="input" as="input"
data-cy="search-bar-input"
placeholder={translation as string} placeholder={translation as string}
onChange={(event: ChangeEvent<HTMLInputElement>) => { onChange={(event: ChangeEvent<HTMLInputElement>) => {
!isOpen && toggleOpen() !isOpen && toggleOpen()
......
...@@ -46,7 +46,7 @@ const SearchBarDropdownSection = ({ ...@@ -46,7 +46,7 @@ const SearchBarDropdownSection = ({
eventProperties, eventProperties,
}: SearchBarDropdownSectionProps) => { }: SearchBarDropdownSectionProps) => {
return ( return (
<Column gap="12"> <Column gap="12" data-cy="searchbar-dropdown">
<Row paddingX="16" paddingY="4" gap="8" color="gray300" className={subheadSmall} style={{ lineHeight: '20px' }}> <Row paddingX="16" paddingY="4" gap="8" color="gray300" className={subheadSmall} style={{ lineHeight: '20px' }}>
{headerIcon ? headerIcon : null} {headerIcon ? headerIcon : null}
<Box>{header}</Box> <Box>{header}</Box>
......
...@@ -181,6 +181,7 @@ export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index, ...@@ -181,6 +181,7 @@ export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index,
return ( return (
<Link <Link
data-cy={`searchbar-token-row-${token.symbol}`}
to={tokenDetailsPath} to={tokenDetailsPath}
onClick={handleClick} onClick={handleClick}
onMouseEnter={() => !isHovered && setHoveredIndex(index)} onMouseEnter={() => !isHovered && setHoveredIndex(index)}
......
...@@ -28,7 +28,7 @@ export default function TokenSafetyIcon({ warning }: { warning: Warning | null } ...@@ -28,7 +28,7 @@ export default function TokenSafetyIcon({ warning }: { warning: Warning | null }
case WARNING_LEVEL.BLOCKED: case WARNING_LEVEL.BLOCKED:
return ( return (
<WarningContainer> <WarningContainer>
<BlockedIcon strokeWidth={2.5} /> <BlockedIcon data-cy="blocked-icon" strokeWidth={2.5} />
</WarningContainer> </WarningContainer>
) )
case WARNING_LEVEL.UNKNOWN: case WARNING_LEVEL.UNKNOWN:
......
...@@ -366,7 +366,14 @@ export const MagnifyingGlassIcon = (props: SVGProps) => ( ...@@ -366,7 +366,14 @@ export const MagnifyingGlassIcon = (props: SVGProps) => (
) )
export const NavMagnifyingGlassIcon = () => ( export const NavMagnifyingGlassIcon = () => (
<svg viewBox="0 0 24 24" width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg
viewBox="0 0 24 24"
width="24"
height="24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
data-cy="magnifying-icon"
>
<path <path
d="M10.5 18C14.6421 18 18 14.6421 18 10.5C18 6.35786 14.6421 3 10.5 3C6.35786 3 3 6.35786 3 10.5C3 14.6421 6.35786 18 10.5 18Z" d="M10.5 18C14.6421 18 18 14.6421 18 10.5C18 6.35786 14.6421 3 10.5 3C6.35786 3 3 6.35786 3 10.5C3 14.6421 6.35786 18 10.5 18Z"
stroke="currentColor" stroke="currentColor"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment