Skip to content
Merged
33 changes: 19 additions & 14 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11526,6 +11526,8 @@ function prepareOnboardingOnyxData({

// Guides are assigned and tasks are posted in the #admins room for the MANAGE_TEAM and TRACK_WORKSPACE onboarding actions, except for emails that have a '+'.
const shouldPostTasksInAdminsRoom = isPostingTasksInAdminsRoom(engagementChoice);
// When posting to admins room in non-production environments, we skip tasks in favor of backend-generated followups.
const shouldUseFollowupsInsteadOfTasks = shouldPostTasksInAdminsRoom && environment !== CONST.ENVIRONMENT.PRODUCTION;
const adminsChatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${adminsChatReportID}`];
const targetChatReport = shouldPostTasksInAdminsRoom
? (adminsChatReport ?? {reportID: adminsChatReportID, policyID: onboardingPolicyID})
Expand Down Expand Up @@ -11602,7 +11604,9 @@ function prepareOnboardingOnyxData({
let addExpenseApprovalsTaskReportID;
let setupTagsTaskReportID;
let setupCategoriesAndTagsTaskReportID;
const tasksData = onboardingMessage.tasks
// If shouldUseFollowupsInsteadOfTasks we do not want to generate tasks in favour of followups.
const tasks = shouldUseFollowupsInsteadOfTasks ? [] : onboardingMessage.tasks;
const tasksData = tasks
.filter((task) => {
if (engagementChoice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM) {
if (!!selectedInterestedFeatures && TASK_TO_FEATURE[task.type] && !selectedInterestedFeatures.includes(TASK_TO_FEATURE[task.type])) {
Expand Down Expand Up @@ -11879,7 +11883,7 @@ function prepareOnboardingOnyxData({
}, []);

const optimisticData: Array<TupleToUnion<typeof tasksForOptimisticData> | OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [...tasksForOptimisticData];
const lastVisibleActionCreated = welcomeSignOffCommentAction.created;
const lastVisibleActionCreated = shouldUseFollowupsInsteadOfTasks ? textCommentAction.created : welcomeSignOffCommentAction.created;
optimisticData.push(
Comment on lines 11885 to 11887

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Avoid updating lastVisibleActionCreated without an action

When shouldUseFollowupsInsteadOfTasks is true (admins room in non‑production), this path skips adding the text/sign‑off report actions, but still sets lastVisibleActionCreated to textCommentAction.created. That makes the admins report look like it has a new action even though no visible action exists, so the report can jump to the top/unread with an empty action list until backend followups arrive. Consider leaving lastVisibleActionCreated unchanged (or only updating it when you actually insert the corresponding report action) in the followups path.

Useful? React with 👍 / 👎.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me since we don't create textCommentAction optimistically.

{
onyxMethod: Onyx.METHOD.MERGE,
Expand All @@ -11902,14 +11906,15 @@ function prepareOnboardingOnyxData({
},
},
);

optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`,
value: {
[textCommentAction.reportActionID]: textCommentAction as ReportAction,
},
});
if (!shouldUseFollowupsInsteadOfTasks) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`,
value: {
[textCommentAction.reportActionID]: textCommentAction as ReportAction,
},
});
}

if (!wasInvited) {
optimisticData.push({
Expand Down Expand Up @@ -12035,8 +12040,9 @@ function prepareOnboardingOnyxData({

// If we post tasks in the #admins room and introSelected?.choice does not exist, it means that a guide is assigned and all messages except tasks are handled by the backend
const guidedSetupData: GuidedSetupData = [];

guidedSetupData.push({type: 'message', ...textMessage});
if (!shouldUseFollowupsInsteadOfTasks) {
guidedSetupData.push({type: 'message', ...textMessage});
}

let selfDMParameters: SelfDMParameters = {};
if (
Expand Down Expand Up @@ -12107,10 +12113,9 @@ function prepareOnboardingOnyxData({
);
}
}

guidedSetupData.push(...tasksForParameters);

if (!introSelected?.choice || introSelected.choice === CONST.ONBOARDING_CHOICES.TEST_DRIVE_RECEIVER) {
if (!shouldUseFollowupsInsteadOfTasks && (!introSelected?.choice || introSelected.choice === CONST.ONBOARDING_CHOICES.TEST_DRIVE_RECEIVER)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`,
Expand Down
8 changes: 3 additions & 5 deletions tests/actions/PolicyTest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {Str} from 'expensify-common';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import {getOnboardingMessages} from '@libs/actions/Welcome/OnboardingFlow';
import {WRITE_COMMANDS} from '@libs/API/types';
// eslint-disable-next-line no-restricted-syntax
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
Expand Down Expand Up @@ -176,13 +175,12 @@ describe('actions/Policy', () => {
expect(reportAction.actorAccountID).toBe(ESH_ACCOUNT_ID);
}

// Following tasks are filtered in prepareOnboardingOnyxData: 'viewTour', 'addAccountingIntegration' and 'setupCategoriesAndTags' (-3)
const {onboardingMessages} = getOnboardingMessages();
const expectedManageTeamDefaultTasksCount = onboardingMessages[CONST.ONBOARDING_CHOICES.MANAGE_TEAM].tasks.length - 3;
// We do not pass tasks to `#admins` channel in favour of backed generated followup-list
const expectedManageTeamDefaultTasksCount = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add test case of email having +?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually this test result will not be affected by + in the email. We are only checking for #admins channel actions that are empty either way now. Would skip adding this one, it will duplicate a lot of code :(


// After filtering, two actions are added to the list =- signoff message (+1) and default create action (+1)
const expectedReportActionsOfTypeCreatedCount = 1;
const expectedSignOffMessagesCount = 1;
const expectedSignOffMessagesCount = 0;
expect(adminReportActions.length).toBe(expectedManageTeamDefaultTasksCount + expectedReportActionsOfTypeCreatedCount + expectedSignOffMessagesCount);

let reportActionsOfTypeCreatedCount = 0;
Expand Down
55 changes: 55 additions & 0 deletions tests/unit/ReportUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,21 @@ describe('ReportUtils', () => {
});

describe('prepareOnboardingOnyxData', () => {
const REPORT_ID = '5';
beforeEach(async () => {
Onyx.merge(ONYXKEYS.SESSION, {email: 'test+test@example.com'});

const chatReport: Report = {
reportID: REPORT_ID,
type: CONST.REPORT.TYPE.CHAT,
participants: {
[CONST.ACCOUNT_ID.CONCIERGE]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS},
[currentUserAccountID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS},
},
};
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport);
});

it('provides test drive url to task title', () => {
const title = jest.fn();

Expand Down Expand Up @@ -509,6 +524,46 @@ describe('ReportUtils', () => {
);
});

it('should not add anything to guidedSetupData when posting into the admin room', async () => {
const adminsChatReportID = '1';
// Not having `+` in the email allows for `isPostingTasksInAdminsRoom` flow
await Onyx.merge(ONYXKEYS.SESSION, {email: 'test@example.com'});
Comment on lines +527 to +530
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add test case of email having +?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

await waitForBatchedUpdates();

const result = prepareOnboardingOnyxData({
introSelected: undefined,
engagementChoice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM,
onboardingMessage: {
message: 'This is a test',
tasks: [{type: CONST.ONBOARDING_TASK_TYPE.CONNECT_CORPORATE_CARD, title: () => '', description: () => '', autoCompleted: false, mediaAttributes: {}}],
},
adminsChatReportID,
selectedInterestedFeatures: ['areCompanyCardsEnabled'],
companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO,
});
expect(result?.guidedSetupData).toHaveLength(0);
expect(result?.optimisticData.filter((i) => i.key === `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`)).toHaveLength(0);
});

it('should add guidedSetupData when email has a +', async () => {
const adminsChatReportID = '1';
await waitForBatchedUpdates();

const result = prepareOnboardingOnyxData({
introSelected: undefined,
engagementChoice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM,
onboardingMessage: {
message: 'This is a test',
tasks: [{type: CONST.ONBOARDING_TASK_TYPE.CONNECT_CORPORATE_CARD, title: () => '', description: () => '', autoCompleted: false, mediaAttributes: {}}],
},
adminsChatReportID,
selectedInterestedFeatures: ['areCompanyCardsEnabled'],
companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO,
});
expect(result?.guidedSetupData).toHaveLength(3);
expect(result?.optimisticData.filter((i) => i.key === `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`)).toHaveLength(0);
});

it('should not create tasks if the task feature is not in the selected interested features', () => {
const result = prepareOnboardingOnyxData({
introSelected: undefined,
Expand Down
Loading