-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import React from 'react'; | ||
import { render, screen, fireEvent } from '@testing-library/react'; | ||
import { useDispatch } from 'react-redux'; | ||
Check failure on line 3 in ui/components/multichain/network-list-menu/NetworkItems/NetworkItems.test.tsx
|
||
import configureStore from 'redux-mock-store'; | ||
import { Provider } from 'react-redux'; | ||
Check failure on line 5 in ui/components/multichain/network-list-menu/NetworkItems/NetworkItems.test.tsx
|
||
|
||
import { NetworkItems } from './NetworkItems'; | ||
import { | ||
NetworkConfiguration, | ||
RpcEndpointType, | ||
} from '@metamask/network-controller'; | ||
import { ACTION_MODES } from '../network-list-menu'; | ||
Check failure on line 12 in ui/components/multichain/network-list-menu/NetworkItems/NetworkItems.test.tsx
|
||
import { showModal, setEditedNetwork } from '../../../../store/actions'; | ||
Check failure on line 13 in ui/components/multichain/network-list-menu/NetworkItems/NetworkItems.test.tsx
|
||
import { CHAIN_IDS } from '@metamask/transaction-controller'; | ||
|
||
jest.mock('react-redux', () => ({ | ||
...jest.requireActual('react-redux'), | ||
useDispatch: jest.fn(), | ||
})); | ||
|
||
describe('NetworkItems', () => { | ||
const mockStore = configureStore([]); | ||
const dispatchMock = jest.fn(); | ||
|
||
// Mock sample data | ||
const mockNetwork: NetworkConfiguration = { | ||
chainId: '0x99', | ||
nativeCurrency: 'TEST', | ||
name: 'Test Network', | ||
rpcEndpoints: [ | ||
{ | ||
url: 'https://test-rpc', | ||
name: 'test', | ||
networkClientId: 'test', | ||
type: RpcEndpointType.Custom, | ||
}, | ||
], | ||
defaultRpcEndpointIndex: 0, | ||
blockExplorerUrls: ['https://test-explorer'], | ||
defaultBlockExplorerUrlIndex: 0, | ||
}; | ||
|
||
const baseProps = { | ||
network: mockNetwork, | ||
isUnlocked: true, | ||
currentChainId: '0x99', // same as mockNetwork, so isCurrentNetwork will be true | ||
handleNetworkChange: jest.fn(), | ||
toggleNetworkMenu: jest.fn(), | ||
setActionMode: jest.fn(), | ||
focusSearch: false, | ||
showMultiRpcSelectors: false, | ||
}; | ||
|
||
beforeEach(() => { | ||
(useDispatch as jest.Mock).mockReturnValue(dispatchMock); | ||
dispatchMock.mockClear(); | ||
baseProps.handleNetworkChange.mockClear(); | ||
baseProps.toggleNetworkMenu.mockClear(); | ||
baseProps.setActionMode.mockClear(); | ||
}); | ||
|
||
const renderComponent = (props = {}) => { | ||
const store = mockStore({}); | ||
return render( | ||
<Provider store={store}> | ||
<NetworkItems {...baseProps} {...props} /> | ||
</Provider>, | ||
); | ||
}; | ||
|
||
it('renders correctly and matches snapshot', () => { | ||
const { container } = renderComponent(); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
|
||
it('renders NetworkListItem with correct name and default props', () => { | ||
renderComponent(); | ||
|
||
expect(screen.getByText(/Test Network/i)).toBeInTheDocument(); | ||
}); | ||
|
||
it('calls handleNetworkChange when the NetworkListItem is clicked', () => { | ||
renderComponent(); | ||
const networkItem = screen.getByText('Test Network'); | ||
|
||
fireEvent.click(networkItem); | ||
|
||
expect(baseProps.handleNetworkChange).toHaveBeenCalledWith(mockNetwork); | ||
}); | ||
|
||
it('does NOT render Delete button if the network is MAINNET, or user is locked, or it is current network', () => { | ||
renderComponent(); | ||
|
||
const deleteButton = screen.queryByLabelText(/delete/i); | ||
expect(deleteButton).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('does not render the RPC endpoint button if showMultiRpcSelectors is false', () => { | ||
renderComponent(); | ||
|
||
const rpcButton = screen.queryByLabelText(/select rpc/i); | ||
expect(rpcButton).not.toBeInTheDocument(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { CHAIN_IDS } from '@metamask/transaction-controller'; | ||
import { NetworkConfiguration } from '@metamask/network-controller'; | ||
import React, { useCallback } from 'react'; | ||
import { useDispatch } from 'react-redux'; | ||
import { NetworkListItem } from '../..'; | ||
import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../shared/constants/network'; | ||
import { AvatarNetworkSize } from '../../../component-library'; | ||
import { showModal, setEditedNetwork } from '../../../../store/actions'; | ||
import { ACTION_MODES } from '../network-list-menu'; | ||
|
||
type NetworkItemsProps = { | ||
network: NetworkConfiguration; | ||
isUnlocked: boolean; | ||
currentChainId: string; | ||
handleNetworkChange: (network: NetworkConfiguration) => void; | ||
toggleNetworkMenu: () => void; | ||
setActionMode: React.Dispatch<React.SetStateAction<ACTION_MODES>>; | ||
focusSearch: boolean; | ||
showMultiRpcSelectors: boolean; | ||
}; | ||
|
||
export const NetworkItems: React.FC<NetworkItemsProps> = ({ | ||
network, | ||
isUnlocked, | ||
currentChainId, | ||
handleNetworkChange, | ||
toggleNetworkMenu, | ||
setActionMode, | ||
focusSearch, | ||
showMultiRpcSelectors, | ||
}) => { | ||
const isCurrentNetwork = network.chainId === currentChainId; | ||
const canDeleteNetwork = | ||
isUnlocked && !isCurrentNetwork && network.chainId !== CHAIN_IDS.MAINNET; | ||
const dispatch = useDispatch(); | ||
|
||
const onClickCallback = useCallback(() => { | ||
handleNetworkChange(network); | ||
}, [handleNetworkChange, network]); | ||
|
||
const onDeleteClickCallback = useCallback(() => { | ||
dispatch(toggleNetworkMenu()); | ||
dispatch( | ||
showModal({ | ||
name: 'CONFIRM_DELETE_NETWORK', | ||
target: network.chainId, | ||
onConfirm: () => undefined, | ||
}), | ||
); | ||
}, [dispatch, toggleNetworkMenu, showModal, network]); | ||
|
||
const onEditClickCallback = useCallback(() => { | ||
dispatch( | ||
setEditedNetwork({ | ||
chainId: network.chainId, | ||
nickname: network.name, | ||
}), | ||
); | ||
setActionMode(ACTION_MODES.ADD_EDIT); | ||
}, [dispatch, network, setEditedNetwork, setActionMode, ACTION_MODES]); | ||
|
||
const onRpcEndpointClickCallback = useCallback(() => { | ||
setActionMode(ACTION_MODES.SELECT_RPC); | ||
dispatch(setEditedNetwork({ chainId: network.chainId })); | ||
}, [dispatch, network, setEditedNetwork, setActionMode, ACTION_MODES]); | ||
|
||
return ( | ||
<NetworkListItem | ||
name={network.name} | ||
key={network.chainId} | ||
iconSrc={ | ||
CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ | ||
network.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP | ||
] | ||
} | ||
iconSize={AvatarNetworkSize.Sm} | ||
rpcEndpoint={ | ||
showMultiRpcSelectors | ||
? network.rpcEndpoints[network.defaultRpcEndpointIndex] | ||
: undefined | ||
} | ||
chainId={network.chainId} | ||
selected={isCurrentNetwork && !focusSearch} | ||
focus={isCurrentNetwork && !focusSearch} | ||
onClick={onClickCallback} | ||
onDeleteClick={canDeleteNetwork ? onDeleteClickCallback : undefined} | ||
onEditClick={onEditClickCallback} | ||
onRpcEndpointClick={onRpcEndpointClickCallback} | ||
/> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`NetworkItems renders correctly and matches snapshot 1`] = ` | ||
<div> | ||
<div | ||
class="mm-box multichain-network-list-item multichain-network-list-item--selected mm-box--padding-top-4 mm-box--padding-right-4 mm-box--padding-bottom-4 mm-box--padding-left-4 mm-box--display-flex mm-box--gap-4 mm-box--justify-content-space-between mm-box--align-items-center mm-box--width-full mm-box--background-color-primary-muted" | ||
> | ||
<div | ||
class="mm-box multichain-network-list-item__selected-indicator mm-box--background-color-primary-default mm-box--rounded-pill" | ||
/> | ||
<div | ||
class="mm-box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network mm-text--body-sm mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-md mm-box--border-color-background-default mm-box--border-width-1 box--border-style-solid" | ||
> | ||
T | ||
</div> | ||
<div | ||
class="mm-box mm-box--display-flex mm-box--flex-direction-column mm-box--justify-content-flex-start mm-box--align-items-flex-start mm-box--width-full" | ||
style="overflow: hidden;" | ||
> | ||
<div | ||
class="mm-box mm-box--display-flex mm-box--align-items-center mm-box--width-full" | ||
data-testid="Test Network" | ||
> | ||
<div | ||
class="multichain-network-list-item__tooltip" | ||
> | ||
<div | ||
class="" | ||
style="display: inline;" | ||
tabindex="0" | ||
title="" | ||
> | ||
<p | ||
class="mm-box mm-text mm-text--body-md mm-text--ellipsis mm-box--color-text-default mm-box--background-color-transparent" | ||
tabindex="0" | ||
> | ||
Test Network | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<button | ||
aria-label="[networkOptions]" | ||
class="mm-box mm-button-icon mm-button-icon--size-sm mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-icon-default mm-box--background-color-transparent mm-box--rounded-lg" | ||
data-testid="network-list-item-options-button-0x99" | ||
> | ||
<span | ||
class="mm-box mm-icon mm-icon--size-sm mm-box--display-inline-block mm-box--color-inherit" | ||
style="mask-image: url('./images/icons/more-vertical.svg');" | ||
/> | ||
</button> | ||
</div> | ||
</div> | ||
`; |