Skip to content

Commit 7f5abcc

Browse files
authored
Merge branch 'main' into sidepanel-icon
2 parents 5af1b52 + 9f83b08 commit 7f5abcc

File tree

10 files changed

+240
-124
lines changed

10 files changed

+240
-124
lines changed

app/_locales/en/messages.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/_locales/en_GB/messages.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/pages/confirmations/components/confirm/footer/footer.test.tsx

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from '../../../../../../test/data/confirmations/personal_sign';
2020
import { permitSignatureMsg } from '../../../../../../test/data/confirmations/typed_sign';
2121
import mockState from '../../../../../../test/data/mock-state.json';
22-
import { fireEvent, waitFor } from '../../../../../../test/jest';
22+
import { fireEvent } from '../../../../../../test/jest';
2323
import { renderWithConfirmContextProvider } from '../../../../../../test/lib/confirmations/render-helpers';
2424
import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts';
2525
import { Severity } from '../../../../../helpers/constants/design-system';
@@ -37,23 +37,9 @@ import Footer from './footer';
3737
jest.mock('../../../hooks/gas/useIsGaslessLoading');
3838
jest.mock('../../../hooks/alerts/transactions/useInsufficientBalanceAlerts');
3939
jest.mock('../../../hooks/gas/useIsGaslessSupported');
40-
41-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
42-
let mockStore: any = null;
43-
44-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
45-
const mockDispatch: any = jest.fn((action: unknown) => {
46-
if (typeof action === 'function') {
47-
// Thunk actions need both dispatch and getState
48-
const mockGetState = mockStore ? mockStore.getState : jest.fn(() => ({}));
49-
return action(mockDispatch, mockGetState);
50-
}
51-
return action;
52-
});
53-
5440
jest.mock('react-redux', () => ({
5541
...jest.requireActual('react-redux'),
56-
useDispatch: () => mockDispatch,
42+
useDispatch: () => jest.fn(),
5743
}));
5844
jest.mock('../../../hooks/useConfirmationNavigation', () => ({
5945
useConfirmationNavigation: jest.fn(() => ({
@@ -73,32 +59,13 @@ jest.mock(
7359
);
7460

7561
jest.mock('../../../hooks/useOriginThrottling');
76-
jest.mock('../../../hooks/useAddEthereumChain', () => ({
77-
useAddEthereumChain: jest.fn(() => ({
78-
onSubmit: jest.fn().mockResolvedValue(undefined),
79-
})),
80-
isAddEthereumChainType: jest.fn(
81-
(confirmation) => confirmation?.type === 'wallet_addEthereumChain',
82-
),
83-
}));
84-
jest.mock('../../../hooks/transactions/useTransactionConfirm', () => ({
85-
useTransactionConfirm: jest.fn(() => ({
86-
onTransactionConfirm: jest.fn().mockResolvedValue(undefined),
87-
})),
88-
}));
89-
jest.mock('../../../hooks/useConfirmSendNavigation', () => ({
90-
useConfirmSendNavigation: jest.fn(() => ({
91-
navigateBackIfSend: jest.fn(),
92-
})),
93-
}));
9462

9563
jest.mock('react-router-dom-v5-compat', () => ({
9664
useNavigate: jest.fn(),
9765
}));
9866

9967
const render = (args?: Record<string, unknown>) => {
10068
const store = configureStore(args ?? getMockPersonalSignConfirmState());
101-
mockStore = store;
10269

10370
return renderWithConfirmContextProvider(<Footer />, store);
10471
};
@@ -121,10 +88,6 @@ describe('ConfirmFooter', () => {
12188
const useConfirmationNavigationMock = jest.mocked(useConfirmationNavigation);
12289

12390
beforeEach(() => {
124-
jest.clearAllMocks();
125-
mockDispatch.mockClear();
126-
mockStore = null;
127-
12891
mockUseOriginThrottling.mockReturnValue({
12992
shouldThrottleOrigin: false,
13093
});
@@ -271,62 +234,50 @@ describe('ConfirmFooter', () => {
271234
});
272235
});
273236

274-
it('invoke required actions when cancel button is clicked', async () => {
237+
it('invoke required actions when cancel button is clicked', () => {
275238
const { getAllByRole } = render();
276239
const cancelButton = getAllByRole('button')[0];
277240
const rejectSpy = jest
278241
.spyOn(Actions, 'rejectPendingApproval')
279242
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31973
280243
// eslint-disable-next-line @typescript-eslint/no-explicit-any
281-
.mockImplementation(() => Promise.resolve() as any);
244+
.mockImplementation(() => ({}) as any);
282245
const updateCustomNonceSpy = jest
283246
.spyOn(Actions, 'updateCustomNonce')
284247
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31973
285248
// eslint-disable-next-line @typescript-eslint/no-explicit-any
286-
.mockReturnValue({} as any);
249+
.mockImplementation(() => ({}) as any);
287250
const setNextNonceSpy = jest
288251
.spyOn(Actions, 'setNextNonce')
289252
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31973
290253
// eslint-disable-next-line @typescript-eslint/no-explicit-any
291-
.mockReturnValue({} as any);
292-
254+
.mockImplementation(() => ({}) as any);
293255
fireEvent.click(cancelButton);
294-
295-
// Wait for async onCancel to complete
296-
await waitFor(() => {
297-
expect(rejectSpy).toHaveBeenCalled();
298-
});
299-
256+
expect(rejectSpy).toHaveBeenCalled();
300257
expect(updateCustomNonceSpy).toHaveBeenCalledWith('');
301258
expect(setNextNonceSpy).toHaveBeenCalledWith('');
302259
});
303260

304-
it('invoke required actions when submit button is clicked', async () => {
261+
it('invoke required actions when submit button is clicked', () => {
305262
const { getAllByRole } = render();
306263
const submitButton = getAllByRole('button')[1];
307264
const resolveSpy = jest
308265
.spyOn(Actions, 'resolvePendingApproval')
309266
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31973
310267
// eslint-disable-next-line @typescript-eslint/no-explicit-any
311-
.mockImplementation(() => Promise.resolve() as any);
268+
.mockImplementation(() => ({}) as any);
312269
const updateCustomNonceSpy = jest
313270
.spyOn(Actions, 'updateCustomNonce')
314271
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31973
315272
// eslint-disable-next-line @typescript-eslint/no-explicit-any
316-
.mockReturnValue({} as any);
273+
.mockImplementation(() => ({}) as any);
317274
const setNextNonceSpy = jest
318275
.spyOn(Actions, 'setNextNonce')
319276
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31973
320277
// eslint-disable-next-line @typescript-eslint/no-explicit-any
321-
.mockReturnValue({} as any);
322-
278+
.mockImplementation(() => ({}) as any);
323279
fireEvent.click(submitButton);
324-
325-
// Wait for async onSubmit to complete
326-
await waitFor(() => {
327-
expect(resolveSpy).toHaveBeenCalled();
328-
});
329-
280+
expect(resolveSpy).toHaveBeenCalled();
330281
expect(updateCustomNonceSpy).toHaveBeenCalledWith('');
331282
expect(setNextNonceSpy).toHaveBeenCalledWith('');
332283
});
@@ -527,7 +478,7 @@ describe('ConfirmFooter', () => {
527478
// @ts-expect-error This is missing from the Mocha type definitions
528479
it.each(['Confirm', 'Cancel'])(
529480
'on %s button click',
530-
async (buttonText: string) => {
481+
(buttonText: string) => {
531482
const navigateNextMock = jest.fn();
532483
useConfirmationNavigationMock.mockReturnValue({
533484
navigateNext: navigateNextMock,
@@ -537,21 +488,17 @@ describe('ConfirmFooter', () => {
537488
const mockStateWithContractInteractionConfirmation =
538489
getMockContractInteractionConfirmState();
539490

540-
// Get the actual transaction from the transactions array
541-
const contractInteractionConfirmation =
542-
mockStateWithContractInteractionConfirmation.metamask
543-
.transactions[0];
544-
545491
mockStateWithContractInteractionConfirmation.metamask.pendingApprovals =
546492
{
493+
[addEthereumChainApproval.id]: addEthereumChainApproval,
547494
...mockStateWithContractInteractionConfirmation.metamask
548495
.pendingApprovals,
549-
[addEthereumChainApproval.id]: addEthereumChainApproval,
550496
};
551497
mockStateWithContractInteractionConfirmation.metamask.pendingApprovalCount = 2;
552498

499+
// Current confirmation is add ethereum chain
553500
jest.spyOn(confirmContext, 'useConfirmContext').mockReturnValue({
554-
currentConfirmation: contractInteractionConfirmation,
501+
currentConfirmation: addEthereumChainApproval,
555502
isScrollToBottomCompleted: true,
556503
setIsScrollToBottomCompleted: () => undefined,
557504
});
@@ -562,13 +509,10 @@ describe('ConfirmFooter', () => {
562509
const button = getByText(buttonText);
563510
fireEvent.click(button);
564511

565-
// Wait for async operations to complete
566-
await waitFor(() => {
567-
expect(navigateNextMock).toHaveBeenCalledTimes(1);
568-
});
569-
512+
// It will navigate to transaction confirmation
513+
expect(navigateNextMock).toHaveBeenCalledTimes(1);
570514
expect(navigateNextMock).toHaveBeenCalledWith(
571-
contractInteractionConfirmation.id,
515+
addEthereumChainApproval.id,
572516
);
573517
},
574518
);

ui/pages/confirmations/components/confirm/footer/footer.tsx

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
} from '@metamask/transaction-controller';
55
import React, { useCallback, useState } from 'react';
66
import { useDispatch, useSelector } from 'react-redux';
7-
import { useHistory } from 'react-router-dom';
87
import { MetaMetricsEventLocation } from '../../../../../../shared/constants/metametrics';
98
import { isCorrectDeveloperTransactionType } from '../../../../../../shared/lib/confirmation.utils';
109
import { ConfirmAlertModal } from '../../../../../components/app/alert-system/confirm-alert-modal';
@@ -22,7 +21,6 @@ import {
2221
FlexDirection,
2322
Severity,
2423
} from '../../../../../helpers/constants/design-system';
25-
import { DEFAULT_ROUTE } from '../../../../../helpers/constants/routes';
2624
import useAlerts from '../../../../../hooks/useAlerts';
2725
import { useI18nContext } from '../../../../../hooks/useI18nContext';
2826
import { doesAddressRequireLedgerHidConnection } from '../../../../../selectors';
@@ -194,7 +192,6 @@ const CancelButton = ({
194192

195193
const Footer = () => {
196194
const dispatch = useDispatch();
197-
const history = useHistory();
198195
const { onTransactionConfirm } = useTransactionConfirm();
199196
const { navigateNext } = useConfirmationNavigation();
200197
const { onSubmit: onAddEthereumChain } = useAddEthereumChain();
@@ -229,56 +226,41 @@ const Footer = () => {
229226
hardwareWalletRequiresConnection ||
230227
isGaslessLoading;
231228

232-
const onSubmit = useCallback(async () => {
229+
const onSubmit = useCallback(() => {
233230
if (!currentConfirmation) {
234231
return;
235232
}
236233

237234
if (isAddEthereumChain) {
238-
await onAddEthereumChain();
239-
history.push(DEFAULT_ROUTE);
235+
onAddEthereumChain();
240236
} else if (isTransactionConfirmation) {
241-
await onTransactionConfirm();
242-
navigateNext(currentConfirmation.id);
237+
onTransactionConfirm();
243238
} else {
244-
await dispatch(resolvePendingApproval(currentConfirmation.id, undefined));
245-
navigateNext(currentConfirmation.id);
239+
dispatch(resolvePendingApproval(currentConfirmation.id, undefined));
246240
}
247241

242+
navigateNext(currentConfirmation.id);
248243
resetTransactionState();
249244
}, [
250245
currentConfirmation,
251246
dispatch,
252-
history,
253247
isTransactionConfirmation,
254-
isAddEthereumChain,
255248
navigateNext,
256249
onTransactionConfirm,
257250
resetTransactionState,
251+
isAddEthereumChain,
258252
onAddEthereumChain,
259253
]);
260254

261-
const handleFooterCancel = useCallback(async () => {
255+
const handleFooterCancel = useCallback(() => {
262256
if (shouldThrottleOrigin) {
263257
setShowOriginThrottleModal(true);
264258
return;
265259
}
260+
onCancel({ location: MetaMetricsEventLocation.Confirmation });
266261

267-
await onCancel({ location: MetaMetricsEventLocation.Confirmation });
268-
269-
if (isAddEthereumChain) {
270-
history.push(DEFAULT_ROUTE);
271-
} else {
272-
navigateNext(currentConfirmation.id);
273-
}
274-
}, [
275-
navigateNext,
276-
onCancel,
277-
shouldThrottleOrigin,
278-
currentConfirmation,
279-
isAddEthereumChain,
280-
history,
281-
]);
262+
navigateNext(currentConfirmation.id);
263+
}, [navigateNext, onCancel, shouldThrottleOrigin, currentConfirmation]);
282264

283265
const { isEnabled, isPaused } = useEnableShieldCoverageChecks();
284266
const isShowShieldFooterCoverageIndicator = isEnabled || isPaused;

ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import {
3737
} from '../../../store/actions';
3838
import ConfirmDecryptMessage from '../../confirm-decrypt-message';
3939
import ConfirmEncryptionPublicKey from '../../confirm-encryption-public-key';
40+
import { useSidePanelEnabled } from '../../../hooks/useSidePanelEnabled';
41+
import { getUnapprovedConfirmations } from '../../../selectors/selectors';
4042
import ConfirmTransactionSwitch from '../confirm-transaction-switch';
4143
import Confirm from '../confirm/confirm';
4244
import useCurrentConfirmation from '../hooks/useCurrentConfirmation';
@@ -51,6 +53,9 @@ const ConfirmTransaction = () => {
5153
const dispatch = useDispatch();
5254
const history = useHistory();
5355
const { id: paramsTransactionId } = useParams();
56+
const isSidePanelEnabled = useSidePanelEnabled();
57+
const hasPendingApprovals =
58+
useSelector(getUnapprovedConfirmations).length > 0;
5459

5560
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage);
5661
const sendTo = useSelector(getSendTo);
@@ -165,6 +170,8 @@ const ConfirmTransaction = () => {
165170
paramsTransactionId !== transactionId
166171
) {
167172
history.replace(mostRecentOverviewPage);
173+
} else if (isSidePanelEnabled && !hasPendingApprovals) {
174+
history.replace(DEFAULT_ROUTE);
168175
}
169176
}, [
170177
dispatch,
@@ -174,6 +181,9 @@ const ConfirmTransaction = () => {
174181
prevParamsTransactionId,
175182
prevTransactionId,
176183
totalUnapproved,
184+
hasPendingApprovals,
185+
isSidePanelEnabled,
186+
isValidTransactionId,
177187
transaction,
178188
transactionId,
179189
use4ByteResolution,

0 commit comments

Comments
 (0)