Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ import {
isIntegrationMessageAction,
isMoneyRequestAction,
isMovedAction,
isMovedTransactionAction,
isOlderReportAction,
isPendingRemove,
isReopenedAction,
Expand Down Expand Up @@ -11686,6 +11687,7 @@ function getNonHeldAndFullAmount(
* - The action is a split expense action
* - The action is deleted and is not threaded
* - The report is archived and the action is not threaded
* - The action is a moved system message and is not threaded (moved actions can't be threaded server-side, so offering "Reply in thread" leads to a failed thread-creation call)
* - The action is a whisper action and it's neither a report preview nor IOU action
* - The action is the thread's first chat
*/
Expand All @@ -11696,12 +11698,14 @@ function shouldDisableThread(reportAction: OnyxInputOrEntry<ReportAction>, isThr
const isIOUAction = isMoneyRequestAction(reportAction);
const isWhisperActionLocal = isWhisperAction(reportAction) || isActionableTrackExpense(reportAction);
const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED);
const isMovedSystemMessage = isMovedAction(reportAction) || isMovedTransactionAction(reportAction);
const isActionDisabled = CONST.REPORT.ACTIONS.THREAD_DISABLED.some((action: string) => action === reportAction?.actionName);
return (
isActionDisabled ||
isSplitBillAction ||
(isDeletedActionLocal && !reportAction?.childVisibleActionCount) ||
(isReportArchived && !reportAction?.childVisibleActionCount) ||
(isMovedSystemMessage && !reportAction?.childVisibleActionCount) ||
(isWhisperActionLocal && !isReportPreviewActionLocal && !isIOUAction) ||
isThreadReportParentAction ||
isDynamicWorkflowRoutedAction
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/ReportUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5325,6 +5325,36 @@ describe('ReportUtils', () => {
expect(isThreadDisabled).toBeTruthy();
});
});

describe('moved system messages', () => {
it.each([CONST.REPORT.ACTIONS.TYPE.MOVED, CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION])('should be disabled for a %s action with no child visible action count', (actionName) => {
// Given a moved system message that has never been threaded
const reportAction = createMock<ReportAction>({
actionName,
childVisibleActionCount: 0,
});

// When it's checked to see if the thread should be disabled
const isThreadDisabled = shouldDisableThread(reportAction, false);

// Then the thread should be disabled so the doomed thread-creation call is never made
expect(isThreadDisabled).toBeTruthy();
});

it.each([CONST.REPORT.ACTIONS.TYPE.MOVED, CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION])('should be enabled for a %s action that has already been threaded', (actionName) => {
// Given a moved system message that already has a legitimately threaded child
const reportAction = createMock<ReportAction>({
actionName,
childVisibleActionCount: 1,
});

// When it's checked to see if the thread should be disabled
const isThreadDisabled = shouldDisableThread(reportAction, false);

// Then the thread should stay enabled so the existing thread remains reachable
expect(isThreadDisabled).toBeFalsy();
});
});
});

describe('isChatUsedForOnboarding', () => {
Expand Down
Loading