Skip to content
This repository has been archived by the owner on Jun 26, 2023. It is now read-only.

Commit

Permalink
Merge pull request #11 from input-output-hk/address-book-edit-fix
Browse files Browse the repository at this point in the history
[ETCM-375] Fix address book edit contact modal
  • Loading branch information
qwhex committed Nov 17, 2020
2 parents 9f73868 + 4a006a4 commit a2c4ceb
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 55 deletions.
85 changes: 63 additions & 22 deletions src/address-book/AddressBook.test.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
import '@testing-library/jest-dom/extend-expect'
import React from 'react'
import Web3 from 'web3'
import {fireEvent, render, waitFor} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {AddressBook} from './AddressBook'
import {WalletState, WalletStatus} from '../common/wallet-state'
import {SettingsState} from '../settings-state'
import {BackendState} from '../common/backend-state'
import {expectNoValidationErrorOnSubmit} from '../common/test-helpers'

const web3 = new Web3()

it('adds a new contact', async () => {
const initialState = {walletStatus: 'LOADED' as WalletStatus, web3}
const {queryByText, getByLabelText, getByTestId} = render(
<SettingsState.Provider>
<WalletState.Provider initialState={initialState}>
<BackendState.Provider initialState={{web3}}>
<AddressBook />
</BackendState.Provider>
</WalletState.Provider>
</SettingsState.Provider>,
)
import {expectNoValidationErrorOnSubmit, createWithProviders} from '../common/test-helpers'

const VALID_ADDRESS = '0xffffffffffffffffffffffffffffffffffffffff'

it('can add a new contact', async () => {
const {queryByText, getByLabelText, getByTestId} = render(<AddressBook />, {
wrapper: createWithProviders(),
})

const newContactButton = getByTestId('add-contact-button')
userEvent.click(newContactButton)
Expand All @@ -42,8 +31,7 @@ it('adds a new contact', async () => {
fireEvent.change(addressInput, {target: {value: 'not an address'}})
await waitFor(() => expect(queryByText(INVALID_ADDRESS_MSG)).toBeInTheDocument())

const FINAL_ADDRESS = '0xffffffffffffffffffffffffffffffffffffffff'
fireEvent.change(addressInput, {target: {value: FINAL_ADDRESS}})
fireEvent.change(addressInput, {target: {value: VALID_ADDRESS}})
await waitFor(() => expect(queryByText(INVALID_ADDRESS_MSG)).not.toBeInTheDocument())

expect(saveButton).toBeDisabled()
Expand All @@ -68,7 +56,60 @@ it('adds a new contact', async () => {

// new contact shows up
await waitFor(() => {
expect(queryByText(FINAL_ADDRESS)).toBeInTheDocument()
expect(queryByText(VALID_ADDRESS)).toBeInTheDocument()
expect(queryByText(FINAL_LABEL)).toBeInTheDocument()
})
})

it('can edit a contact', async () => {
const {queryByText, getByLabelText, getByTestId, getByTitle} = render(<AddressBook />, {
wrapper: createWithProviders({
wallet: {addressBook: {[VALID_ADDRESS]: 'Gandhi'}, accounts: []},
}),
})

const startEditButton = getByTitle('Edit Contact')
userEvent.click(startEditButton)

// dialog opened
await waitFor(() => expect(queryByText('Edit Contact')).toBeInTheDocument())

const saveButton = getByTestId('right-button')
expect(saveButton).toBeEnabled()

const cancelButton = getByTestId('left-button')
expect(cancelButton).toBeEnabled()

// address cannot be changed in edit mode
const addressInput = getByLabelText('Address')
expect(addressInput).toBeDisabled()

// address input shows up with the correct value
expect(addressInput).toHaveValue(VALID_ADDRESS)

// label is editable
const labelInput = getByLabelText('Label')
expect(labelInput).toBeEnabled()

// label input shows up with the correct value
expect(labelInput).toHaveValue('Gandhi')

// change label
fireEvent.change(labelInput, {target: {value: 'Ihdnag'}})

// saving the contact
await expectNoValidationErrorOnSubmit(queryByText, saveButton)

// dialog closed
await waitFor(() => expect(queryByText('Edit Contact')).not.toBeInTheDocument())

// new contact shows up
await waitFor(() => {
// address is the same
expect(queryByText(VALID_ADDRESS)).toBeInTheDocument()
// previous label doesn't show up
expect(queryByText('Gandhi')).not.toBeInTheDocument()
// new label shows up
expect(queryByText('Ihdnag')).toBeInTheDocument()
})
})
26 changes: 18 additions & 8 deletions src/address-book/AddressBook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {NoWallet} from '../wallets/NoWallet'
import './AddressBook.scss'

const LABEL_MAX_LENGTH = 80
const LABEL_FIELD_NAME = 'contact-label'
const ADDRESS_FIELD_NAME = 'contact-address'

type Setter<T> = React.Dispatch<React.SetStateAction<T>>

Expand Down Expand Up @@ -58,28 +60,28 @@ const _EditContactModal = ({
}}
onSetLoading={modalLocker.setLocked}
initialValues={{
address: address,
label: label,
[ADDRESS_FIELD_NAME]: address,
[LABEL_FIELD_NAME]: label,
}}
>
<DialogInput
label={t(['addressBook', 'label', 'address'])}
onChange={(e): void => setAddress(e.target.value)}
formItem={{
name: 'contact-address',
name: ADDRESS_FIELD_NAME,
rules: [
{required: true, message: t(['addressBook', 'error', 'addressMustBeSet'])},
addressValidator,
],
}}
disabled={toEdit}
id="contact-address"
id={ADDRESS_FIELD_NAME}
/>
<DialogInput
label={t(['addressBook', 'label', 'label'])}
onChange={(e): void => setLabel(e.target.value)}
formItem={{
name: 'contact-label',
name: LABEL_FIELD_NAME,
rules: [
{required: true, message: t(['addressBook', 'error', 'labelMustBeSet'])},
{
Expand All @@ -90,7 +92,7 @@ const _EditContactModal = ({
},
],
}}
id="contact-label"
id={LABEL_FIELD_NAME}
/>
</Dialog>
)
Expand Down Expand Up @@ -213,10 +215,18 @@ const _AddressBook = ({
</Popover>
</span>
<span className="actions">
<span className="delete" {...fillActionHandlers(onStartDelete(address))}>
<span
className="delete"
title={t(['addressBook', 'book', 'deleteContact'])}
{...fillActionHandlers(onStartDelete(address))}
>
<DeleteOutlined />
</span>
<span className="edit" {...fillActionHandlers(onStartEdit(address, label))}>
<span
className="edit"
title={t(['addressBook', 'book', 'editContact'])}
{...fillActionHandlers(onStartEdit(address, label))}
>
<EditOutlined />
</span>
</span>
Expand Down
26 changes: 26 additions & 0 deletions src/common/test-helpers.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
/* eslint-disable react/display-name */
import '@testing-library/jest-dom/extend-expect'
import React, {FunctionComponent} from 'react'
import Web3 from 'web3'
import BigNumber from 'bignumber.js'
import {waitFor, act} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {SettingsState} from '../settings-state'
import {defaultWalletData, WalletState, WalletStatus, StoreWalletData} from './wallet-state'
import {BackendState} from './backend-state'
import {abbreviateAmount} from './formatters'
import {EN_US_BIG_NUMBER_FORMAT} from './i18n'
import {createInMemoryStore} from './store'

const web3 = new Web3()

export const WithSettingsProvider: FunctionComponent = ({
children,
}: {
children?: React.ReactNode
}) => <SettingsState.Provider>{children}</SettingsState.Provider>

export const createWithProviders = (
walletData: StoreWalletData | null = null,
): FunctionComponent => ({children}: {children?: React.ReactNode}) => {
const initialState = {
walletStatus: 'LOADED' as WalletStatus,
store: createInMemoryStore(walletData ?? defaultWalletData),
isMocked: true,
web3,
}

return (
<SettingsState.Provider>
<BackendState.Provider initialState={{web3}}>
<WalletState.Provider initialState={initialState}>{children}</WalletState.Provider>
</BackendState.Provider>
</SettingsState.Provider>
)
}

export const expectCalledOnClick = async (
getter: () => HTMLElement,
toBeCalledFn: CallableFunction,
Expand Down
30 changes: 5 additions & 25 deletions src/wallets/TransactionHistory.test.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import '@testing-library/jest-dom/extend-expect'
import React, {FunctionComponent, useState} from 'react'
import React, {useState} from 'react'
import {render, RenderResult, waitFor, act, fireEvent} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import Web3 from 'web3'
import {TransactionHistory, TransactionHistoryProps} from './TransactionHistory'
import {Account, WalletState, WalletStatus, FeeEstimates, Transaction} from '../common/wallet-state'
import {SettingsState} from '../settings-state'
import {abbreviateAmountForEnUS} from '../common/test-helpers'
import {BackendState} from '../common/backend-state'
import {Account, FeeEstimates, Transaction} from '../common/wallet-state'
import {abbreviateAmountForEnUS, createWithProviders} from '../common/test-helpers'
import {ADDRESS} from '../storybook-util/dummies'
import {mockedCopyToClipboard} from '../jest.setup'
import {asWei, asEther, etherValue} from '../common/units'

const web3 = new Web3()

const tx1: Transaction = {
hash: '1',
from: '0x00112233445566778899aabbccddeeff00112233',
Expand Down Expand Up @@ -67,21 +62,6 @@ const accounts: Account[] = [
},
]

const WithProviders: FunctionComponent = ({children}: {children?: React.ReactNode}) => {
const initialState = {
walletStatus: 'LOADED' as WalletStatus,
web3,
}

return (
<SettingsState.Provider>
<BackendState.Provider initialState={{web3}}>
<WalletState.Provider initialState={initialState}>{children}</WalletState.Provider>
</BackendState.Provider>
</SettingsState.Provider>
)
}

const estimateFees = (): Promise<FeeEstimates> =>
Promise.resolve({
low: asWei(100),
Expand All @@ -103,7 +83,7 @@ const renderTransactionHistory = (props: Partial<TransactionHistoryProps> = {}):
...props,
}

return render(<TransactionHistory {...usedProps} />, {wrapper: WithProviders})
return render(<TransactionHistory {...usedProps} />, {wrapper: createWithProviders()})
}

const TxHistoryWithAddressGenerator = ({
Expand Down Expand Up @@ -131,7 +111,7 @@ const TxHistoryWithAddressGenerator = ({

const renderTxHistoryWithAddressGenerator = (preparedAccounts: Account[] = []): RenderResult =>
render(<TxHistoryWithAddressGenerator preparedAccounts={preparedAccounts} />, {
wrapper: WithProviders,
wrapper: createWithProviders(),
})

test('TransactionHistory shows proper message with empty tx list', () => {
Expand Down

0 comments on commit a2c4ceb

Please sign in to comment.