diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index e43b73781f8be..28738494b37b5 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -219,6 +219,10 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers if (hasApprovers) { const ownerEmail = ownerDetails.login; for (const login of selectedEmployees) { + if (!isApprover(policy, login)) { + continue; + } + const accountID = policyMemberEmailsToAccountIDs[login]; const removedApprover = personalDetails?.[accountID]; if (!removedApprover?.login || !ownerEmail) { @@ -241,6 +245,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers } setRemoveMembersConfirmModalVisible(false); + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { setSelectedEmployees([]); diff --git a/tests/ui/WorkspaceMembersTest.tsx b/tests/ui/WorkspaceMembersTest.tsx index f78e192b27983..df6f62d35f0d4 100644 --- a/tests/ui/WorkspaceMembersTest.tsx +++ b/tests/ui/WorkspaceMembersTest.tsx @@ -9,7 +9,9 @@ import OnyxListItemProvider from '@components/OnyxListItemProvider'; import {CurrentReportIDContextProvider} from '@hooks/useCurrentReportID'; import * as useResponsiveLayoutModule from '@hooks/useResponsiveLayout'; import type ResponsiveLayoutResult from '@hooks/useResponsiveLayout/types'; +import {removeApprovalWorkflow} from '@libs/actions/Workflow'; import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator'; +import {updateWorkflowDataOnApproverRemoval} from '@libs/WorkflowUtils'; import type {WorkspaceSplitNavigatorParamList} from '@navigation/types'; import WorkspaceMembersPage from '@pages/workspace/WorkspaceMembersPage'; import CONST from '@src/CONST'; @@ -24,6 +26,26 @@ jest.unmock('react-native-worklets'); jest.mock('@src/components/ConfirmedRoute.tsx'); +jest.mock('@libs/WorkflowUtils', () => { + // eslint-disable-next-line + const actual = jest.requireActual('@libs/WorkflowUtils'); + // eslint-disable-next-line + return { + ...actual, + updateWorkflowDataOnApproverRemoval: jest.fn(() => [{members: [], approvers: [], isDefault: false, removeApprovalWorkflow: true}]), + }; +}); + +jest.mock('@libs/actions/Workflow', () => { + // eslint-disable-next-line + const actual = jest.requireActual('@libs/actions/Workflow'); + // eslint-disable-next-line + return { + ...actual, + removeApprovalWorkflow: jest.fn(), + }; +}); + TestHelper.setupGlobalFetchMock(); const Stack = createPlatformStackNavigator(); @@ -66,6 +88,7 @@ describe('WorkspaceMembers', () => { owner: ownerEmail, ownerAccountID, type: CONST.POLICY.TYPE.CORPORATE, + approver: adminEmail, employeeList: { [ownerEmail]: {email: ownerEmail, role: CONST.POLICY.ROLE.ADMIN}, [adminEmail]: {email: adminEmail, role: CONST.POLICY.ROLE.ADMIN}, @@ -296,4 +319,51 @@ describe('WorkspaceMembers', () => { await waitForBatchedUpdatesWithAct(); }); }); + + describe('Removing members who are approvers and non-approvers', () => { + it('should call workflow actions once when removing multiple members including an approver', async () => { + const {unmount} = renderPage(SCREENS.WORKSPACE.MEMBERS, {policyID: policy.id}); + await waitForBatchedUpdatesWithAct(); + + await screen.findByText(ADMIN_OPTION); + + // Select all + fireEvent.press(screen.getByTestId('selection-list-select-all-checkbox')); + + // Open dropdown + fireEvent.press(await screen.findByTestId('WorkspaceMembersPage-header-dropdown-menu-button')); + await waitForBatchedUpdatesWithAct(); + + // Click "Remove members" + const removeText = TestHelper.translateLocal('workspace.people.removeMembersTitle', {count: 3}); + const removeMenuItem = screen.getByText(removeText); + fireEvent.press(removeMenuItem, { + nativeEvent: {}, + type: 'press', + target: removeMenuItem, + currentTarget: removeMenuItem, + }); + + await waitForBatchedUpdatesWithAct(); + + // Wait until confirm modal confirm button exists + const confirmText = TestHelper.translateLocal('common.remove'); + + await waitFor(() => { + expect(screen.getByLabelText(confirmText)).toBeOnTheScreen(); + }); + + // Press confirm button + fireEvent.press(screen.getByLabelText(confirmText)); + + await waitForBatchedUpdatesWithAct(); + + // Verify workflow actions are only called once when an approver is removed + expect(updateWorkflowDataOnApproverRemoval).toHaveBeenCalledTimes(1); + expect(removeApprovalWorkflow).toHaveBeenCalledTimes(1); + + unmount(); + await waitForBatchedUpdatesWithAct(); + }); + }); });