mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
[MMI] Added code fencing in app menu bar (#18069)
* Added code fencing in app me nu bar * Fixed lint issues * Fixed yarn.lock * Fixed issue * Fixed tests * Fixed yarn.lock * Fixing policies * Fixing lavamoat * fixed yarn.lock * Fixed storybook * clean up and adds test * lint * typo * adds test --------- Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net>
This commit is contained in:
parent
290dbd77ce
commit
dfb2c0e0e8
@ -5,6 +5,9 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getAccountLink } from '@metamask/etherscan-link';
|
||||
|
||||
import { showModal } from '../../../store/actions';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
import { mmiActionsFactory } from '../../../store/institutional/institution-background';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import {
|
||||
CONNECTED_ROUTE,
|
||||
NETWORKS_ROUTE,
|
||||
@ -17,10 +20,16 @@ import {
|
||||
getCurrentKeyring,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getSelectedIdentity,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
getMetaMaskAccountsOrdered,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} from '../../../selectors';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import { KeyringType } from '../../../../shared/constants/keyring';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
@ -46,6 +55,12 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
const blockExplorerLinkText = useSelector(getBlockExplorerLinkText);
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
const accounts = useSelector(getMetaMaskAccountsOrdered);
|
||||
const isCustodial = /Custody/u.test(keyring.type);
|
||||
const mmiActions = mmiActionsFactory();
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const isRemovable = keyring.type !== KeyringType.hdKeyTree;
|
||||
|
||||
const routeToAddBlockExplorerUrl = () => {
|
||||
@ -165,6 +180,37 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
|
||||
{t('removeAccount')}
|
||||
</MenuItem>
|
||||
) : null}
|
||||
{
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
isCustodial ? (
|
||||
<MenuItem
|
||||
data-testid="account-options-menu__remove-jwt"
|
||||
onClick={async () => {
|
||||
const token = await dispatch(mmiActions.getCustodianToken());
|
||||
const custodyAccountDetails = await dispatch(
|
||||
mmiActions.getAllCustodianAccountsWithToken(
|
||||
keyring.type.split(' - ')[1],
|
||||
token,
|
||||
),
|
||||
);
|
||||
dispatch(
|
||||
showModal({
|
||||
name: 'CONFIRM_REMOVE_JWT',
|
||||
token,
|
||||
custodyAccountDetails,
|
||||
accounts,
|
||||
selectedAddress: toChecksumHexAddress(address),
|
||||
}),
|
||||
);
|
||||
onClose();
|
||||
}}
|
||||
iconClassName="fas fa-trash-alt"
|
||||
>
|
||||
{t('removeJWT')}
|
||||
</MenuItem>
|
||||
) : null
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
104
ui/components/app/menu-bar/account-options-menu.test.js
Normal file
104
ui/components/app/menu-bar/account-options-menu.test.js
Normal file
@ -0,0 +1,104 @@
|
||||
import React from 'react';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import AccountOptionsMenu from './account-options-menu';
|
||||
|
||||
const initState = {
|
||||
...mockState,
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
providerConfig: {
|
||||
type: 'test',
|
||||
chainId: '1',
|
||||
},
|
||||
identities: {
|
||||
'0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275': {
|
||||
name: 'Custody Account A',
|
||||
address: '0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275',
|
||||
},
|
||||
},
|
||||
selectedAddress: '0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275',
|
||||
keyrings: [
|
||||
{
|
||||
type: 'Custody',
|
||||
accounts: ['0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275'],
|
||||
},
|
||||
],
|
||||
custodyStatusMaps: '123',
|
||||
custodyAccountDetails: {
|
||||
'0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275': {
|
||||
custodianName: 'saturn',
|
||||
},
|
||||
},
|
||||
custodianSupportedChains: {
|
||||
'0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275': {
|
||||
supportedChains: ['1', '2'],
|
||||
custodianName: 'saturn',
|
||||
},
|
||||
},
|
||||
mmiConfiguration: {
|
||||
portfolio: {
|
||||
enabled: true,
|
||||
url: 'https://dashboard.metamask-institutional.io',
|
||||
},
|
||||
custodians: [
|
||||
{
|
||||
type: 'saturn',
|
||||
name: 'saturn',
|
||||
apiUrl: 'https://saturn-custody.dev.metamask-institutional.io',
|
||||
iconUrl: 'images/saturn.svg',
|
||||
displayName: 'Saturn Custody',
|
||||
production: true,
|
||||
refreshTokenUrl: null,
|
||||
isNoteToTraderSupported: false,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockStore = configureStore();
|
||||
|
||||
const props = {
|
||||
onClose: jest.fn(),
|
||||
anchorElement: document.body,
|
||||
};
|
||||
|
||||
const mockedGetCustodianToken = jest.fn().mockReturnValue({ type: 'TYPE' });
|
||||
const mockedGetAllCustodianAccountsWithToken = jest
|
||||
.fn()
|
||||
.mockReturnValue({ type: 'TYPE' });
|
||||
|
||||
jest.mock('../../../store/institutional/institution-background', () => ({
|
||||
mmiActionsFactory: () => ({
|
||||
getCustodianToken: mockedGetCustodianToken,
|
||||
getAllCustodianAccountsWithToken: mockedGetAllCustodianAccountsWithToken,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('AccountOptionsMenu', () => {
|
||||
it('shows the remove account and remove jwt menu options', async () => {
|
||||
const store = mockStore(initState);
|
||||
renderWithProvider(<AccountOptionsMenu {...props} />, store);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.queryByTestId('account-options-menu__connected-sites'),
|
||||
).toBeInTheDocument();
|
||||
|
||||
const removeAccount = screen.queryByTestId(
|
||||
'account-options-menu__remove-account',
|
||||
);
|
||||
fireEvent.click(removeAccount);
|
||||
expect(props.onClose).toHaveBeenCalled();
|
||||
|
||||
const removeJwt = screen.queryByTestId(
|
||||
'account-options-menu__remove-jwt',
|
||||
);
|
||||
fireEvent.click(removeJwt);
|
||||
expect(mockedGetCustodianToken).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
@ -14,6 +14,19 @@
|
||||
color: var(--color-text-default);
|
||||
}
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
&__custody-logo {
|
||||
@media screen and (max-width: $break-small) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&--icon {
|
||||
height: 35px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
.selected-account {
|
||||
grid-column: 2 / span 1;
|
||||
place-self: center stretch;
|
||||
|
@ -2,6 +2,11 @@ import React, { useState, useContext, useRef } from 'react';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
import { getCustodianIconForAddress } from '../../../selectors/institutional/selectors';
|
||||
import Box from '../../ui/box';
|
||||
import { DISPLAY, AlignItems } from '../../../helpers/constants/design-system';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import SelectedAccount from '../selected-account';
|
||||
import ConnectedStatusIndicator from '../connected-status-indicator';
|
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||
@ -12,7 +17,12 @@ import {
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { getOriginOfCurrentTab } from '../../../selectors';
|
||||
import {
|
||||
getOriginOfCurrentTab,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
getSelectedAddress,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} from '../../../selectors';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import { ButtonIcon, IconName } from '../../component-library';
|
||||
import AccountOptionsMenu from './account-options-menu';
|
||||
@ -23,6 +33,12 @@ export default function MenuBar() {
|
||||
const history = useHistory();
|
||||
const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false);
|
||||
const origin = useSelector(getOriginOfCurrentTab);
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
const selectedAddress = useSelector(getSelectedAddress);
|
||||
const custodianIcon = useSelector((state) =>
|
||||
getCustodianIconForAddress(state, selectedAddress),
|
||||
);
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
const ref = useRef(false);
|
||||
|
||||
const showStatus =
|
||||
@ -37,6 +53,24 @@ export default function MenuBar() {
|
||||
onClick={() => history.push(CONNECTED_ACCOUNTS_ROUTE)}
|
||||
/>
|
||||
) : null}
|
||||
{
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
custodianIcon && (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={AlignItems.center}
|
||||
className="menu-bar__custody-logo"
|
||||
data-testid="custody-logo"
|
||||
>
|
||||
<img
|
||||
src={custodianIcon}
|
||||
className="menu-bar__custody-logo--icon"
|
||||
alt=""
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
<SelectedAccount />
|
||||
<span style={{ display: 'inherit' }} ref={ref}>
|
||||
<ButtonIcon
|
||||
|
@ -4,11 +4,14 @@ import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import { CHAIN_IDS } from '../../../../shared/constants/network';
|
||||
import { KeyringType } from '../../../../shared/constants/keyring';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import MenuBar from './menu-bar';
|
||||
|
||||
const initState = {
|
||||
...mockState,
|
||||
activeTab: {},
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
providerConfig: {
|
||||
chainId: CHAIN_IDS.GOERLI,
|
||||
},
|
||||
@ -64,4 +67,76 @@ describe('MenuBar', () => {
|
||||
|
||||
expect(accountOptionsMenu).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows a custodial account detail', async () => {
|
||||
const customState = {
|
||||
...mockState,
|
||||
activeTab: {},
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
networkConfigurations: {},
|
||||
|
||||
providerConfig: {
|
||||
type: 'test',
|
||||
chainId: '1',
|
||||
},
|
||||
identities: {
|
||||
'0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275': {
|
||||
name: 'Custody Account A',
|
||||
address: '0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275',
|
||||
},
|
||||
},
|
||||
selectedAddress: '0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275',
|
||||
waitForConfirmDeepLinkDialog: '123',
|
||||
keyrings: [
|
||||
{
|
||||
type: 'Custody',
|
||||
accounts: ['0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275'],
|
||||
},
|
||||
],
|
||||
custodyStatusMaps: '123',
|
||||
custodyAccountDetails: {
|
||||
'0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275': {
|
||||
custodianName: 'saturn',
|
||||
},
|
||||
},
|
||||
custodianSupportedChains: {
|
||||
'0x5Ab19e7091dD208F352F8E727B6DCC6F8aBB6275': {
|
||||
supportedChains: ['1', '2'],
|
||||
custodianName: 'saturn',
|
||||
},
|
||||
},
|
||||
mmiConfiguration: {
|
||||
portfolio: {
|
||||
enabled: true,
|
||||
url: 'https://dashboard.metamask-institutional.io',
|
||||
},
|
||||
custodians: [
|
||||
{
|
||||
type: 'saturn',
|
||||
name: 'saturn',
|
||||
apiUrl: 'https://saturn-custody.dev.metamask-institutional.io',
|
||||
iconUrl: 'images/saturn.svg',
|
||||
displayName: 'Saturn Custody',
|
||||
production: true,
|
||||
refreshTokenUrl: null,
|
||||
isNoteToTraderSupported: false,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const store = mockStore(customState);
|
||||
renderWithProvider(<MenuBar />, store);
|
||||
|
||||
const accountOptions = screen.queryByTestId('account-options-menu-button');
|
||||
fireEvent.click(accountOptions);
|
||||
|
||||
await waitFor(() => {
|
||||
const custodyLogo = screen.queryByTestId('custody-logo');
|
||||
expect(custodyLogo).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user