diff --git a/src/components/ChronosTimerHeaderButton.tsx b/src/components/ChronosTimerHeaderButton.tsx index 69f5c9ef9362..9c25a57e1ffe 100644 --- a/src/components/ChronosTimerHeaderButton.tsx +++ b/src/components/ChronosTimerHeaderButton.tsx @@ -44,6 +44,7 @@ function ChronosTimerHeaderButton({report}: ChronosTimerHeaderButtonProps) { const isReportArchived = useReportIsArchived(report?.reportID); const canPerformWriteAction = canUserPerformWriteAction(report, isReportArchived); const [visibleReportActionsData] = useOnyx(ONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const {accountID: currentUserAccountID, timezone: timezoneParam} = useCurrentUserPersonalDetails(); const reportActionsOnyxKey = `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}` as OnyxKey; @@ -92,6 +93,7 @@ function ChronosTimerHeaderButton({report}: ChronosTimerHeaderButtonProps) { shouldPlaySound: false, isInSidePanel, delegateAccountID, + conciergeReportID, }); } diff --git a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx index 8a7afae68411..62c3f7cf9d47 100644 --- a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx +++ b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx @@ -258,6 +258,7 @@ function MoneyRequestReceiptView({ currentUserAccountID, timezone: currentUserTimezone, delegateAccountID, + conciergeReportID, }); }; diff --git a/src/components/Search/SearchRouter/useAskConcierge.tsx b/src/components/Search/SearchRouter/useAskConcierge.tsx index 14e443127cc7..e43f6167808a 100644 --- a/src/components/Search/SearchRouter/useAskConcierge.tsx +++ b/src/components/Search/SearchRouter/useAskConcierge.tsx @@ -43,6 +43,7 @@ function useAskConcierge() { shouldPlaySound: true, isInSidePanel, delegateAccountID, + conciergeReportID, }); }; diff --git a/src/libs/actions/Report/SuggestedFollowup.ts b/src/libs/actions/Report/SuggestedFollowup.ts index f59e4c6a9c97..0064b5bdb05b 100644 --- a/src/libs/actions/Report/SuggestedFollowup.ts +++ b/src/libs/actions/Report/SuggestedFollowup.ts @@ -29,6 +29,7 @@ const CONCIERGE_RESPONSE_DELAY_MS = 4000; * @param reportAction - The report action containing the followup-list * @param selectedFollowup - The followup object containing the question text and optional pre-generated response * @param timezoneParam - The user's timezone + * @param conciergeReportID - The Concierge report ID, used to detect whether the comment is posted in the Concierge chat * @param ancestors - Array of ancestor reports for proper threading */ function resolveSuggestedFollowup( @@ -40,6 +41,7 @@ function resolveSuggestedFollowup( currentUserAccountID: number, currentUserEmail: string | undefined, delegateAccountID: number | undefined, + conciergeReportID: string | undefined, ancestors: Ancestor[] = [], ) { const reportID = report?.reportID; @@ -69,7 +71,16 @@ function resolveSuggestedFollowup( }); if (!selectedFollowup.response) { - addComment({report, notifyReportID: notifyReportID ?? reportID, ancestors, text: selectedFollowup.text, timezoneParam, currentUserAccountID, delegateAccountID}); + addComment({ + report, + notifyReportID: notifyReportID ?? reportID, + ancestors, + text: selectedFollowup.text, + timezoneParam, + currentUserAccountID, + delegateAccountID, + conciergeReportID, + }); return; } @@ -91,6 +102,7 @@ function resolveSuggestedFollowup( pregeneratedResponse: selectedFollowup.response, }, delegateAccountID, + conciergeReportID, }); // Use the full delay as createdOffset so the Concierge response timestamp is @@ -177,7 +189,10 @@ function applyPendingConciergeAction(reportID: string | undefined, reportAction: { onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.CONCIERGE_PENDING_FOLLOWUP_LIST}${reportID}`, - value: {reportActionID: reportAction.reportActionID, createdAt: Date.now()}, + value: { + reportActionID: reportAction.reportActionID, + createdAt: Date.now(), + }, }, ]); } diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index dfaee0078f28..348784f74ef6 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -381,6 +381,7 @@ type AddCommentParams = { pregeneratedResponseParams?: PregeneratedResponseParams; reportActionID?: string; delegateAccountID: number | undefined; + conciergeReportID: string | undefined; }; type AddActionsParams = { @@ -396,6 +397,7 @@ type AddActionsParams = { pregeneratedResponseParams?: PregeneratedResponseParams; reportActionID?: string; delegateAccountID: number | undefined; + conciergeReportID: string | undefined; }; type AddAttachmentWithCommentParams = { @@ -410,6 +412,7 @@ type AddAttachmentWithCommentParams = { isInSidePanel?: boolean; delegateAccountID: number | undefined; sidePanelContext?: SidePanelContext; + conciergeReportID: string | undefined; }; const addNewMessageWithText = new Set([WRITE_COMMANDS.ADD_COMMENT, WRITE_COMMANDS.ADD_TEXT_AND_ATTACHMENT]); @@ -839,6 +842,7 @@ function addActions({ pregeneratedResponseParams, reportActionID, delegateAccountID, + conciergeReportID, }: AddActionsParams) { if (!report?.reportID) { return; @@ -962,7 +966,7 @@ function addActions({ idempotencyKey: Str.guid(), }; - const isConciergeChat = isConciergeChatReport(reportForAction); + const isConciergeChat = isConciergeChatReport(reportForAction, conciergeReportID); if (reportIDDeeplinkedFromOldDot === reportID && isConciergeChat) { parameters.isOldDotConciergeChat = true; } @@ -1108,6 +1112,7 @@ function addAttachmentWithComment({ isInSidePanel = false, delegateAccountID, sidePanelContext, + conciergeReportID, }: AddAttachmentWithCommentParams) { if (!report?.reportID) { return; @@ -1122,13 +1127,25 @@ function addAttachmentWithComment({ // Single attachment if (!Array.isArray(attachments)) { - addActions({report, notifyReportID, ancestors, timezoneParam: timezone, currentUserAccountID, text, file: attachments, isInSidePanel, delegateAccountID, sidePanelContext}); + addActions({ + report, + notifyReportID, + ancestors, + timezoneParam: timezone, + currentUserAccountID, + text, + file: attachments, + isInSidePanel, + delegateAccountID, + sidePanelContext, + conciergeReportID, + }); handlePlaySound(); return; } // Multiple attachments - first: combine text + first attachment as a single action - addActions({report, notifyReportID, ancestors, timezoneParam: timezone, currentUserAccountID, text, file: attachments?.at(0), isInSidePanel, delegateAccountID}); + addActions({report, notifyReportID, ancestors, timezoneParam: timezone, currentUserAccountID, text, file: attachments?.at(0), isInSidePanel, delegateAccountID, conciergeReportID}); // Remaining: attachment-only actions (no text duplication) for (let i = 1; i < attachments?.length; i += 1) { @@ -1143,6 +1160,7 @@ function addAttachmentWithComment({ isInSidePanel, delegateAccountID, sidePanelContext, + conciergeReportID, }); } @@ -1164,6 +1182,7 @@ function addComment({ pregeneratedResponseParams, reportActionID, delegateAccountID, + conciergeReportID, }: AddCommentParams) { if (shouldPlaySound) { playSound(SOUNDS.DONE); @@ -1180,6 +1199,7 @@ function addComment({ reportActionID, delegateAccountID, sidePanelContext, + conciergeReportID, }); } @@ -2617,6 +2637,8 @@ function explain( currentUserAccountID, shouldPlaySound: true, delegateAccountID, + // Safe: the explanation posts to a thread, never the Concierge chat. Thread it if #66411 removes the fallback. + conciergeReportID: undefined, }); }); } @@ -5085,6 +5107,8 @@ function inviteToRoomAction( currentUserAccountID, shouldPlaySound: false, delegateAccountID, + // Safe: this posts to the room, never the Concierge chat. Thread it if #66411 removes the fallback. + conciergeReportID: undefined, }); } @@ -7840,7 +7864,8 @@ function resolveConciergeOptions( } const reportID = report.reportID; - addComment({report, notifyReportID: notifyReportID ?? reportID, ancestors, text: selectedValue, timezoneParam, currentUserAccountID, delegateAccountID}); + // Must thread before #66411 removes the fallback: this report CAN be the Concierge chat, so undefined would drop Concierge params. + addComment({report, notifyReportID: notifyReportID ?? reportID, ancestors, text: selectedValue, timezoneParam, currentUserAccountID, delegateAccountID, conciergeReportID: undefined}); Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { [reportActionID]: { diff --git a/src/pages/ChronosScheduleOOOPage.tsx b/src/pages/ChronosScheduleOOOPage.tsx index ad1ac9f5b575..e6a82ac0bae2 100644 --- a/src/pages/ChronosScheduleOOOPage.tsx +++ b/src/pages/ChronosScheduleOOOPage.tsx @@ -47,6 +47,7 @@ function ChronosScheduleOOOPage({route}: ChronosScheduleOOOPageProps) { const delegateAccountID = useDelegateAccountID(); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const [isDurationUnitModalVisible, setIsDurationUnitModalVisible] = useState(false); const [selectedDurationUnit, setSelectedDurationUnit] = useState(CONST.CHRONOS.OOO_DURATION_UNITS.DAY); const ancestors = useAncestors(report); @@ -115,6 +116,7 @@ function ChronosScheduleOOOPage({route}: ChronosScheduleOOOPageProps) { shouldPlaySound: false, isInSidePanel, delegateAccountID, + conciergeReportID, }); Navigation.goBack(); diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 9671debd7c45..63353b4106f4 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -64,6 +64,7 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { const [validatedFile] = useOnyx(ONYXKEYS.VALIDATED_FILE_OBJECT); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const [betas] = useOnyx(ONYXKEYS.BETAS); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const delegateAccountID = useDelegateAccountID(); const reportAttributesDerived = useReportAttributes(); @@ -138,6 +139,7 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { timezoneParam: personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, currentUserAccountID: personalDetail.accountID, delegateAccountID, + conciergeReportID, }); const routeToNavigate = ROUTES.REPORT_WITH_ID.getRoute(reportOrAccountID); Navigation.revealRouteBeforeDismissingModal(routeToNavigate); @@ -173,6 +175,7 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { text: message, timezone: personalDetail.timezone, delegateAccountID, + conciergeReportID, }); } diff --git a/src/pages/Travel/DynamicTravelTerms.tsx b/src/pages/Travel/DynamicTravelTerms.tsx index 76dc76f979c8..622513cc5eee 100644 --- a/src/pages/Travel/DynamicTravelTerms.tsx +++ b/src/pages/Travel/DynamicTravelTerms.tsx @@ -83,6 +83,7 @@ function DynamicTravelTerms({route}: TravelTermsPageProps) { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID, delegateAccountID, + conciergeReportID, }); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(conciergeReportID)); }; diff --git a/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts b/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts index c2e9521f2ec7..7c5fae40a525 100644 --- a/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts +++ b/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts @@ -40,6 +40,7 @@ function useComposerSubmit(reportID: string) { const isInSidePanel = useIsInSidePanel(); const sidePanelContext = useSidePanelContext(reportID); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`); const delegateAccountID = useDelegateAccountID(); const {kickoffWaitingIndicator} = useAgentZeroStatusActions(); @@ -89,6 +90,7 @@ function useComposerSubmit(reportID: string) { isInSidePanel, delegateAccountID, sidePanelContext, + conciergeReportID, }); attachmentFileRef.current = null; return; @@ -172,6 +174,7 @@ function useComposerSubmit(reportID: string) { sidePanelContext, reportActionID: optimisticReportActionID, delegateAccountID, + conciergeReportID, }); }; diff --git a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx index b8d8aeedf6d2..5e28dc9e9ee8 100644 --- a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx +++ b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx @@ -57,7 +57,9 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo const {isRestrictedToPreferredPolicy, preferredPolicyID} = usePreferredPolicy(); const activePolicy = useActivePolicy(); - const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); + const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, { + selector: validTransactionDraftIDsSelector, + }); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); @@ -68,6 +70,7 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo const firstPolicyID = filteredPoliciesInfo?.firstPolicyID; const trackExpenseTransactionID = isActionableTrackExpense(action) ? getOriginalMessage(action)?.transactionID : undefined; const [trackExpenseTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(trackExpenseTransactionID)}`); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const delegateAccountID = useDelegateAccountID(); const actionableItemButtons = ((): ActionableItem[] => { @@ -163,6 +166,7 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo personalDetail.accountID, personalDetail.email, delegateAccountID, + conciergeReportID, ); }, })); @@ -202,7 +206,12 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo }); }, }); - const options = [prepareTrackExpenseButton('submit', {isRestrictedToPreferredPolicy, preferredPolicyID})]; + const options = [ + prepareTrackExpenseButton('submit', { + isRestrictedToPreferredPolicy, + preferredPolicyID, + }), + ]; if (Permissions.canUseTrackFlows()) { options.push(prepareTrackExpenseButton('categorize'), prepareTrackExpenseButton('share')); diff --git a/tests/actions/AttachmentTest.ts b/tests/actions/AttachmentTest.ts index 0f13417f98df..6839b01cb876 100644 --- a/tests/actions/AttachmentTest.ts +++ b/tests/actions/AttachmentTest.ts @@ -74,7 +74,15 @@ describe('AttachmentStorage', () => { }; // Then upload the attachment - addAttachmentWithComment({report: {reportID}, notifyReportID: reportID, ancestors: [], attachments: fileData, currentUserAccountID: 1, delegateAccountID: undefined}); + addAttachmentWithComment({ + report: {reportID}, + notifyReportID: reportID, + ancestors: [], + attachments: fileData, + currentUserAccountID: 1, + delegateAccountID: undefined, + conciergeReportID: undefined, + }); await waitForBatchedUpdates(); @@ -114,6 +122,7 @@ describe('AttachmentStorage', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -170,6 +179,7 @@ describe('AttachmentStorage', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -234,7 +244,15 @@ describe('AttachmentStorage', () => { await waitForBatchedUpdates(); // Then upload the attachment - addAttachmentWithComment({report: {reportID}, notifyReportID: reportID, ancestors: [], attachments: fileData, currentUserAccountID: 1, delegateAccountID: undefined}); + addAttachmentWithComment({ + report: {reportID}, + notifyReportID: reportID, + ancestors: [], + attachments: fileData, + currentUserAccountID: 1, + delegateAccountID: undefined, + conciergeReportID: undefined, + }); await waitForBatchedUpdates(); @@ -297,6 +315,7 @@ describe('AttachmentStorage', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -367,8 +386,17 @@ describe('AttachmentStorage', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, + }); + addAttachmentWithComment({ + report: {reportID}, + notifyReportID: reportID, + ancestors: [], + attachments: attachmentFiles, + currentUserAccountID: 1, + delegateAccountID: undefined, + conciergeReportID: undefined, }); - addAttachmentWithComment({report: {reportID}, notifyReportID: reportID, ancestors: [], attachments: attachmentFiles, currentUserAccountID: 1, delegateAccountID: undefined}); await waitForBatchedUpdates(); diff --git a/tests/actions/IOUTest/DeleteMoneyRequestTest.ts b/tests/actions/IOUTest/DeleteMoneyRequestTest.ts index 86661ad5afef..d016fa2826ad 100644 --- a/tests/actions/IOUTest/DeleteMoneyRequestTest.ts +++ b/tests/actions/IOUTest/DeleteMoneyRequestTest.ts @@ -814,6 +814,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: RORY_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -964,6 +965,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: RORY_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -1021,6 +1023,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: RORY_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); } await waitForBatchedUpdates(); @@ -1461,6 +1464,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); diff --git a/tests/actions/IOUTest/DuplicateTest.ts b/tests/actions/IOUTest/DuplicateTest.ts index bd2a277a0b97..1e8187045bb9 100644 --- a/tests/actions/IOUTest/DuplicateTest.ts +++ b/tests/actions/IOUTest/DuplicateTest.ts @@ -531,6 +531,7 @@ describe('actions/Duplicate', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: RORY_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); }; diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts index f2b1bd2022e0..7706a7fb0387 100644 --- a/tests/actions/IOUTest/SplitTest.ts +++ b/tests/actions/IOUTest/SplitTest.ts @@ -4434,6 +4434,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -4496,6 +4497,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -4541,6 +4543,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -4659,6 +4662,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -4740,6 +4744,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -4812,6 +4817,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -4879,6 +4885,7 @@ describe('updateSplitTransactions', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); diff --git a/tests/actions/IOUTest/TrackExpenseTest.ts b/tests/actions/IOUTest/TrackExpenseTest.ts index 208843caddfb..469a836e87c8 100644 --- a/tests/actions/IOUTest/TrackExpenseTest.ts +++ b/tests/actions/IOUTest/TrackExpenseTest.ts @@ -2383,6 +2383,7 @@ describe('actions/IOU/TrackExpense', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: CARLOS_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); diff --git a/tests/actions/MergeTransactionTest.ts b/tests/actions/MergeTransactionTest.ts index 49e53031354b..dc89b9a725c8 100644 --- a/tests/actions/MergeTransactionTest.ts +++ b/tests/actions/MergeTransactionTest.ts @@ -1188,6 +1188,7 @@ describe('mergeTransactionRequest', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index ae85aa79666f..db363c7538d1 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -273,6 +273,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -517,6 +518,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Then we should expect that there is on persisted request @@ -648,6 +650,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_1_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -668,6 +671,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_1_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -687,6 +691,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_1_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -987,6 +992,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -1125,6 +1131,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -1373,6 +1380,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Need the reportActionID to delete the comments @@ -1458,6 +1466,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportActionID = PersistedRequests.getAll().at(0)?.data?.reportActionID as string | undefined; @@ -1505,6 +1514,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -1578,6 +1588,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForNetworkPromises(); @@ -1633,7 +1644,15 @@ describe('actions/Report', () => { const file = new File([''], 'test.txt', {type: 'text/plain'}); const REPORT: OnyxTypes.Report = createRandomReport(1, undefined); - Report.addAttachmentWithComment({report: REPORT, notifyReportID: REPORT_ID, ancestors: [], attachments: file, currentUserAccountID: 1, delegateAccountID: undefined}); + Report.addAttachmentWithComment({ + report: REPORT, + notifyReportID: REPORT_ID, + ancestors: [], + attachments: file, + currentUserAccountID: 1, + delegateAccountID: undefined, + conciergeReportID: undefined, + }); // Need the reportActionID to delete the comments const newComment = PersistedRequests.getAll().at(0); @@ -1716,6 +1735,7 @@ describe('actions/Report', () => { currentUserAccountID: 1, text: 'Attachment with comment', delegateAccountID: undefined, + conciergeReportID: undefined, }); // Need the reportActionID to delete the comments @@ -1815,6 +1835,7 @@ describe('actions/Report', () => { timezone: CONST.DEFAULT_TIME_ZONE, shouldPlaySound, delegateAccountID: undefined, + conciergeReportID: undefined, }); const relevant = (await relevantPromise) as OnyxTypes.AnyRequest[]; @@ -1863,6 +1884,7 @@ describe('actions/Report', () => { timezone: CONST.DEFAULT_TIME_ZONE, shouldPlaySound, delegateAccountID: undefined, + conciergeReportID: undefined, }); const relevant = (await relevantPromise) as OnyxTypes.AnyRequest[]; @@ -1901,7 +1923,15 @@ describe('actions/Report', () => { const file = new File(['a'], 'a.txt', {type: 'text/plain'}); const REPORT: OnyxTypes.Report = createRandomReport(1, undefined); - Report.addAttachmentWithComment({report: REPORT, notifyReportID: REPORT_ID, ancestors: [], attachments: file, currentUserAccountID: 1, delegateAccountID: undefined}); + Report.addAttachmentWithComment({ + report: REPORT, + notifyReportID: REPORT_ID, + ancestors: [], + attachments: file, + currentUserAccountID: 1, + delegateAccountID: undefined, + conciergeReportID: undefined, + }); const relevant = (await relevantPromise) as OnyxTypes.AnyRequest[]; expect(playSoundMock).toHaveBeenCalledTimes(0); @@ -2078,6 +2108,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Need the reportActionID to delete the comments @@ -2186,6 +2217,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Need the reportActionID to delete the comments — read before the queue processes the request @@ -2275,6 +2307,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); const newComment = PersistedRequests.getAll().at(0); @@ -2337,6 +2370,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Need the reportActionID to delete the comments const newComment = PersistedRequests.getAll().at(0); @@ -2433,6 +2467,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Get the reportActionID to edit and delete the comment @@ -6192,7 +6227,7 @@ describe('actions/Report', () => { }); await waitForBatchedUpdates(); - resolveSuggestedFollowup(report, undefined, reportAction, {text: 'test question'}, CONST.DEFAULT_TIME_ZONE, TEST_USER_ACCOUNT_ID, TEST_USER_EMAIL, undefined); + resolveSuggestedFollowup(report, undefined, reportAction, {text: 'test question'}, CONST.DEFAULT_TIME_ZONE, TEST_USER_ACCOUNT_ID, TEST_USER_EMAIL, undefined, undefined); await waitForBatchedUpdates(); // The report action should remain unchanged (no followup-list to resolve) @@ -6220,7 +6255,17 @@ describe('actions/Report', () => { }); await waitForBatchedUpdates(); - resolveSuggestedFollowup(report, undefined, reportAction, {text: 'How do I set up QuickBooks?'}, CONST.DEFAULT_TIME_ZONE, TEST_USER_ACCOUNT_ID, TEST_USER_EMAIL, undefined); + resolveSuggestedFollowup( + report, + undefined, + reportAction, + {text: 'How do I set up QuickBooks?'}, + CONST.DEFAULT_TIME_ZONE, + TEST_USER_ACCOUNT_ID, + TEST_USER_EMAIL, + undefined, + undefined, + ); await waitForBatchedUpdates(); // Verify the followup-list was marked as selected @@ -6261,6 +6306,7 @@ describe('actions/Report', () => { TEST_USER_ACCOUNT_ID, TEST_USER_EMAIL, undefined, + undefined, ); await waitForBatchedUpdates(); @@ -6314,6 +6360,7 @@ describe('actions/Report', () => { TEST_USER_ACCOUNT_ID, TEST_USER_EMAIL, undefined, + undefined, ); await waitForBatchedUpdates(); @@ -6354,7 +6401,17 @@ describe('actions/Report', () => { }); await waitForBatchedUpdates(); - resolveSuggestedFollowup(report, undefined, reportAction, {text: 'How do I set up QuickBooks?'}, CONST.DEFAULT_TIME_ZONE, TEST_USER_ACCOUNT_ID, TEST_USER_EMAIL, undefined); + resolveSuggestedFollowup( + report, + undefined, + reportAction, + {text: 'How do I set up QuickBooks?'}, + CONST.DEFAULT_TIME_ZONE, + TEST_USER_ACCOUNT_ID, + TEST_USER_EMAIL, + undefined, + undefined, + ); await waitForBatchedUpdates(); const telemetryCall = logInfoSpy.mock.calls.find((args) => { @@ -6367,6 +6424,23 @@ describe('actions/Report', () => { }); }); + describe('resolveConciergeCategoryOptions', () => { + it('posts the selected category back to Concierge as a comment (routes through resolveConciergeOptions → addComment)', async () => { + global.fetch = TestHelper.getGlobalFetchMock(); + const REPORT_ID = 'concierge-opts-1'; + const report = createMock({reportID: REPORT_ID, type: CONST.REPORT.TYPE.CHAT}); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); + await waitForBatchedUpdates(); + + // When the user picks one of the Concierge-suggested category options + Report.resolveConciergeCategoryOptions(report, REPORT_ID, '5150', 'Food', CONST.DEFAULT_TIME_ZONE, 1, undefined); + await waitForBatchedUpdates(); + + // Then the selection is posted back to Concierge as a comment + TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.ADD_COMMENT, 1); + }); + }); + // Shared test constants for leave functions const TEST_CONCIERGE_REPORT_ID = '999'; const TEST_CURRENT_USER_ACCOUNT_ID = 1; @@ -7866,6 +7940,7 @@ describe('actions/Report', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: TEST_USER_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index b4743400a1a0..43136b9af19d 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -536,6 +536,7 @@ describe('Unread Indicators', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_A_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -617,6 +618,7 @@ describe('Unread Indicators', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_A_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); return waitForBatchedUpdates(); }) @@ -672,6 +674,7 @@ describe('Unread Indicators', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_A_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -691,6 +694,7 @@ describe('Unread Indicators', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_A_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); @@ -873,6 +877,7 @@ describe('Unread Indicators', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: USER_A_ACCOUNT_ID, delegateAccountID: undefined, + conciergeReportID: undefined, }); await waitForBatchedUpdates(); diff --git a/tests/unit/SidebarOrderTest.ts b/tests/unit/SidebarOrderTest.ts index ca00cde5bd25..5a80500bc44d 100644 --- a/tests/unit/SidebarOrderTest.ts +++ b/tests/unit/SidebarOrderTest.ts @@ -157,6 +157,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -166,6 +167,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -175,6 +177,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportCollectionDataSet: ReportCollectionDataSet = { @@ -229,6 +232,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -238,6 +242,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -247,6 +252,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const currentReportId = report1.reportID; @@ -301,6 +307,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -310,6 +317,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -319,6 +327,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportCollectionDataSet: ReportCollectionDataSet = { @@ -387,6 +396,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -396,6 +406,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -405,6 +416,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportCollectionDataSet: ReportCollectionDataSet = { @@ -485,6 +497,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -494,6 +507,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -503,6 +517,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportCollectionDataSet: ReportCollectionDataSet = { @@ -588,6 +603,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -597,6 +613,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -606,6 +623,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportCollectionDataSet: ReportCollectionDataSet = { @@ -662,6 +680,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -671,6 +690,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -680,6 +700,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const currentReportId = report2.reportID; @@ -835,6 +856,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const iouReport: OnyxTypes.Report = { @@ -1051,6 +1073,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -1060,6 +1083,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -1069,6 +1093,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); // Given the user is in all betas @@ -1129,6 +1154,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report2, @@ -1138,6 +1164,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); addComment({ report: report3, @@ -1147,6 +1174,7 @@ describe('Sidebar', () => { timezoneParam: CONST.DEFAULT_TIME_ZONE, currentUserAccountID: 1, delegateAccountID: undefined, + conciergeReportID: undefined, }); const reportCollectionDataSet: ReportCollectionDataSet = { diff --git a/tests/unit/SuggestedFollowupTest.ts b/tests/unit/SuggestedFollowupTest.ts index 0e0ce91eb93c..c0aa6fd90273 100644 --- a/tests/unit/SuggestedFollowupTest.ts +++ b/tests/unit/SuggestedFollowupTest.ts @@ -1,11 +1,16 @@ -import {applyPendingConciergeAction, clearPendingFollowupList, discardPendingConciergeAction} from '@libs/actions/Report/SuggestedFollowup'; +import * as ReportActions from '@libs/actions/Report'; +import {applyPendingConciergeAction, clearPendingFollowupList, discardPendingConciergeAction, resolveSuggestedFollowup} from '@libs/actions/Report/SuggestedFollowup'; +import type {Followup} from '@libs/ReportActionFollowupUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {ReportAction} from '@src/types/onyx'; +import type {Report, ReportAction} from '@src/types/onyx'; +import type {Timezone} from '@src/types/onyx/PersonalDetails'; import Onyx from 'react-native-onyx'; +import createRandomReportAction from '../utils/collections/reportActions'; +import {createRandomReport} from '../utils/collections/reports'; import getOnyxValue from '../utils/getOnyxValue'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -127,4 +132,87 @@ describe('SuggestedFollowup actions — followup-list skeleton flag', () => { expect(pendingFollowupList?.reportActionID).toBe(REPORT_ACTION_ID); }); }); + + describe('resolveSuggestedFollowup — conciergeReportID threading', () => { + const CONCIERGE_REPORT_ID = 'concierge-report-id-42'; + const CURRENT_USER_ACCOUNT_ID = 5; + const CURRENT_USER_EMAIL = 'user@example.com'; + const timezone = CONST.DEFAULT_TIME_ZONE as Timezone; + + // A report action carrying an unresolved , so buildOptimisticResolvedFollowups + // returns a truthy value and resolveSuggestedFollowup proceeds to call addComment. + const followupReport: Report = { + ...createRandomReport(1, undefined), + reportID: REPORT_ID, + type: CONST.REPORT.TYPE.CHAT, + }; + const followupListReportAction: ReportAction = { + ...createRandomReportAction(1), + reportActionID: REPORT_ACTION_ID, + actorAccountID: CONST.ACCOUNT_ID.CONCIERGE, + actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, + message: [ + { + html: 'Why was this flagged?', + text: 'Why was this flagged?', + type: CONST.REPORT.MESSAGE.TYPE.COMMENT, + }, + ], + }; + + it('forwards the real conciergeReportID to addComment instead of falling back to the deprecated Onyx.connect value', async () => { + // Given addComment is stubbed so we can inspect the params it receives + const addCommentSpy = jest.spyOn(ReportActions, 'addComment').mockImplementation(() => {}); + // And a followup with no pre-generated response (the plain-comment path) + const selectedFollowup: Followup = {text: 'Why was this flagged?'}; + + // When the followup is resolved with a concrete conciergeReportID + resolveSuggestedFollowup( + followupReport, + undefined, + followupListReportAction, + selectedFollowup, + timezone, + CURRENT_USER_ACCOUNT_ID, + CURRENT_USER_EMAIL, + undefined, + CONCIERGE_REPORT_ID, + ); + await waitForBatchedUpdates(); + + // Then that exact conciergeReportID is threaded through to addComment (not undefined) + expect(addCommentSpy).toHaveBeenCalledTimes(1); + expect(addCommentSpy).toHaveBeenCalledWith(expect.objectContaining({conciergeReportID: CONCIERGE_REPORT_ID})); + + addCommentSpy.mockRestore(); + }); + + it('forwards the conciergeReportID on the pre-generated-response path as well', async () => { + // Given addComment is stubbed and a followup that carries a pre-generated Concierge response + const addCommentSpy = jest.spyOn(ReportActions, 'addComment').mockImplementation(() => {}); + const selectedFollowup: Followup = { + text: 'Why was this flagged?', + response: 'Because it was a duplicate.', + }; + + // When the followup is resolved + resolveSuggestedFollowup( + followupReport, + undefined, + followupListReportAction, + selectedFollowup, + timezone, + CURRENT_USER_ACCOUNT_ID, + CURRENT_USER_EMAIL, + undefined, + CONCIERGE_REPORT_ID, + ); + await waitForBatchedUpdates(); + + // Then the user's immediately-posted comment still carries the real conciergeReportID + expect(addCommentSpy).toHaveBeenCalledWith(expect.objectContaining({conciergeReportID: CONCIERGE_REPORT_ID})); + + addCommentSpy.mockRestore(); + }); + }); });