Skip to content
Merged
6 changes: 3 additions & 3 deletions ui/components/app/alerts/alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import PropTypes from 'prop-types';
import { alertIsOpen as invalidCustomNetworkAlertIsOpen } from '../../../ducks/alerts/invalid-custom-network';
import InvalidCustomNetworkAlert from './invalid-custom-network-alert';

const Alerts = ({ history }) => {
const Alerts = ({ navigate }) => {
const _invalidCustomNetworkAlertIsOpen = useSelector(
invalidCustomNetworkAlertIsOpen,
);

if (_invalidCustomNetworkAlertIsOpen) {
return <InvalidCustomNetworkAlert history={history} />;
return <InvalidCustomNetworkAlert navigate={navigate} />;
}

return null;
};

Alerts.propTypes = {
history: PropTypes.object.isRequired,
navigate: PropTypes.func.isRequired,
};

export default Alerts;
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { NETWORKS_ROUTE } from '../../../../helpers/constants/routes';

const { ERROR, LOADING } = ALERT_STATE;

const InvalidCustomNetworkAlert = ({ history }) => {
const InvalidCustomNetworkAlert = ({ navigate }) => {
const t = useI18nContext();
const dispatch = useDispatch();
const alertState = useSelector(getAlertState);
Expand Down Expand Up @@ -43,7 +43,7 @@ const InvalidCustomNetworkAlert = ({ history }) => {
disabled={alertState === LOADING}
onClick={async () => {
await onClose();
history.push(NETWORKS_ROUTE);
navigate(NETWORKS_ROUTE);
}}
variant={ButtonVariant.Primary}
className="invalid-custom-network-alert__footer-row-button"
Expand Down Expand Up @@ -82,7 +82,7 @@ const InvalidCustomNetworkAlert = ({ history }) => {
};

InvalidCustomNetworkAlert.propTypes = {
history: PropTypes.object.isRequired,
navigate: PropTypes.func.isRequired,
};

export default InvalidCustomNetworkAlert;
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@ const meta: Meta<typeof InvalidCustomNetworkAlert> = {
),
],
argTypes: {
history: {
control: 'object',
navigate: {
control: 'function',
},
},
args: {
history: {
push: () => {},
},
navigate: () => {},
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ import useFetchNftDetailsFromTokenURI from '../../../../../hooks/useFetchNftDeta
import { isWebUrl } from '../../../../../../app/scripts/lib/util';
import { getNetworkConfigurationsByChainId } from '../../../../../../shared/modules/selectors/networks';
import { getImageForChainId } from '../../../../../selectors/multichain';
import { ASSET_ROUTE } from '../../../../../helpers/constants/routes';
import {
ASSET_ROUTE,
PREVIOUS_ROUTE,
} from '../../../../../helpers/constants/routes';

type NftFullImageProps = {
params?: {
Expand Down Expand Up @@ -102,7 +105,7 @@ export default function NftFullImage({ params }: NftFullImageProps) {
const onClose = useCallback(() => {
if (navigationType === 'PUSH') {
// Previous navigation was a PUSH, so safe to go back
navigate(-1);
navigate(PREVIOUS_ROUTE);
} else {
// Fallback: go to the asset details route explicitly
navigate(`${ASSET_ROUTE}/${hexChainId}/${asset}/${id}`, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function mapStateToProps(state) {
return {
chainId: getCurrentChainId(state),
token: state.appState.modal.modalState.props.token,
history: state.appState.modal.modalState.props.history,
navigate: state.appState.modal.modalState.props.navigate,
networkConfigurationsByChainId: getNetworkConfigurationsByChainId(state),
getAccountForChain: (caipChainId) =>
getInternalAccountBySelectedAccountGroupAndCaip(state, caipChainId),
Expand Down Expand Up @@ -85,7 +85,7 @@ class HideTokenConfirmationModal extends Component {
image: PropTypes.string,
chainId: PropTypes.string,
}),
history: PropTypes.object,
navigate: PropTypes.func,
};

state = {};
Expand All @@ -96,7 +96,7 @@ class HideTokenConfirmationModal extends Component {
token,
hideToken,
hideModal,
history,
navigate,
networkConfigurationsByChainId,
getAccountForChain,
} = this.props;
Expand Down Expand Up @@ -154,7 +154,7 @@ class HideTokenConfirmationModal extends Component {
getAccountForChain,
);
}
history.push(DEFAULT_ROUTE);
navigate(DEFAULT_ROUTE);
}}
>
{this.context.t('hide')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import configureMockStore from 'redux-mock-store';
import { fireEvent } from '@testing-library/react';
import thunk from 'redux-thunk';
import * as actions from '../../../../store/actions';
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
import { renderWithProvider } from '../../../../../test/lib/render-helpers-navigate';
import mockState from '../../../../../test/data/mock-state.json';
import { mockNetworkState } from '../../../../../test/stub/networks';
import HideTokenConfirmationModal from '.';

const mockHistoryPush = jest.fn();
const mockUseNavigate = jest.fn();
const mockHideModal = jest.fn();
const mockHideToken = jest.fn().mockResolvedValue();

Expand Down Expand Up @@ -40,9 +40,7 @@ describe('Hide Token Confirmation Modal', () => {
modal: {
modalState: {
props: {
history: {
push: mockHistoryPush,
},
navigate: mockUseNavigate,
token: tokenState,
},
},
Expand Down Expand Up @@ -105,9 +103,7 @@ describe('Hide Token Confirmation Modal', () => {
modal: {
modalState: {
props: {
history: {
push: mockHistoryPush,
},
navigate: mockUseNavigate,
token: tokenState2,
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { fireEvent } from '@testing-library/react';
import { BtcAccountType } from '@metamask/keyring-api';
import { renderWithProvider } from '../../../../../test/jest';
import { renderWithProvider } from '../../../../../test/lib/render-helpers-navigate';
import configureStore from '../../../../store/store';
import mockState from '../../../../../test/data/mock-state.json';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const DefaultStory: StoryFn<typeof SRPQuiz> = () => {
<SRPQuiz
isOpen={isShowingModal}
onClose={() => updateArgs({ isShowingModal: false })}
navigate={() => {}}
/>
)}
</>
Expand Down
3 changes: 2 additions & 1 deletion ui/components/app/srp-quiz-modal/SRPQuiz/SRPQuiz.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ describe('srp-reveal-quiz', () => {
});

it('should go through the full sequence of steps', async () => {
renderWithProvider(<SRPQuiz isOpen />, store);
const mockNavigate = jest.fn();
renderWithProvider(<SRPQuiz isOpen navigate={mockNavigate} />, store);

expect(screen.queryByTestId('srp-quiz-get-started')).toBeInTheDocument();

Expand Down
12 changes: 9 additions & 3 deletions ui/components/app/srp-quiz-modal/SRPQuiz/SRPQuiz.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports, import/no-commonjs */
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
import type { To } from 'react-router-dom-v5-compat';
import {
MetaMetricsEventCategory,
MetaMetricsEventKeyType,
Expand Down Expand Up @@ -64,6 +64,13 @@ export type SRPQuizProps = {
isOpen: boolean;
onClose: () => void;
closeAfterCompleting?: boolean;
navigate: {
(
to: To,
options?: { replace?: boolean; state?: Record<string, unknown> },
): void;
(delta: number): void;
};
};

// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31860
Expand All @@ -72,7 +79,6 @@ export default function SRPQuiz(props: SRPQuizProps): JSX.Element {
const [stage, setStage] = useState<QuizStage>(QuizStage.introduction);

const trackEvent = useContext(MetaMetricsContext);
const history = useHistory();
const t = useI18nContext();
const hdEntropyIndex = useSelector(getHDEntropyIndex);

Expand Down Expand Up @@ -237,7 +243,7 @@ export default function SRPQuiz(props: SRPQuizProps): JSX.Element {
route = `${REVEAL_SEED_ROUTE}/${props.keyringId}`;
}

history.push(route);
props.navigate(route);
if (props.closeAfterCompleting) {
props.onClose();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default class TransactionListItemDetails extends PureComponent {
senderNickname: PropTypes.string.isRequired,
transactionStatus: PropTypes.func,
isCustomNetwork: PropTypes.bool,
history: PropTypes.object,
navigate: PropTypes.func.isRequired,
blockExplorerLinkText: PropTypes.object,
chainId: PropTypes.string,
networkConfiguration: PropTypes.object,
Expand All @@ -66,7 +66,7 @@ export default class TransactionListItemDetails extends PureComponent {
transactionGroup: { primaryTransaction },
networkConfiguration,
isCustomNetwork,
history,
navigate,
onClose,
chainId,
} = this.props;
Expand All @@ -87,7 +87,7 @@ export default class TransactionListItemDetails extends PureComponent {

if (!rpcPrefs.blockExplorerUrl && isCustomNetwork) {
onClose();
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
navigate(`${NETWORKS_ROUTE}#blockExplorerUrl`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: TransactionListItemDetails crashes due to missing navigate prop

The TransactionListItemDetails class component was updated to expect a navigate prop instead of history, but it is not wrapped with withRouterHooks nor is its parent (TransactionListItem, which is not in the diff) updated to pass this prop. This will cause a runtime error when attempting to navigate to the block explorer.

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The component is already correctly wrapped with withRouterHooks and will receive the navigate prop. The bug was likely fixed earlier in the migration. No changes needed :)

} else {
this.context.trackEvent({
category: MetaMetricsEventCategory.Transactions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React from 'react';
import configureStore from 'redux-mock-store';
import mockUnifiedSwapTxGroup from '../../../../test/data/swap/mock-unified-swap-transaction-group.json';
import mockBridgeTxData from '../../../../test/data/bridge/mock-bridge-transaction-details.json';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import { renderWithProvider } from '../../../../test/lib/render-helpers-navigate';
import { createBridgeMockStore } from '../../../../test/data/bridge/mock-bridge-store';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import TransactionListItem from '.';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const AccountShowSrpRow = ({ account }: AccountShowSrpRowProps) => {
isOpen={srpQuizModalVisible}
onClose={() => setSrpQuizModalVisible(false)}
closeAfterCompleting
navigate={navigate}
/>
) : null}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import React from 'react';
import {
render,
screen,
fireEvent,
waitFor,
act,
} from '@testing-library/react';
import { Provider } from 'react-redux';
import { screen, fireEvent, waitFor, act } from '@testing-library/react';
import configureStore from 'redux-mock-store';
import { InternalAccount } from '@metamask/keyring-internal-api';
import {
Expand All @@ -16,6 +9,7 @@ import {
toAccountWalletId,
} from '@metamask/account-api';
import { CaipChainId } from '@metamask/utils';
import { renderWithProvider } from '../../../../test/lib/render-helpers-navigate';
import { MULTICHAIN_ACCOUNT_ADDRESS_LIST_PAGE_ROUTE } from '../../../helpers/constants/routes';
import {
getInternalAccountListSpreadByScopesByGroupId,
Expand All @@ -26,14 +20,13 @@ import { selectBalanceForAllWallets } from '../../../selectors/assets';
import { MultichainHoveredAddressRowsList } from './multichain-hovered-address-rows-hovered-list';

const mockStore = configureStore([]);
const mockPush = jest.fn();

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: () => ({
push: mockPush,
}),
}));
const mockUseNavigate = jest.fn();
jest.mock('react-router-dom-v5-compat', () => {
return {
...jest.requireActual('react-router-dom-v5-compat'),
useNavigate: () => mockUseNavigate,
};
});

jest.mock('../../../selectors/multichain-accounts/account-tree', () => ({
...jest.requireActual('../../../selectors/multichain-accounts/account-tree'),
Expand Down Expand Up @@ -325,12 +318,11 @@ const createMockBalance = (

const renderComponent = (groupId: AccountGroupId = GROUP_ID_MOCK) => {
const store = mockStore(createMockState());
return render(
<Provider store={store}>
<MultichainHoveredAddressRowsList groupId={groupId}>
<div data-testid="hover-trigger">Hover Me</div>
</MultichainHoveredAddressRowsList>
</Provider>,
return renderWithProvider(
<MultichainHoveredAddressRowsList groupId={groupId}>
<div data-testid="hover-trigger">Hover Me</div>
</MultichainHoveredAddressRowsList>,
store,
);
};

Expand Down Expand Up @@ -700,7 +692,7 @@ describe('MultichainHoveredAddressRowsList', () => {

fireEvent.click(viewAllButton);

expect(mockPush).toHaveBeenCalledWith(
expect(mockUseNavigate).toHaveBeenCalledWith(
`${MULTICHAIN_ACCOUNT_ADDRESS_LIST_PAGE_ROUTE}/${encodeURIComponent(GROUP_ID_MOCK)}`,
);
});
Expand Down Expand Up @@ -740,7 +732,7 @@ describe('MultichainHoveredAddressRowsList', () => {

fireEvent.click(viewAllButton);

expect(mockPush).toHaveBeenCalledWith(
expect(mockUseNavigate).toHaveBeenCalledWith(
`${MULTICHAIN_ACCOUNT_ADDRESS_LIST_PAGE_ROUTE}/${encodeURIComponent(SPECIAL_GROUP_ID)}`,
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
TextColor,
TextVariant,
} from '@metamask/design-system-react';
import { useHistory } from 'react-router-dom';
import { useNavigate } from 'react-router-dom-v5-compat';
import { BackgroundColor } from '../../../helpers/constants/design-system';
import { Popover, PopoverPosition } from '../../component-library';
import { useI18nContext } from '../../../hooks/useI18nContext';
Expand Down Expand Up @@ -77,7 +77,7 @@ export const MultichainHoveredAddressRowsList = ({
}: MultichainAddressRowsListProps) => {
const t = useI18nContext();
const [, handleCopy] = useCopyToClipboard();
const history = useHistory();
const navigate = useNavigate();
const [isHoverOpen, setIsHoverOpen] = useState(false);
const [referenceElement, setReferenceElement] = useState<HTMLElement | null>(
null,
Expand Down Expand Up @@ -264,11 +264,11 @@ export const MultichainHoveredAddressRowsList = ({
const handleViewAllClick = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
history.push(
navigate(
`${MULTICHAIN_ACCOUNT_ADDRESS_LIST_PAGE_ROUTE}/${encodeURIComponent(groupId)}`,
);
},
[groupId, history],
[groupId, navigate],
);

const renderedRows = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const MultichainSrpBackup: React.FC<MultichainSrpBackupProps> = ({
isOpen={srpQuizModalVisible}
onClose={handleQuizModalClose}
closeAfterCompleting
navigate={navigate}
/>
)}
</>
Expand Down
Loading
Loading