mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
18566 firefox ledger u2f message (#18570)
* check for user agent * fix regex * fix lint * update link * add test * update message * update coverage * fix test names * update text * add whats new notification for firefox and ledger users * update action button link * update notification text * update viewed notification * update coverage * update coverage
This commit is contained in:
parent
34c1e5a2a1
commit
fa6e26744d
29
app/_locales/en/messages.json
generated
29
app/_locales/en/messages.json
generated
@ -2537,6 +2537,19 @@
|
||||
"message": "Swapping on mobile is here!",
|
||||
"description": "Title for a notification in the 'See What's New' popup. Tells users that they can now use MetaMask Swaps on Mobile."
|
||||
},
|
||||
"notifications20ActionText": {
|
||||
"message": "Learn more",
|
||||
"description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a ledger page to resolve the U2F connection issue."
|
||||
},
|
||||
|
||||
"notifications20Description": {
|
||||
"message": "If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support.",
|
||||
"description": "Description of a notification in the 'See What's New' popup. Describes the U2F support being dropped by firefox and that it affects ledger users."
|
||||
},
|
||||
"notifications20Title": {
|
||||
"message": "Ledger and Firefox Users Experiencing Connection Issues",
|
||||
"description": "Title for a notification in the 'See What's New' popup. Tells users that latest firefox users using U2F may experience connection issues."
|
||||
},
|
||||
"notifications3ActionText": {
|
||||
"message": "Read more",
|
||||
"description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a page about security on the metamask support website."
|
||||
@ -4541,6 +4554,22 @@
|
||||
"transferFrom": {
|
||||
"message": "Transfer from"
|
||||
},
|
||||
"troubleConnectingToLedgerU2FOnFirefox": {
|
||||
"message": "We're having trouble connecting your Ledger. $1",
|
||||
"description": "$1 is a link to the wallet connection guide;"
|
||||
},
|
||||
"troubleConnectingToLedgerU2FOnFirefox2": {
|
||||
"message": "Review our hardware wallet connection guide and try again.",
|
||||
"description": "$1 of the ledger wallet connection guide"
|
||||
},
|
||||
"troubleConnectingToLedgerU2FOnFirefoxLedgerSolution": {
|
||||
"message": "If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support. Learn how to fix this issue $1.",
|
||||
"description": "It is a link to the ledger website for the workaround."
|
||||
},
|
||||
"troubleConnectingToLedgerU2FOnFirefoxLedgerSolution2": {
|
||||
"message": "here",
|
||||
"description": "Second part of the error message; It is a link to the ledger website for the workaround."
|
||||
},
|
||||
"troubleConnectingToWallet": {
|
||||
"message": "We had trouble connecting to your $1, try reviewing $2 and try again.",
|
||||
"description": "$1 is the wallet device name; $2 is a link to wallet connection guide"
|
||||
|
@ -6,10 +6,10 @@
|
||||
// subset of files to check against these targets.
|
||||
module.exports = {
|
||||
global: {
|
||||
lines: 67.8,
|
||||
branches: 55.84,
|
||||
statements: 67.13,
|
||||
functions: 59.66,
|
||||
lines: 68.5,
|
||||
branches: 56.34,
|
||||
statements: 67.86,
|
||||
functions: 60.69,
|
||||
},
|
||||
transforms: {
|
||||
branches: 100,
|
||||
|
@ -102,6 +102,10 @@ export const UI_NOTIFICATIONS = {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
20: {
|
||||
id: 20,
|
||||
date: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const getTranslatedUINotifications = (t, locale) => {
|
||||
@ -279,5 +283,16 @@ export const getTranslatedUINotifications = (t, locale) => {
|
||||
)
|
||||
: '',
|
||||
},
|
||||
20: {
|
||||
...UI_NOTIFICATIONS[20],
|
||||
title: t('notifications20Title'),
|
||||
description: [t('notifications20Description')],
|
||||
actionText: t('notifications20ActionText'),
|
||||
date: UI_NOTIFICATIONS[20].date
|
||||
? new Intl.DateTimeFormat(formattedLocale).format(
|
||||
new Date(UI_NOTIFICATIONS[20].date),
|
||||
)
|
||||
: '',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -73,6 +73,12 @@ function getActionFunctionById(id, history) {
|
||||
updateViewedNotifications({ 19: true });
|
||||
history.push(`${EXPERIMENTAL_ROUTE}#autodetect-nfts`);
|
||||
},
|
||||
20: () => {
|
||||
updateViewedNotifications({ 20: true });
|
||||
global.platform.openTab({
|
||||
url: ZENDESK_URLS.LEDGER_FIREFOX_U2F_GUIDE,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return actionFunctions[id];
|
||||
|
@ -15,6 +15,8 @@ const ZENDESK_URLS = {
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/360015289932',
|
||||
INFURA_BLOCKAGE:
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/360059386712',
|
||||
LEDGER_FIREFOX_U2F_GUIDE:
|
||||
'https://support.ledger.com/hc/en-us/articles/10371387758493-MetaMask-Firefox-Ledger-Integration-Issue?support=true',
|
||||
LEGACY_WEB3: 'https://metamask.zendesk.com/hc/en-us/articles/360053147012',
|
||||
NFT_TOKENS:
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/360058238591-NFT-tokens-in-MetaMask-wallet',
|
||||
|
File diff suppressed because one or more lines are too long
@ -20,7 +20,14 @@ import {
|
||||
HardwareDeviceNames,
|
||||
LedgerTransportTypes,
|
||||
} from '../../../../shared/constants/hardware-wallets';
|
||||
import {
|
||||
BUTTON_TYPES,
|
||||
BUTTON_SIZES,
|
||||
Button,
|
||||
Text,
|
||||
} from '../../../components/component-library';
|
||||
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
||||
import { TextColor } from '../../../helpers/constants/design-system';
|
||||
import SelectHardware from './select-hardware';
|
||||
import AccountList from './account-list';
|
||||
|
||||
@ -74,6 +81,7 @@ class ConnectHardwareForm extends Component {
|
||||
browserSupported: true,
|
||||
unlocked: false,
|
||||
device: null,
|
||||
isFirefox: false,
|
||||
};
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
@ -89,6 +97,10 @@ class ConnectHardwareForm extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.checkIfUnlocked();
|
||||
const useAgent = window.navigator.userAgent;
|
||||
if (/Firefox/u.test(useAgent)) {
|
||||
this.setState({ isFirefox: true });
|
||||
}
|
||||
}
|
||||
|
||||
async checkIfUnlocked() {
|
||||
@ -287,23 +299,64 @@ class ConnectHardwareForm extends Component {
|
||||
|
||||
renderError() {
|
||||
if (this.state.error === U2F_ERROR) {
|
||||
if (this.state.device === 'ledger' && this.state.isFirefox) {
|
||||
return (
|
||||
<>
|
||||
<Text color={TextColor.warningDefault} margin={[5, 5, 2]}>
|
||||
{this.context.t('troubleConnectingToLedgerU2FOnFirefox', [
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Button
|
||||
type={BUTTON_TYPES.LINK}
|
||||
href={ZENDESK_URLS.HARDWARE_CONNECTION}
|
||||
size={BUTTON_SIZES.INHERIT}
|
||||
key="u2f-error-1"
|
||||
as="a"
|
||||
block={false}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{this.context.t('troubleConnectingToLedgerU2FOnFirefox2')}
|
||||
</Button>,
|
||||
])}
|
||||
</Text>
|
||||
<Text color={TextColor.warningDefault} margin={[5, 5, 2]}>
|
||||
{this.context.t(
|
||||
'troubleConnectingToLedgerU2FOnFirefoxLedgerSolution',
|
||||
[
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Button
|
||||
type={BUTTON_TYPES.LINK}
|
||||
href={ZENDESK_URLS.LEDGER_FIREFOX_U2F_GUIDE}
|
||||
size={BUTTON_SIZES.INHERIT}
|
||||
key="u2f-error-1"
|
||||
as="a"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{this.context.t(
|
||||
'troubleConnectingToLedgerU2FOnFirefoxLedgerSolution2',
|
||||
)}
|
||||
</Button>,
|
||||
],
|
||||
)}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<p className="hw-connect__error">
|
||||
<Text color={TextColor.warningDefault} margin={[5, 5, 2]}>
|
||||
{this.context.t('troubleConnectingToWallet', [
|
||||
this.state.device,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<a
|
||||
<Button
|
||||
type={BUTTON_TYPES.LINK}
|
||||
href={ZENDESK_URLS.HARDWARE_CONNECTION}
|
||||
key="hardware-connection-guide"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hw-connect__link"
|
||||
style={{ marginLeft: '5px', marginRight: '5px' }}
|
||||
key="u2f-error-1"
|
||||
>
|
||||
{this.context.t('walletConnectionGuide')}
|
||||
</a>,
|
||||
</Button>,
|
||||
])}
|
||||
</p>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
return this.state.error ? (
|
||||
|
151
ui/pages/create-account/connect-hardware/index.test.tsx
Normal file
151
ui/pages/create-account/connect-hardware/index.test.tsx
Normal file
@ -0,0 +1,151 @@
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import thunk from 'redux-thunk';
|
||||
import React from 'react';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import {
|
||||
LedgerTransportTypes,
|
||||
HardwareDeviceNames,
|
||||
} from '../../../../shared/constants/hardware-wallets';
|
||||
import ConnectHardwareForm from '.';
|
||||
|
||||
const mockConnectHardware = jest.fn();
|
||||
const mockCheckHardwareStatus = jest.fn().mockResolvedValue(false);
|
||||
|
||||
jest.mock('../../../store/actions', () => ({
|
||||
connectHardware: () => mockConnectHardware,
|
||||
checkHardwareStatus: () => mockCheckHardwareStatus,
|
||||
}));
|
||||
|
||||
jest.mock('../../../selectors', () => ({
|
||||
getCurrentChainId: () => jest.fn().mockResolvedValue('0x1'),
|
||||
getRpcPrefsForCurrentProvider: () => jest.fn().mockResolvedValue({}),
|
||||
getMetaMaskAccountsConnected: () => jest.fn().mockResolvedValue([]),
|
||||
getMetaMaskAccounts: () => jest.fn().mockResolvedValue([]),
|
||||
}));
|
||||
|
||||
jest.mock('../../../ducks/history/history', () => ({
|
||||
getMostRecentOverviewPage: () => jest.fn().mockResolvedValue('/'),
|
||||
}));
|
||||
|
||||
const mockProps = {
|
||||
forgetDevice: jest.fn(),
|
||||
showAlert: jest.fn(),
|
||||
hideAlert: jest.fn(),
|
||||
unlockHardwareWalletAccount: jest.fn(),
|
||||
setHardwareWalletDefaultHdPath: jest.fn(),
|
||||
history: {},
|
||||
defaultHdPath: "m/44'/60'/0'/0",
|
||||
mostRecentOverviewPage: '',
|
||||
};
|
||||
|
||||
const mockState = {
|
||||
metamask: {
|
||||
provider: {
|
||||
chainId: '0x1',
|
||||
},
|
||||
},
|
||||
appState: {
|
||||
networkDropdownOpen: false,
|
||||
gasIsLoading: false,
|
||||
isLoading: false,
|
||||
modal: {
|
||||
open: false,
|
||||
modalState: {
|
||||
name: null,
|
||||
props: {},
|
||||
},
|
||||
previousModalState: {
|
||||
name: null,
|
||||
},
|
||||
},
|
||||
warning: null,
|
||||
chainId: '0x1',
|
||||
rpcPrefs: null,
|
||||
accounts: [],
|
||||
connectedAccounts: [],
|
||||
defaultHdPaths: {
|
||||
[HardwareDeviceNames.lattice]: "m/44'/60'/0'/0",
|
||||
[HardwareDeviceNames.ledger]: "m/44'/60'/0'/0",
|
||||
[HardwareDeviceNames.trezor]: "m/44'/60'/0'/0",
|
||||
},
|
||||
mostRecentOverviewPage: '',
|
||||
ledgerTransportType: LedgerTransportTypes.webhid,
|
||||
},
|
||||
};
|
||||
|
||||
describe('ConnectHardwareForm', () => {
|
||||
const mockStore = configureMockStore([thunk])(mockState);
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<ConnectHardwareForm {...mockProps} />,
|
||||
mockStore,
|
||||
);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('U2F Error', () => {
|
||||
it('should render a U2F error', async () => {
|
||||
mockConnectHardware.mockRejectedValue(new Error('U2F Error'));
|
||||
const mockStateWithU2F = Object.assign(mockState, {});
|
||||
mockStateWithU2F.appState.ledgerTransportType = LedgerTransportTypes.u2f;
|
||||
const mockStoreWithU2F = configureMockStore([thunk])(mockStateWithU2F);
|
||||
const { getByText, getByLabelText, queryByText } = renderWithProvider(
|
||||
<ConnectHardwareForm {...mockProps} />,
|
||||
mockStoreWithU2F,
|
||||
);
|
||||
|
||||
const ledgerButton = getByLabelText('Ledger');
|
||||
const continueButton = getByText('Continue');
|
||||
|
||||
fireEvent.click(ledgerButton);
|
||||
fireEvent.click(continueButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
getByText('We had trouble connecting to your ledger, try reviewing', {
|
||||
exact: false,
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
const firefoxError = queryByText(
|
||||
"If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support. Learn how to fix this issue",
|
||||
{ exact: false },
|
||||
);
|
||||
expect(firefoxError).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render a different U2F error for firefox', async () => {
|
||||
jest
|
||||
.spyOn(window.navigator, 'userAgent', 'get')
|
||||
.mockReturnValue(
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0',
|
||||
);
|
||||
|
||||
mockConnectHardware.mockRejectedValue(new Error('U2F Error'));
|
||||
const mockStateWithU2F = Object.assign(mockState, {});
|
||||
mockStateWithU2F.appState.ledgerTransportType = LedgerTransportTypes.u2f;
|
||||
const mockStoreWithU2F = configureMockStore([thunk])(mockStateWithU2F);
|
||||
const { getByText, getByLabelText } = renderWithProvider(
|
||||
<ConnectHardwareForm {...mockProps} />,
|
||||
mockStoreWithU2F,
|
||||
);
|
||||
|
||||
const ledgerButton = getByLabelText('Ledger');
|
||||
const continueButton = getByText('Continue');
|
||||
|
||||
fireEvent.click(ledgerButton);
|
||||
fireEvent.click(continueButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
getByText(
|
||||
"If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support. Learn how to fix this issue",
|
||||
{ exact: false },
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -935,6 +935,7 @@ function getAllowedAnnouncementIds(state) {
|
||||
const supportsWebHid = window.navigator.hid !== undefined;
|
||||
const currentlyUsingLedgerLive =
|
||||
getLedgerTransportType(state) === LedgerTransportTypes.live;
|
||||
const isFirefox = window.navigator.userAgent.includes('Firefox');
|
||||
|
||||
return {
|
||||
1: false,
|
||||
@ -956,6 +957,7 @@ function getAllowedAnnouncementIds(state) {
|
||||
17: false,
|
||||
18: true,
|
||||
19: true,
|
||||
20: currentKeyringIsLedger && isFirefox,
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user