Skip to content

Commit

Permalink
Tests for services (safe-global#22)
Browse files Browse the repository at this point in the history
* Add tests for formatters and extractTxInfo

* Add path rewrite tests
  • Loading branch information
katspaugh authored Apr 22, 2022
1 parent 82e7c9e commit 78ef8d3
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 3 deletions.
118 changes: 118 additions & 0 deletions services/__tests__/extractTxInfo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type { TransactionDetails, TransactionSummary } from '@gnosis.pm/safe-react-gateway-sdk'
import extractTxInfo from '../extractTxInfo'

describe('extractTxInfo', () => {
it('should extract tx info for an ETH transfer', () => {
const txSummary = {
txInfo: {
type: 'Transfer',
transferInfo: {
type: 'NATIVE_COIN',
value: '1000000000000000000',
},
recipient: {
value: '0x1234567890123456789012345678901234567890',
},
},
executionInfo: {
nonce: '0',
},
} as unknown as TransactionSummary

const txDetails = {
txData: {
operation: 'CALL',
value: '1000000000000000000',
data: '0x1234567890123456789012345678901234567890',
},
detailedExecutionInfo: {
baseGas: 21000,
gasPrice: '10000000000',
safeTxGas: 11000,
gasToken: '0x0000000000000000000000000000000000000000',

refundReceiver: {
type: 'Address',
value: '0x1234567890123456789012345678901234567890',
},
confirmations: [{ signer: { value: '0x1234567890123456789012345678901234567890' }, signature: '0x123' }],
},
} as unknown as TransactionDetails

expect(extractTxInfo(txSummary, txDetails)).toEqual({
txParams: {
data: '0x',
baseGas: 21000,
gasPrice: 10000000000,
safeTxGas: 11000,
gasToken: '0x0000000000000000000000000000000000000000',
nonce: '0',
refundReceiver: '0x1234567890123456789012345678901234567890',
value: '1000000000000000000',
to: '0x1234567890123456789012345678901234567890',
operation: 'CALL',
},
signatures: {
'0x1234567890123456789012345678901234567890': '0x123',
},
})
})

it('should extract tx info for an ERC20 token transfer', () => {
const txSummary = {
txInfo: {
type: 'Transfer',
transferInfo: {
type: 'ERC20',
value: '1000000000000000000',
tokenAddress: '0xa74476443119A942dE498590Fe1f2454d7D4aC0d',
},
recipient: {
value: '0x1234567890123456789012345678901234567890',
},
},
executionInfo: {
nonce: '0',
},
} as unknown as TransactionSummary

const txDetails = {
txData: {
operation: 'CALL',
value: '0x0',
hexData: '0x546785',
data: '0x1234567890123456789012345678901234567890',
},
detailedExecutionInfo: {
baseGas: 21000,
gasPrice: '10000000000',
safeTxGas: 11000,
gasToken: '0x0000000000000000000000000000000000000000',

refundReceiver: {
type: 'Address',
value: '0x1234567890123456789012345678901234567890',
},
confirmations: [{ signer: { value: '0x1234567890123456789012345678901234567890' }, signature: '0x123' }],
},
} as unknown as TransactionDetails

expect(extractTxInfo(txSummary, txDetails)).toEqual({
txParams: {
data: '0x546785',
baseGas: 21000,
gasPrice: 10000000000,
safeTxGas: 11000,
gasToken: '0x0000000000000000000000000000000000000000',
nonce: '0',
refundReceiver: '0x1234567890123456789012345678901234567890',
value: '0x0',
to: '0xa74476443119A942dE498590Fe1f2454d7D4aC0d',
operation: 'CALL',
},
signatures: {
'0x1234567890123456789012345678901234567890': '0x123',
},
})
})
})
32 changes: 32 additions & 0 deletions services/__tests__/formatters.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import BigNumber from 'bignumber.js'
import * as formatters from '../formatters'

describe('shortenAddress', () => {
it('should shorten an address', () => {
expect(formatters.shortenAddress('0x1234567890123456789012345678901234567890')).toEqual('0x1234...7890')
})

it('should shorten an address with custom length', () => {
expect(formatters.shortenAddress('0x1234567890123456789012345678901234567890', 5)).toEqual('0x12345...67890')
})
})

describe('formatDecimals', () => {
it('should format decimals', () => {
expect(formatters.formatDecimals('100000000000000000')).toEqual('0.1')
})

it('should format decimals with custom decimals', () => {
expect(formatters.formatDecimals('1000000000000000000', 6)).toEqual('1000000000000')
})
})

describe('toDecimals', () => {
it('should convert to decimals', () => {
expect(formatters.toDecimals('2.01')).toEqual(new BigNumber('2010000000000000000'))
})

it('should convert to decimals with custom decimals', () => {
expect(formatters.toDecimals('3', 6)).toEqual(new BigNumber('3000000'))
})
})
2 changes: 1 addition & 1 deletion services/__tests__/useChains.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('useInitChains hook', () => {

it('should set the error state when the promise rejects', async () => {
// Change the getChainsConfig mock to reject
;(getChainsConfig as any).mockImplementation(() => Promise.reject('Something went wrong'))
;(getChainsConfig as jest.Mock).mockImplementation(() => Promise.reject('Something went wrong'))

// Render the hook and check that the loading state is true
renderHook(() => useInitChains(), { wrapper: TestProviderWrapper })
Expand Down
77 changes: 77 additions & 0 deletions services/__tests__/usePathRewrite.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { act, renderHook } from '@testing-library/react-hooks'
import { useRouter } from 'next/router'
import usePathRewrite, { useQueryRewrite } from '../usePathRewrite'

// Mock useRouter
jest.mock('next/router', () => ({
useRouter: jest.fn(() => ({
pathname: '/safe/balances',
query: {
safe: 'rin:0x0000000000000000000000000000000000000000',
},
replace: jest.fn(),
})),
}))

// mock window history replaceState
Object.defineProperty(window, 'history', {
writable: true,
value: {
replaceState: jest.fn(),
},
})

describe('usePathRewrite', () => {
beforeEach(() => {
jest.clearAllMocks()
})

it('should rewrite the path if there is /safe/ in path and ?safe= in the query', () => {
renderHook(() => usePathRewrite())

expect(history.replaceState).toHaveBeenCalledWith(
undefined,
'',
'/rin:0x0000000000000000000000000000000000000000/balances',
)
})

it('should not rewrite the path if there is no /safe/ in path or ?safe= in the query', () => {
;(useRouter as jest.Mock).mockImplementationOnce(() =>
jest.fn(() => ({
pathname: '/welcome',
query: {},
replace: jest.fn(),
})),
)

renderHook(() => usePathRewrite())

expect(history.replaceState).not.toHaveBeenCalled()
})
})

describe('useQueryRewrite', () => {
beforeEach(() => {
jest.clearAllMocks()
})

it('should not redirect if there is no Safe address in the path', async () => {
const { result } = renderHook(() => useQueryRewrite())
expect(result.current).toBe(false)
})

it('should redirect if there is a Safe address in the path', async () => {
Object.defineProperty(window, 'location', {
writable: true,
value: {
pathname: '/rin:0x0000000000000000000000000000000000000000/balances',
},
})

const { result } = renderHook(() => useQueryRewrite())
expect(result.current).toBe(true)
await act(() => Promise.resolve())
expect(result.current).toBe(true)
})
})
14 changes: 14 additions & 0 deletions services/__tests__/validation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as validators from '../validation'

describe('validation', () => {
describe('Ethereum address validation', () => {
it('should return undefined if the address is valid', () => {
expect(validators.validateAddress('0x1234567890123456789012345678901234567890')).toBeUndefined()
})

it('should return an error if the address is invalid', () => {
expect(validators.validateAddress('0x1234567890123456789012345678901234567890x')).toBe('Invalid address format')
expect(validators.validateAddress('0x1234a67890123456789012345678901234567890')).toBe('Invalid address checksum')
})
})
})
4 changes: 2 additions & 2 deletions services/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ export const toDecimals = (value: string, decimals = 18): BigNumber => {
return new BigNumber(value).div(`1e-${decimals}`)
}

export const shortenAddress = (address: string): string => {
return `${address.slice(0, 6)}...${address.slice(-4)}`
export const shortenAddress = (address: string, length = 4): string => {
return `${address.slice(0, length + 2)}...${address.slice(-length)}`
}

0 comments on commit 78ef8d3

Please sign in to comment.