Added tests for Address Book import validations (#2393)

* Added tests and utils file

* Minor changes
This commit is contained in:
juampibermani 2021-06-07 11:49:20 -03:00 committed by GitHub
parent add406c42b
commit a130fdd4cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 134 additions and 40 deletions

View File

@ -5,9 +5,9 @@ import { Text } from '@gnosis.pm/safe-react-components'
import { Modal } from 'src/components/Modal'
import { CSVReader } from 'react-papaparse'
import { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
import { isValidAddress } from 'src/utils/isValidAddress'
import { checksumAddress } from 'src/utils/checksumAddress'
import HelpInfo from 'src/routes/safe/components/AddressBook/HelpInfo'
import { validateCsvData, validateFile } from 'src/routes/safe/components/AddressBook/utils'
const ImportContainer = styled.div`
flex-direction: column;
@ -28,15 +28,6 @@ const InfoContainer = styled.div`
margin-top: 16px;
`
const WRONG_FILE_EXTENSION_ERROR = 'Only CSV files are allowed'
const FILE_SIZE_TOO_BIG = 'The size of the file is over 1 MB'
const FILE_BYTES_LIMIT = 1000000
const IMPORT_SUPPORTED_FORMATS = [
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'text/csv',
]
type ImportEntriesModalProps = {
importEntryModalHandler: (addressList: AddressBookEntry[]) => void
isOpen: boolean
@ -76,36 +67,6 @@ const ImportEntriesModal = ({ importEntryModalHandler, isOpen, onClose }: Import
setCsvLoaded(true)
}
const validateFile = (file) => {
if (!IMPORT_SUPPORTED_FORMATS.includes(file.type)) {
return WRONG_FILE_EXTENSION_ERROR
}
if (file.size >= FILE_BYTES_LIMIT) {
return FILE_SIZE_TOO_BIG
}
return
}
const validateCsvData = (data) => {
for (let index = 0; index < data.length; index++) {
const entry = data[index]
if (!entry.data[0] || !entry.data[1] || !entry.data[2]) {
return `Invalid amount of columns on row ${index + 1}`
}
// Verify address properties
const address = entry.data[0].toLowerCase()
if (!isValidAddress(address)) {
return `Invalid address on row ${index + 1}`
}
if (isNaN(entry.data[2])) {
return `Invalid chain id on row ${index + 1}`
}
}
return
}
const handleOnError = (error) => {
setImportError(error.message)
}

View File

@ -0,0 +1,84 @@
import {
WRONG_FILE_EXTENSION_ERROR,
FILE_SIZE_TOO_BIG_ERROR,
IMPORT_SUPPORTED_FORMATS,
validateFile,
validateCsvData,
CsvDataType,
} from '../utils'
describe('Address Book file validations', () => {
it('Should return wrong file extension error if file extension is not the allowed', () => {
const file = new File([''], 'file.txt', { type: 'text/plain' })
const result = validateFile(file)
expect(result).toBe(WRONG_FILE_EXTENSION_ERROR)
})
it('Should return file size error if file size is over the allowed', () => {
const file = new File([''], 'file.csv', { type: IMPORT_SUPPORTED_FORMATS[0] })
Object.defineProperty(file, 'size', { value: 1024 * 1024 + 1 })
const result = validateFile(file)
expect(result).toBe(FILE_SIZE_TOO_BIG_ERROR)
})
it('Should return undefined if extension and file size are valid', () => {
const file = new File([''], 'file.csv', { type: IMPORT_SUPPORTED_FORMATS[0] })
const result = validateFile(file)
expect(result).toBe(undefined)
})
})
describe('Address Book CSV data validations', () => {
const validAddress = '0x4362527986c3fD47f498eF24B4D01e6AAD7aBcb2'
const noHexAddress = '4362527986c3fD47f498eF24B4D01e6AAD7aBcb2'
const invalidAddress = '0xC1912fEE45d61C87Cc5EA59DaE31190FFFFfff2'
const validName = 'Name'
const validChainId = '4'
it('Should return an error if the amount of columns is not valid', () => {
const data: CsvDataType = [{ data: [validAddress, validName] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid amount of columns on row 1')
})
it('Should return an error if name is empty', () => {
const data = [{ data: [validAddress, '', validChainId] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid amount of columns on row 1')
})
it('Should return an error if address is empty', () => {
const data = [{ data: ['', validName, validChainId] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid amount of columns on row 1')
})
it('Should return an error if chainId is empty', () => {
const data = [{ data: [validAddress, validName, ''] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid amount of columns on row 1')
})
it('Should return an error if address is not hex strict', () => {
const data = [{ data: [noHexAddress, validName, validChainId] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid address on row 1')
})
it('Should return an error if address is not valid', () => {
const data = [{ data: [invalidAddress, validName, validChainId] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid address on row 1')
})
it('Should return an error if chainId is not valid', () => {
const data = [{ data: [validAddress, validName, 'notAChainId'] }]
const result = validateCsvData(data)
expect(result).toBe('Invalid chain id on row 1')
})
it('Should return undefined if all elements are valid', () => {
const data = [{ data: [validAddress, validName, validChainId] }]
const result = validateCsvData(data)
expect(result).toBe(undefined)
})
})

View File

@ -0,0 +1,49 @@
import { isValidAddress } from 'src/utils/isValidAddress'
export const WRONG_FILE_EXTENSION_ERROR = 'Only CSV files are allowed'
export const FILE_SIZE_TOO_BIG_ERROR = 'The size of the file is over 1 MB'
export const FILE_BYTES_LIMIT = 1000000
export const IMPORT_SUPPORTED_FORMATS = [
'text/csv',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
]
export type CsvDataType = { data: string[] }[]
export const validateFile = (file: File): string | undefined => {
if (!IMPORT_SUPPORTED_FORMATS.includes(file.type)) {
return WRONG_FILE_EXTENSION_ERROR
}
if (file.size >= FILE_BYTES_LIMIT) {
return FILE_SIZE_TOO_BIG_ERROR
}
return
}
export const validateCsvData = (data: CsvDataType): string | undefined => {
for (let index = 0; index < data.length; index++) {
const entry = data[index]
const [address, name, chainId] = entry.data
if (entry.data.length !== 3) {
return `Invalid amount of columns on row ${index + 1}`
}
if (typeof address !== 'string' || typeof name !== 'string' || typeof chainId !== 'string') {
return `Invalid amount of columns on row ${index + 1}`
}
if (!address.trim() || !name.trim() || !chainId.trim()) {
return `Invalid amount of columns on row ${index + 1}`
}
// Verify address properties
const lowerCaseAddress = address.toLowerCase()
if (!isValidAddress(lowerCaseAddress)) {
return `Invalid address on row ${index + 1}`
}
if (isNaN(parseInt(chainId))) {
return `Invalid chain id on row ${index + 1}`
}
}
return
}