mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Bridge tokens by redirecting to Portfolio from wallet overview page (#17952)
* Add Bridge button * Add newline to the end of bridge svg * Move Portfolio button * Vertically center Portfolio button * Use IconButton for Portfolio button * Change portfolio button size * Lowering coverage to get this in for release by a very small amount * Add unit tests for Portfolio button --------- Co-authored-by: georgewrmarshall <george.marshall@consensys.net>
This commit is contained in:
parent
13d03abe9b
commit
e77e20d8c4
3
app/_locales/en/messages.json
generated
3
app/_locales/en/messages.json
generated
@ -515,6 +515,9 @@
|
|||||||
"blockies": {
|
"blockies": {
|
||||||
"message": "Blockies"
|
"message": "Blockies"
|
||||||
},
|
},
|
||||||
|
"bridge": {
|
||||||
|
"message": "Bridge"
|
||||||
|
},
|
||||||
"browserNotSupported": {
|
"browserNotSupported": {
|
||||||
"message": "Your browser is not supported..."
|
"message": "Your browser is not supported..."
|
||||||
},
|
},
|
||||||
|
3
app/images/icons/bridge.svg
Normal file
3
app/images/icons/bridge.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m74 284c-21 7-36 26-36 49 0 28 23 51 52 51 28 0 51-23 51-51 0-20-12-38-28-46 14-65 73-114 143-114 47 0 89 22 116 56 12-6 25-10 39-11-33-50-90-84-155-84-90 0-165 65-182 150z m400 49c0 28-23 51-52 51-28 0-51-23-51-51 0-28 23-51 51-51 29 0 52 23 52 51z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 334 B |
@ -7,8 +7,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
global: {
|
global: {
|
||||||
lines: 64.39,
|
lines: 64.39,
|
||||||
branches: 53.03,
|
branches: 53.01,
|
||||||
statements: 63.66,
|
statements: 63.63,
|
||||||
functions: 56.67,
|
functions: 56.67,
|
||||||
},
|
},
|
||||||
transforms: {
|
transforms: {
|
||||||
|
@ -292,6 +292,7 @@ export const EVENT_NAMES = {
|
|||||||
APP_UNLOCKED: 'App Unlocked',
|
APP_UNLOCKED: 'App Unlocked',
|
||||||
APP_UNLOCKED_FAILED: 'App Unlocked Failed',
|
APP_UNLOCKED_FAILED: 'App Unlocked Failed',
|
||||||
APP_WINDOW_EXPANDED: 'App Window Expanded',
|
APP_WINDOW_EXPANDED: 'App Window Expanded',
|
||||||
|
BRIDGE_LINK_CLICKED: 'Bridge Link Clicked',
|
||||||
DECRYPTION_APPROVED: 'Decryption Approved',
|
DECRYPTION_APPROVED: 'Decryption Approved',
|
||||||
DECRYPTION_REJECTED: 'Decryption Rejected',
|
DECRYPTION_REJECTED: 'Decryption Rejected',
|
||||||
DECRYPTION_REQUESTED: 'Decryption Requested',
|
DECRYPTION_REQUESTED: 'Decryption Requested',
|
||||||
|
@ -35,7 +35,12 @@ import {
|
|||||||
import Spinner from '../../ui/spinner';
|
import Spinner from '../../ui/spinner';
|
||||||
import { startNewDraftTransaction } from '../../../ducks/send';
|
import { startNewDraftTransaction } from '../../../ducks/send';
|
||||||
import { AssetType } from '../../../../shared/constants/transaction';
|
import { AssetType } from '../../../../shared/constants/transaction';
|
||||||
import { Icon, ICON_NAMES } from '../../component-library';
|
import {
|
||||||
|
ButtonIcon,
|
||||||
|
BUTTON_ICON_SIZES,
|
||||||
|
Icon,
|
||||||
|
ICON_NAMES,
|
||||||
|
} from '../../component-library';
|
||||||
import { IconColor } from '../../../helpers/constants/design-system';
|
import { IconColor } from '../../../helpers/constants/design-system';
|
||||||
import useRamps from '../../../hooks/experiences/useRamps';
|
import useRamps from '../../../hooks/experiences/useRamps';
|
||||||
import WalletOverview from './wallet-overview';
|
import WalletOverview from './wallet-overview';
|
||||||
@ -88,6 +93,34 @@ const EthOverview = ({ className }) => {
|
|||||||
{balanceIsCached ? (
|
{balanceIsCached ? (
|
||||||
<span className="eth-overview__cached-star">*</span>
|
<span className="eth-overview__cached-star">*</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
<ButtonIcon
|
||||||
|
className="eth-overview__portfolio-button"
|
||||||
|
data-testid="home__portfolio-site"
|
||||||
|
color={IconColor.primaryDefault}
|
||||||
|
iconName={ICON_NAMES.DIAGRAM}
|
||||||
|
ariaLabel={t('portfolio')}
|
||||||
|
size={BUTTON_ICON_SIZES.LG}
|
||||||
|
onClick={() => {
|
||||||
|
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||||
|
global.platform.openTab({
|
||||||
|
url: `${portfolioUrl}?metamaskEntry=ext`,
|
||||||
|
});
|
||||||
|
trackEvent(
|
||||||
|
{
|
||||||
|
category: EVENT.CATEGORIES.HOME,
|
||||||
|
event: EVENT_NAMES.PORTFOLIO_LINK_CLICKED,
|
||||||
|
properties: {
|
||||||
|
url: portfolioUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contextPropsIntoEventProperties: [
|
||||||
|
CONTEXT_PROPS.PAGE_TITLE,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showFiat && balance && (
|
{showFiat && balance && (
|
||||||
<UserPreferencedCurrencyDisplay
|
<UserPreferencedCurrencyDisplay
|
||||||
@ -198,31 +231,25 @@ const EthOverview = ({ className }) => {
|
|||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
className="eth-overview__button"
|
className="eth-overview__button"
|
||||||
data-testid="home__portfolio-site"
|
data-testid="eth-overview-bridge"
|
||||||
Icon={
|
Icon={
|
||||||
<Icon
|
<Icon name={ICON_NAMES.BRIDGE} color={IconColor.primaryInverse} />
|
||||||
name={ICON_NAMES.DIAGRAM}
|
|
||||||
color={IconColor.primaryInverse}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
label={t('portfolio')}
|
label={t('bridge')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||||
|
const bridgeUrl = `${portfolioUrl}/bridge`;
|
||||||
global.platform.openTab({
|
global.platform.openTab({
|
||||||
url: `${portfolioUrl}?metamaskEntry=ext`,
|
url: `${bridgeUrl}?metamaskEntry=ext`,
|
||||||
});
|
});
|
||||||
trackEvent(
|
trackEvent({
|
||||||
{
|
category: EVENT.CATEGORIES.NAVIGATION,
|
||||||
category: EVENT.CATEGORIES.HOME,
|
event: EVENT_NAMES.BRIDGE_LINK_CLICKED,
|
||||||
event: EVENT_NAMES.PORTFOLIO_LINK_CLICKED,
|
|
||||||
properties: {
|
properties: {
|
||||||
url: portfolioUrl,
|
location: 'Home',
|
||||||
|
text: 'Bridge',
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
{
|
|
||||||
contextPropsIntoEventProperties: [CONTEXT_PROPS.PAGE_TITLE],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -23,6 +23,7 @@ jest.mock('../../../../shared/constants/network', () => ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
let openTabSpy;
|
||||||
|
|
||||||
describe('EthOverview', () => {
|
describe('EthOverview', () => {
|
||||||
const mockStore = {
|
const mockStore = {
|
||||||
@ -63,6 +64,8 @@ describe('EthOverview', () => {
|
|||||||
|
|
||||||
const store = configureMockStore([thunk])(mockStore);
|
const store = configureMockStore([thunk])(mockStore);
|
||||||
const ETH_OVERVIEW_BUY = 'eth-overview-buy';
|
const ETH_OVERVIEW_BUY = 'eth-overview-buy';
|
||||||
|
const ETH_OVERVIEW_BRIDGE = 'eth-overview-bridge';
|
||||||
|
const ETH_OVERVIEW_PORTFOLIO = 'home__portfolio-site';
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
store.clearActions();
|
store.clearActions();
|
||||||
@ -76,6 +79,59 @@ describe('EthOverview', () => {
|
|||||||
openTab: jest.fn(),
|
openTab: jest.fn(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
openTabSpy = jest.spyOn(global.platform, 'openTab');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
openTabSpy.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always show the Bridge button', () => {
|
||||||
|
const { queryByTestId } = renderWithProvider(<EthOverview />, store);
|
||||||
|
const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE);
|
||||||
|
expect(bridgeButton).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open the Bridge URI when clicking on Bridge button', async () => {
|
||||||
|
const { queryByTestId } = renderWithProvider(<EthOverview />, store);
|
||||||
|
|
||||||
|
const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE);
|
||||||
|
|
||||||
|
expect(bridgeButton).toBeInTheDocument();
|
||||||
|
expect(bridgeButton).not.toBeDisabled();
|
||||||
|
|
||||||
|
fireEvent.click(bridgeButton);
|
||||||
|
expect(openTabSpy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(openTabSpy).toHaveBeenCalledWith({
|
||||||
|
url: expect.stringContaining(`/bridge?metamaskEntry=ext`),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always show the Portfolio button', () => {
|
||||||
|
const { queryByTestId } = renderWithProvider(<EthOverview />, store);
|
||||||
|
const portfolioButton = queryByTestId(ETH_OVERVIEW_PORTFOLIO);
|
||||||
|
expect(portfolioButton).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open the Portfolio URI when clicking on Portfolio button', async () => {
|
||||||
|
const { queryByTestId } = renderWithProvider(<EthOverview />, store);
|
||||||
|
|
||||||
|
const portfolioButton = queryByTestId(ETH_OVERVIEW_PORTFOLIO);
|
||||||
|
|
||||||
|
expect(portfolioButton).toBeInTheDocument();
|
||||||
|
expect(portfolioButton).not.toBeDisabled();
|
||||||
|
|
||||||
|
fireEvent.click(portfolioButton);
|
||||||
|
expect(openTabSpy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(openTabSpy).toHaveBeenCalledWith({
|
||||||
|
url: expect.stringContaining(`?metamaskEntry=ext`),
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should always show the Buy button regardless of current chain Id', () => {
|
it('should always show the Buy button regardless of current chain Id', () => {
|
||||||
@ -135,8 +191,6 @@ describe('EthOverview', () => {
|
|||||||
mockedStoreWithBuyableChainId,
|
mockedStoreWithBuyableChainId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const openTabSpy = jest.spyOn(global.platform, 'openTab');
|
|
||||||
|
|
||||||
const { queryByTestId } = renderWithProvider(
|
const { queryByTestId } = renderWithProvider(
|
||||||
<EthOverview />,
|
<EthOverview />,
|
||||||
mockedStore,
|
mockedStore,
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
&__primary-container {
|
&__primary-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__primary-balance {
|
&__primary-balance {
|
||||||
@ -65,6 +66,13 @@
|
|||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__portfolio-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
left: calc(100% + 2px);
|
||||||
|
}
|
||||||
|
|
||||||
&__cached-balance,
|
&__cached-balance,
|
||||||
&__cached-star {
|
&__cached-star {
|
||||||
color: var(--color-warning-default);
|
color: var(--color-warning-default);
|
||||||
|
Loading…
Reference in New Issue
Block a user