ConfirmAddSuggestToken: replace mapDispatchToProps & mapStateToProps; Add Tests (#13526)
* ConfirmAddSuggestedToken: component.js -> .js * replace mapStateToProps w/ useSelector ConfirmAddSuggestedToken * replace mapDispatchToProps w/ useDispatch ConfirmAddSuggestedToken * ConfirmAddSuggestedToken: useHistory * ConfirmAddSuggestedToken: revert scss reuse ConfirmImportToken styles for now * ConfirmAddSuggestToken: add tests * ConfirmAddSuggestedToken: rm unused controls * ConfirmAddSuggestedToken: rm snapshot * use `metamark.svg` instead of `metamask.svg` * ConfirmAddSuggestedToken: update useSelectors * Revert "ConfirmAddSuggestedToken: revert scss" This reverts commit 07aed4576caaf247cb38ad481d79a339ba3d3947. * ConfirmAddSuggestedToken: === undefined w/ strict mode * ConfirmAddSuggestedToken: use useNewMetricEvent * ConfirmAddSuggestedToken: run useEffect once * ConfirmAddSuggestedToken: rm unused async * ConfirmAddSuggestedToken: rm mock redux store * ConfirmAddSuggestedToken: duplicate ConfirmImportToken styles * ConfirmAddSuggestedToken: update metrics logic * ConfirmAddSuggestedToken: metricEvent-> trackEvent * ConfirmAddSuggestedToken:clean useEffect w/ new fn - PR suggestion: https://github.com/MetaMask/metamask-extension/pull/13526#discussion_r818007393 * ConfirmAddSuggestedToken: rm unused .token-balance stylesfeature/default_network_editable
parent
bcf59ab09b
commit
fa15b32fab
@ -1,32 +0,0 @@ |
||||
import { connect } from 'react-redux'; |
||||
import { compose } from 'redux'; |
||||
import { withRouter } from 'react-router-dom'; |
||||
import { rejectWatchAsset, acceptWatchAsset } from '../../store/actions'; |
||||
import { getMostRecentOverviewPage } from '../../ducks/history/history'; |
||||
import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component'; |
||||
|
||||
const mapStateToProps = (state) => { |
||||
const { |
||||
metamask: { suggestedAssets, tokens }, |
||||
} = state; |
||||
|
||||
return { |
||||
mostRecentOverviewPage: getMostRecentOverviewPage(state), |
||||
suggestedAssets, |
||||
tokens, |
||||
}; |
||||
}; |
||||
|
||||
const mapDispatchToProps = (dispatch) => { |
||||
return { |
||||
rejectWatchAsset: (suggestedAssetID) => |
||||
dispatch(rejectWatchAsset(suggestedAssetID)), |
||||
acceptWatchAsset: (suggestedAssetID) => |
||||
dispatch(acceptWatchAsset(suggestedAssetID)), |
||||
}; |
||||
}; |
||||
|
||||
export default compose( |
||||
withRouter, |
||||
connect(mapStateToProps, mapDispatchToProps), |
||||
)(ConfirmAddSuggestedToken); |
@ -0,0 +1,142 @@ |
||||
import React from 'react'; |
||||
import { fireEvent, screen } from '@testing-library/react'; |
||||
import { acceptWatchAsset, rejectWatchAsset } from '../../store/actions'; |
||||
import configureStore from '../../store/store'; |
||||
import { renderWithProvider } from '../../../test/jest/rendering'; |
||||
import ConfirmAddSuggestedToken from '.'; |
||||
|
||||
const MOCK_SUGGESTED_ASSETS = [ |
||||
{ |
||||
id: 1, |
||||
asset: { |
||||
address: '0x8b175474e89094c44da98b954eedeac495271d0a', |
||||
symbol: 'NEW', |
||||
decimals: 18, |
||||
image: 'metamark.svg', |
||||
unlisted: false, |
||||
}, |
||||
}, |
||||
{ |
||||
id: 2, |
||||
asset: { |
||||
address: '0xC8c77482e45F1F44dE1745F52C74426C631bDD51', |
||||
symbol: '0XYX', |
||||
decimals: 18, |
||||
image: '0x.svg', |
||||
unlisted: false, |
||||
}, |
||||
}, |
||||
]; |
||||
|
||||
const MOCK_TOKEN = { |
||||
address: '0x108cf70c7d384c552f42c07c41c0e1e46d77ea0d', |
||||
symbol: 'TEST', |
||||
decimals: '0', |
||||
}; |
||||
|
||||
jest.mock('../../store/actions', () => ({ |
||||
acceptWatchAsset: jest.fn().mockReturnValue({ type: 'test' }), |
||||
rejectWatchAsset: jest.fn().mockReturnValue({ type: 'test' }), |
||||
})); |
||||
|
||||
const renderComponent = (tokens = []) => { |
||||
const store = configureStore({ |
||||
metamask: { |
||||
suggestedAssets: [...MOCK_SUGGESTED_ASSETS], |
||||
tokens, |
||||
provider: { chainId: '0x1' }, |
||||
}, |
||||
history: { |
||||
mostRecentOverviewPage: '/', |
||||
}, |
||||
}); |
||||
return renderWithProvider(<ConfirmAddSuggestedToken />, store); |
||||
}; |
||||
|
||||
describe('ConfirmAddSuggestedToken Component', () => { |
||||
it('should render', () => { |
||||
renderComponent(); |
||||
|
||||
expect(screen.getByText('Add Suggested Tokens')).toBeInTheDocument(); |
||||
expect( |
||||
screen.getByText('Would you like to import these tokens?'), |
||||
).toBeInTheDocument(); |
||||
expect(screen.getByText('Token')).toBeInTheDocument(); |
||||
expect(screen.getByText('Balance')).toBeInTheDocument(); |
||||
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument(); |
||||
expect( |
||||
screen.getByRole('button', { name: 'Add Token' }), |
||||
).toBeInTheDocument(); |
||||
}); |
||||
|
||||
it('should render the list of suggested tokens', () => { |
||||
renderComponent(); |
||||
|
||||
for (const { asset } of MOCK_SUGGESTED_ASSETS) { |
||||
expect(screen.getByText(asset.symbol)).toBeInTheDocument(); |
||||
} |
||||
expect(screen.getAllByRole('img')).toHaveLength( |
||||
MOCK_SUGGESTED_ASSETS.length, |
||||
); |
||||
}); |
||||
|
||||
it('should dispatch acceptWatchAsset when clicking the "Add Token" button', () => { |
||||
renderComponent(); |
||||
const addTokenBtn = screen.getByRole('button', { name: 'Add Token' }); |
||||
|
||||
fireEvent.click(addTokenBtn); |
||||
expect(acceptWatchAsset).toHaveBeenCalled(); |
||||
}); |
||||
|
||||
it('should dispatch rejectWatchAsset when clicking the "Cancel" button', () => { |
||||
renderComponent(); |
||||
const cancelBtn = screen.getByRole('button', { name: 'Cancel' }); |
||||
|
||||
expect(rejectWatchAsset).toHaveBeenCalledTimes(0); |
||||
fireEvent.click(cancelBtn); |
||||
expect(rejectWatchAsset).toHaveBeenCalledTimes( |
||||
MOCK_SUGGESTED_ASSETS.length, |
||||
); |
||||
}); |
||||
|
||||
describe('when the suggested token address matches an existing token address', () => { |
||||
it('should show "already listed" warning', () => { |
||||
const mockTokens = [ |
||||
{ |
||||
...MOCK_TOKEN, |
||||
address: MOCK_SUGGESTED_ASSETS[0].asset.address, |
||||
}, |
||||
]; |
||||
renderComponent(mockTokens); |
||||
|
||||
expect( |
||||
screen.getByText( |
||||
'This action will edit tokens that are already listed in your wallet, which can be used' + |
||||
' to phish you. Only approve if you are certain that you mean to change what these' + |
||||
' tokens represent. Learn more about', |
||||
), |
||||
).toBeInTheDocument(); |
||||
expect( |
||||
screen.getByRole('link', { name: 'scams and security risks.' }), |
||||
).toBeInTheDocument(); |
||||
}); |
||||
}); |
||||
|
||||
describe('when the suggested token symbol matches an existing token symbol and has a different address', () => { |
||||
it('should show "reuses a symbol" warning', () => { |
||||
const mockTokens = [ |
||||
{ |
||||
...MOCK_TOKEN, |
||||
symbol: MOCK_SUGGESTED_ASSETS[0].asset.symbol, |
||||
}, |
||||
]; |
||||
renderComponent(mockTokens); |
||||
|
||||
expect( |
||||
screen.getByText( |
||||
'A token here reuses a symbol from another token you watch, this can be confusing or deceptive.', |
||||
), |
||||
).toBeInTheDocument(); |
||||
}); |
||||
}); |
||||
}); |
@ -1,3 +1 @@ |
||||
import ConfirmAddSuggestedToken from './confirm-add-suggested-token.container'; |
||||
|
||||
export default ConfirmAddSuggestedToken; |
||||
export { default } from './confirm-add-suggested-token'; |
||||
|
Loading…
Reference in new issue