diff --git a/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx b/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx index e217c36f813..b22b6c8d366 100644 --- a/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx +++ b/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx @@ -1,6 +1,5 @@ import React from 'react'; import useApprovalRequest from '../../hooks/useApprovalRequest'; -import { shallow } from 'enzyme'; import { ApprovalTypes } from '../../../core/RPCMethods/RPCMethodMiddleware'; import { ApprovalRequest } from '@metamask/approval-controller'; import PermissionApproval from './PermissionApproval'; @@ -9,6 +8,7 @@ import AnalyticsV2 from '../../../util/analyticsV2'; import { useSelector } from 'react-redux'; import { MetaMetricsEvents } from '../../../core/Analytics'; import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { render } from '@testing-library/react-native'; jest.mock('../../hooks/useApprovalRequest'); jest.mock('../../../util/analyticsV2'); @@ -63,7 +63,7 @@ describe('PermissionApproval', () => { jest.resetAllMocks(); }); - it('navigates', () => { + it('navigates', async () => { const navigationMock = { navigate: jest.fn(), }; @@ -75,7 +75,7 @@ describe('PermissionApproval', () => { mockCreateAccountConnectNavDetails(NAV_DETAILS_MOCK); - shallow(); + render(); expect(navigationMock.navigate).toHaveBeenCalledTimes(1); expect(navigationMock.navigate).toHaveBeenCalledWith(NAV_DETAILS_MOCK[0]); @@ -87,7 +87,7 @@ describe('PermissionApproval', () => { }); }); - it('generates analytics', () => { + it('generates analytics', async () => { const navigationMock = { navigate: jest.fn(), }; @@ -114,7 +114,7 @@ describe('PermissionApproval', () => { }, }); - shallow(); + render(); expect(AnalyticsV2.trackEvent).toHaveBeenCalledTimes(1); expect(AnalyticsV2.trackEvent).toHaveBeenCalledWith( @@ -126,19 +126,19 @@ describe('PermissionApproval', () => { ); }); - it('returns null if no approval request', () => { + it('does not navigate if no approval request', async () => { const navigationMock = { navigate: jest.fn(), }; mockApprovalRequest(undefined); - expect(shallow()).toEqual( - {}, - ); + render(); + + expect(navigationMock.navigate).toHaveBeenCalledTimes(0); }); - it('returns null if incorrect approval request type', () => { + it('does not navigate if incorrect approval request type', async () => { const navigationMock = { navigate: jest.fn(), }; @@ -148,12 +148,12 @@ describe('PermissionApproval', () => { requestData: HOST_INFO_MOCK, } as any); - expect(shallow()).toEqual( - {}, - ); + render(); + + expect(navigationMock.navigate).toHaveBeenCalledTimes(0); }); - it('returns null if no eth_accounts permission', () => { + it('does not navigate if no eth_accounts permission', async () => { const navigationMock = { navigate: jest.fn(), }; @@ -163,8 +163,64 @@ describe('PermissionApproval', () => { requestData: { ...HOST_INFO_MOCK, permissions: { eth_accounts: false } }, } as any); - expect(shallow()).toEqual( - {}, + render(); + + expect(navigationMock.navigate).toHaveBeenCalledTimes(0); + }); + + it('does not navigate if still processing', async () => { + const navigationMock = { + navigate: jest.fn(), + }; + + mockCreateAccountConnectNavDetails(NAV_DETAILS_MOCK); + + mockApprovalRequest({ + type: ApprovalTypes.REQUEST_PERMISSIONS, + requestData: HOST_INFO_MOCK, + } as any); + + const { rerender } = render( + , + ); + + mockApprovalRequest({ + type: ApprovalTypes.REQUEST_PERMISSIONS, + requestData: HOST_INFO_MOCK, + } as any); + + rerender(); + + expect(navigationMock.navigate).toHaveBeenCalledTimes(1); + }); + + it('navigates if previous processing finished', async () => { + const navigationMock = { + navigate: jest.fn(), + }; + + mockCreateAccountConnectNavDetails(NAV_DETAILS_MOCK); + + mockApprovalRequest({ + type: ApprovalTypes.REQUEST_PERMISSIONS, + requestData: HOST_INFO_MOCK, + } as any); + + const { rerender } = render( + , ); + + mockApprovalRequest(undefined); + + rerender(); + + mockApprovalRequest({ + type: ApprovalTypes.REQUEST_PERMISSIONS, + requestData: HOST_INFO_MOCK, + } as any); + + rerender(); + + expect(navigationMock.navigate).toHaveBeenCalledTimes(2); }); }); diff --git a/app/components/Approvals/PermissionApproval/PermissionApproval.tsx b/app/components/Approvals/PermissionApproval/PermissionApproval.tsx index 87cf447cb87..f70db700caa 100644 --- a/app/components/Approvals/PermissionApproval/PermissionApproval.tsx +++ b/app/components/Approvals/PermissionApproval/PermissionApproval.tsx @@ -1,5 +1,5 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars -import React from 'react'; +import { useEffect, useRef } from 'react'; import useApprovalRequest from '../../hooks/useApprovalRequest'; import { ApprovalTypes } from '../../../core/RPCMethods/RPCMethodMiddleware'; import AnalyticsV2 from '../../../util/analyticsV2'; @@ -15,28 +15,38 @@ export interface PermissionApprovalProps { const PermissionApproval = (props: PermissionApprovalProps) => { const { approvalRequest } = useApprovalRequest(); const totalAccounts = useSelector(selectAccountsLength); + const isProcessing = useRef(false); - if (approvalRequest?.type !== ApprovalTypes.REQUEST_PERMISSIONS) return null; + useEffect(() => { + if (approvalRequest?.type !== ApprovalTypes.REQUEST_PERMISSIONS) { + isProcessing.current = false; + return; + } - const requestData = approvalRequest?.requestData; + const requestData = approvalRequest?.requestData; - if (!requestData?.permissions?.eth_accounts) return null; + if (!requestData?.permissions?.eth_accounts) return; - const { - metadata: { id }, - } = requestData; + const { + metadata: { id }, + } = requestData; - AnalyticsV2.trackEvent(MetaMetricsEvents.CONNECT_REQUEST_STARTED, { - number_of_accounts: totalAccounts, - source: 'PERMISSION SYSTEM', - }); + if (isProcessing.current) return; - props.navigation.navigate( - ...createAccountConnectNavDetails({ - hostInfo: requestData, - permissionRequestId: id, - }), - ); + isProcessing.current = true; + + AnalyticsV2.trackEvent(MetaMetricsEvents.CONNECT_REQUEST_STARTED, { + number_of_accounts: totalAccounts, + source: 'PERMISSION SYSTEM', + }); + + props.navigation.navigate( + ...createAccountConnectNavDetails({ + hostInfo: requestData, + permissionRequestId: id, + }), + ); + }, [approvalRequest, totalAccounts, props.navigation]); return null; };