Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests: Add test IDs and modify NFT tests #2804

Merged
merged 3 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions cypress/e2e/pages/main.page.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as constants from '../../support/constants'

const acceptSelection = 'Accept selection'
export const modalDialogCloseBtn = '[data-testid="modal-dialog-close-btn"]'

export function clickOnSideMenuItem(item) {
cy.get('p').contains(item).click()
Expand Down
76 changes: 46 additions & 30 deletions cypress/e2e/pages/nfts.pages.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import * as constants from '../../support/constants'
import * as main from '../pages/main.page'

const nftModal = 'div[role="dialog"]'
const nftModalCloseBtn = 'button[aria-label="close"]'
const nftModalTitle = '[data-testid="modal-title"]'
const nftModal = '[data-testid="modal-view"]'

const nftModalCloseBtn = main.modalDialogCloseBtn
const recipientInput = 'input[name="recipient"]'
const nftsRow = '[data-testid^="nfts-table-row"]'
const inactiveNftIcon = '[data-testid="nft-icon-border"]'
const activeNftIcon = '[data-testid="nft-icon-primary"]'
const nftCheckBox = (index) => `[data-testid="nft-checkbox-${index}"] > input`
const activeSendNFTBtn = '[data-testid="nft-send-btn-false"]'
const modalTitle = '[data-testid="modal-title"]'
const modalHeader = '[data-testid="modal-header"]'
const modalSelectedNFTs = '[data-testid="selected-nfts"]'
const nftItemList = '[data-testid="nft-item-list"]'
const nftItemNane = '[data-testid="nft-item-name"]'
const signBtn = '[data-testid="sign-btn"]'

const noneNFTSelected = '0 NFTs selected'
const sendNFTStr = 'Send NFTs'
Expand All @@ -19,52 +33,57 @@ export function clickOnNftsTab() {
cy.get('p').contains('NFTs').click()
}
function verifyTableRows(number) {
cy.get('tbody tr').should('have.length', number)
cy.scrollTo('bottom').wait(500)
cy.get(nftsRow).should('have.length.at.least', number)
}

export function verifyNFTNumber(number) {
verifyTableRows(number)
}

export function verifyDataInTable(name, address, tokenID) {
cy.get('tbody tr:first-child').contains('td:first-child', name)
cy.get('tbody tr:first-child').contains('td:first-child', address)
cy.get('tbody tr:first-child').contains('td:nth-child(2)', tokenID)
cy.get(nftsRow).contains(name)
cy.get(nftsRow).contains(address)
cy.get(nftsRow).contains(tokenID)
}

export function openNFT(index) {
cy.get('tbody').within(() => {
cy.get('tr').eq(index).click()
})
export function waitForNftItems(count) {
cy.get(nftsRow).should('have.length.at.least', count)
}

export function openActiveNFT(index) {
cy.get(activeNftIcon).eq(index).click()
}

export function verifyNameInNFTModal(name) {
cy.get(nftModal).contains(name)
cy.get(nftModalTitle).contains(name)
}

export function verifySelectedNetwrokSepolia() {
cy.get(nftModal).contains(constants.networks.sepolia)
cy.get(nftModal).within(() => {
cy.get(nftModalTitle).contains(constants.networks.sepolia)
})
}

export function verifyNFTModalLink(link) {
cy.get(nftModal).contains(`a[href="${link}"]`, 'View on OpenSea')
cy.get(nftModalTitle).contains(`a[href="${link}"]`, 'View on OpenSea')
}

export function closeNFTModal() {
cy.get(nftModalCloseBtn).click()
cy.get(nftModal).should('not.exist')
cy.get(nftModalTitle).should('not.exist')
}

export function clickOn6thNFT() {
cy.get('tbody tr:nth-child(6) td:nth-child(2)').click()
export function clickOnInactiveNFT() {
cy.get(inactiveNftIcon).eq(0).click()
}
export function verifyNFTModalDoesNotExist() {
cy.get(nftModal).should('not.exist')
cy.get(nftModalTitle).should('not.exist')
}

export function selectNFTs(numberOfNFTs) {
for (let i = 1; i <= numberOfNFTs; i++) {
cy.get(`tbody tr:nth-child(${i}) input[type="checkbox"]`).click()
cy.get(nftCheckBox(i)).click()
cy.contains(`${i} NFT${i > 1 ? 's' : ''} selected`)
}
cy.contains('button', `Send ${numberOfNFTs} NFT${numberOfNFTs > 1 ? 's' : ''}`)
Expand All @@ -73,8 +92,8 @@ export function selectNFTs(numberOfNFTs) {
export function deselectNFTs(checkboxIndexes, checkedItems) {
let total = checkedItems - checkboxIndexes.length

checkboxIndexes.forEach((index) => {
cy.get(`tbody tr:nth-child(${index}) input[type="checkbox"]`).uncheck()
checkboxIndexes.forEach((i) => {
cy.get(nftCheckBox(i)).uncheck()
})

cy.contains(`${total} NFT${total !== 1 ? 's' : ''} selected`)
Expand All @@ -88,14 +107,12 @@ export function verifyInitialNFTData() {
cy.contains('button[disabled]', 'Send')
}

export function sendNFT(numberOfCheckedNFTs) {
cy.contains('button', `Send ${numberOfCheckedNFTs} NFT${numberOfCheckedNFTs !== 1 ? 's' : ''}`).click()
export function sendNFT() {
cy.get(activeSendNFTBtn).click()
}

export function verifyNFTModalData() {
cy.contains(sendNFTStr)
cy.contains(recipientAddressStr)
cy.contains(selectedNFTStr)
main.verifyElementsExist([modalTitle, modalHeader, modalSelectedNFTs])
}

export function typeRecipientAddress(address) {
Expand All @@ -107,11 +124,10 @@ export function clikOnNextBtn() {
}

export function verifyReviewModalData(NFTcount) {
cy.contains(sendStr)
cy.contains(toStr)
cy.wait(1000)
cy.get(`b:contains(${transferFromStr})`).should('have.length', NFTcount)
cy.contains('button:not([disabled])', signBtnStr)
main.verifyElementsExist([nftItemList])
main.verifyElementsCount(nftItemNane, NFTcount)
cy.get(signBtn).should('not.be.disabled')

if (NFTcount > 1) {
const numbersArr = Array.from({ length: NFTcount }, (_, index) => index + 1)
numbersArr.forEach((number) => {
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/safe-apps/tx-builder.spec.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
getBody().findByText(safeapps.sendBatchStr).click()
})
cy.get('p').contains('1').should('exist')
cy.get('p').contains('2').should('be.visible')
cy.get('p').contains('2').should('exist')
})

it('Verify a batch cannot be created with invalid address', () => {
Expand Down
10 changes: 5 additions & 5 deletions cypress/e2e/smoke/nfts.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,34 @@ describe('NFTs tests', () => {
cy.clearLocalStorage()
cy.visit(constants.balanceNftsUrl + constants.SEPOLIA_TEST_SAFE_5)
main.acceptCookies()
nfts.clickOnNftsTab()
nfts.waitForNftItems(2)
})

it('Verify that NFTs exist in the table', () => {
nfts.verifyNFTNumber(20)
nfts.verifyNFTNumber(10)
})

it('Verify NFT row contains data', () => {
nfts.verifyDataInTable(nftsName, nftsAddress, nftsTokenID)
})

it('Verify NFT preview window can be opened', () => {
nfts.openNFT(0)
nfts.openActiveNFT(0)
nfts.verifyNameInNFTModal(nftsTokenID)
nfts.verifySelectedNetwrokSepolia()
nfts.closeNFTModal()
})

it('Verify NFT open does not open if no NFT exits', () => {
nfts.clickOn6thNFT()
nfts.clickOnInactiveNFT()
nfts.verifyNFTModalDoesNotExist()
})

it('Verify multipls NFTs can be selected and reviewed', () => {
nfts.verifyInitialNFTData()
nfts.selectNFTs(3)
nfts.deselectNFTs([2], 3)
nfts.sendNFT(2)
nfts.sendNFT()
nfts.verifyNFTModalData()
nfts.typeRecipientAddress(constants.SEPOLIA_TEST_SAFE_4)
nfts.clikOnNextBtn()
Expand Down
4 changes: 3 additions & 1 deletion src/components/common/ModalDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ interface DialogTitleProps {

export const ModalDialogTitle = ({ children, onClose, hideChainIndicator = false, ...other }: DialogTitleProps) => {
return (
<DialogTitle sx={{ m: 0, p: 2, display: 'flex', alignItems: 'center' }} {...other}>
<DialogTitle data-testid="modal-title" sx={{ m: 0, p: 2, display: 'flex', alignItems: 'center' }} {...other}>
{children}
<span style={{ flex: 1 }} />
{!hideChainIndicator && <ChainIndicator inline />}
{onClose ? (
<IconButton
data-testid="modal-dialog-close-btn"
aria-label="close"
onClick={(e) => {
onClose(e, 'backdropClick')
Expand Down Expand Up @@ -56,6 +57,7 @@ const ModalDialog = ({

return (
<Dialog
data-testid="modal-view"
{...restProps}
fullScreen={isFullScreen}
scroll={fullScreen ? 'paper' : 'body'}
Expand Down
18 changes: 15 additions & 3 deletions src/components/nfts/NftGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@ const headCells = [
const stopPropagation = (e: SyntheticEvent) => e.stopPropagation()

const NftIndicator = ({ color }: { color: SvgIconProps['color'] }) => (
<SvgIcon component={NftIcon} inheritViewBox width={20} height={20} color={color} sx={{ ml: 0.25 }} />
<SvgIcon
data-testid={`nft-icon-${color}`}
component={NftIcon}
inheritViewBox
width={20}
height={20}
color={color}
sx={{ ml: 0.25 }}
/>
)

const activeNftIcon = <NftIndicator color="primary" />
Expand Down Expand Up @@ -191,7 +199,7 @@ const NftGrid = ({
const sx = item.imageUri ? { cursor: 'pointer' } : undefined

return (
<TableRow tabIndex={-1} key={`${item.address}-${item.id}`}>
<TableRow data-testid={`nfts-table-row-${index + 1}`} tabIndex={-1} key={`${item.address}-${item.id}`}>
{/* Collection name */}
<TableCell onClick={onClick} sx={sx}>
<Box display="flex" alignItems="center" gap={2}>
Expand Down Expand Up @@ -233,7 +241,11 @@ const NftGrid = ({

{/* Checkbox */}
<TableCell align="right">
<Checkbox checked={selectedNfts.includes(item)} onChange={(e) => onCheckboxClick(e, item)} />
<Checkbox
data-testid={`nft-checkbox-${index + 1}`}
checked={selectedNfts.includes(item)}
onChange={(e) => onCheckboxClick(e, item)}
/>

{/* Insert the children at the end of the table */}
{index === filteredNfts.length - 1 && children}
Expand Down
1 change: 1 addition & 0 deletions src/components/nfts/NftSendForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const NftSendForm = ({ selectedNfts }: NftSendFormProps): ReactElement => {
<CheckWallet>
{(isOk) => (
<Button
data-testid={`nft-send-btn-${!isOk || noSelected}`}
type="submit"
variant="contained"
size="small"
Expand Down
17 changes: 14 additions & 3 deletions src/components/tx-flow/common/TxLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,20 @@ const TxLayout = ({
{/* Main content */}
<Grid item xs={12} md={7}>
<div className={css.titleWrapper}>
<Typography variant="h3" component="div" fontWeight="700" className={css.title}>
<Typography
data-testid="modal-title"
variant="h3"
component="div"
fontWeight="700"
className={css.title}
>
{title}
</Typography>

<ChainIndicator inline />
</div>

<Paper className={css.header}>
<Paper data-testid="modal-header" className={css.header}>
<Box className={css.progressBar}>
<ProgressBar value={progress} />
</Box>
Expand All @@ -128,7 +134,12 @@ const TxLayout = ({
{steps[step]}

{onBack && step > 0 && (
<Button variant="contained" onClick={onBack} className={css.backButton}>
<Button
data-testid="modal-back-btn"
variant="contained"
onClick={onBack}
className={css.backButton}
>
Back
</Button>
)}
Expand Down
21 changes: 18 additions & 3 deletions src/components/tx-flow/flows/NftTransfer/SendNftBatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ const NftItem = ({ image, name, description }: { image: string; name: string; de
</Grid>

<Grid item overflow="hidden">
<Typography variant="body2" fontWeight={700} whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
<Typography
data-testid="nft-item-name"
variant="body2"
fontWeight={700}
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
>
{name}
</Typography>

Expand All @@ -59,7 +66,15 @@ const NftItem = ({ image, name, description }: { image: string; name: string; de

export const NftItems = ({ tokens }: { tokens: SafeCollectibleResponse[] }) => {
return (
<Box display="flex" flexDirection="column" gap={2} overflow="auto" maxHeight="20vh" minHeight="40px">
<Box
data-testid="nft-item-list"
display="flex"
flexDirection="column"
gap={2}
overflow="auto"
maxHeight="20vh"
minHeight="40px"
>
{tokens.map((token) => (
<NftItem
key={`${token.address}-${token.id}`}
Expand Down Expand Up @@ -124,7 +139,7 @@ const SendNftBatch = ({ params, onSubmit }: SendNftBatchProps) => {
)}
</FormControl>

<Typography variant="body2" color="text.secondary" mb={2}>
<Typography data-testid="selected-nfts" variant="body2" color="text.secondary" mb={2}>
Selected NFTs
</Typography>

Expand Down
2 changes: 1 addition & 1 deletion src/components/tx/SignOrExecuteForm/SignForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const SignForm = ({
{/* Submit button */}
<CheckWallet>
{(isOk) => (
<Button variant="contained" type="submit" disabled={!isOk || submitDisabled}>
<Button data-testid="sign-btn" variant="contained" type="submit" disabled={!isOk || submitDisabled}>
Sign
</Button>
)}
Expand Down