Skip to content

Commit 32f682c

Browse files
authored
Merge pull request Expensify#85435 from dukenv0307/fix/66424-part-11
2 parents 482e0d7 + d5c7265 commit 32f682c

3 files changed

Lines changed: 160 additions & 27 deletions

File tree

src/libs/actions/Report/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,7 @@ function createGroupChat(
16571657
newReportObject: OptimisticChatReport,
16581658
currentUserLogin: string,
16591659
introSelected: OnyxEntry<IntroSelected>,
1660+
isSelfTourViewed: boolean | undefined,
16601661
avatar?: File | CustomRNImageManipulatorResult,
16611662
// TODO: Remove optional (?) once buildPolicyData is updated (https://github.com/Expensify/App/issues/66417)
16621663
betas?: OnyxEntry<Beta[]>,
@@ -1820,7 +1821,7 @@ function createGroupChat(
18201821
}
18211822

18221823
// Preserve guided setup data when creating group chats
1823-
const guidedSetup = getGuidedSetupDataForOpenReport(introSelected, betas);
1824+
const guidedSetup = getGuidedSetupDataForOpenReport(introSelected, betas, isSelfTourViewed);
18241825
if (guidedSetup) {
18251826
optimisticData.push(...guidedSetup.optimisticData);
18261827
successData.push(...guidedSetup.successData);
@@ -1996,6 +1997,7 @@ function navigateToAndCreateGroupChat(
19961997
currentUserLogin: string,
19971998
optimisticReportID: string,
19981999
introSelected: OnyxEntry<IntroSelected>,
2000+
isSelfTourViewed: boolean | undefined,
19992001
avatarUri?: string,
20002002
avatarFile?: File | CustomRNImageManipulatorResult | undefined,
20012003
// TODO: Remove optional (?) once buildPolicyData is updated (https://github.com/Expensify/App/issues/66417)
@@ -2005,7 +2007,7 @@ function navigateToAndCreateGroupChat(
20052007

20062008
// If we are creating a group chat then participantAccountIDs is expected to contain currentUserAccountID
20072009
const newChat = buildOptimisticGroupChatReport(participantAccountIDs, reportName, avatarUri ?? '', optimisticReportID, CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN);
2008-
createGroupChat(newChat.reportID, userLogins, newChat, currentUserLogin, introSelected, avatarFile, betas);
2010+
createGroupChat(newChat.reportID, userLogins, newChat, currentUserLogin, introSelected, isSelfTourViewed, avatarFile, betas);
20092011

20102012
navigateToReport(newChat.reportID);
20112013
}

src/pages/NewChatConfirmPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {navigateToAndCreateGroupChat, setGroupDraft} from '@userActions/Report';
2424
import CONST from '@src/CONST';
2525
import ONYXKEYS from '@src/ONYXKEYS';
2626
import ROUTES from '@src/ROUTES';
27+
import {hasSeenTourSelector} from '@src/selectors/Onboarding';
2728
import type {Participant} from '@src/types/onyx/IOU';
2829
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
2930

@@ -45,6 +46,7 @@ function NewChatConfirmPage() {
4546
const [allPersonalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
4647
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
4748
const [betas] = useOnyx(ONYXKEYS.BETAS);
49+
const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
4850

4951
const icons = useMemoizedLazyExpensifyIcons(['Camera']);
5052

@@ -108,11 +110,12 @@ function NewChatConfirmPage() {
108110
personalData.login ?? '',
109111
optimisticReportID.current,
110112
introSelected,
113+
isSelfTourViewed,
111114
newGroupDraft.avatarUri ?? '',
112115
avatarFile,
113116
betas,
114117
);
115-
}, [newGroupDraft, avatarFile, personalData.login, introSelected, betas]);
118+
}, [newGroupDraft, avatarFile, personalData.login, introSelected, betas, isSelfTourViewed]);
116119

117120
const stashedLocalAvatarImage = newGroupDraft?.avatarUri;
118121

tests/actions/ReportTest.ts

Lines changed: 152 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5615,18 +5615,39 @@ describe('actions/Report', () => {
56155615
});
56165616

56175617
describe('navigateToAndCreateGroupChat', () => {
5618+
const TEST_USER_ACCOUNT_ID = 1;
5619+
const TEST_USER_LOGIN = 'test@user.com';
5620+
const PARTICIPANT_1_LOGIN = 'participant1@test.com';
5621+
const PARTICIPANT_1_ACCOUNT_ID = 2;
5622+
5623+
beforeEach(async () => {
5624+
await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN);
5625+
await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {
5626+
[CONST.ACCOUNT_ID.CONCIERGE]: {
5627+
accountID: CONST.ACCOUNT_ID.CONCIERGE,
5628+
login: CONST.EMAIL.CONCIERGE,
5629+
displayName: 'Concierge',
5630+
},
5631+
[TEST_USER_ACCOUNT_ID]: {
5632+
accountID: TEST_USER_ACCOUNT_ID,
5633+
login: TEST_USER_LOGIN,
5634+
displayName: 'Test user account',
5635+
},
5636+
[PARTICIPANT_1_ACCOUNT_ID]: {
5637+
accountID: PARTICIPANT_1_ACCOUNT_ID,
5638+
login: PARTICIPANT_1_LOGIN,
5639+
displayName: 'Participant One',
5640+
},
5641+
});
5642+
await waitForBatchedUpdates();
5643+
});
5644+
56185645
it('should create a group chat and navigate to it', async () => {
56195646
// Given a test user with initial data
5620-
const TEST_USER_ACCOUNT_ID = 1;
5621-
const TEST_USER_LOGIN = 'test@user.com';
5622-
const PARTICIPANT_1_LOGIN = 'participant1@test.com';
5623-
const PARTICIPANT_1_ACCOUNT_ID = 2;
56245647
const GROUP_CHAT_NAME = 'Test Group';
56255648
const GROUP_CHAT_REPORT_ID = '12345';
56265649
const CONCIERGE_REPORT_ID = '99999';
56275650

5628-
await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN);
5629-
56305651
// Create a Concierge chat for guided setup
56315652
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${CONCIERGE_REPORT_ID}`, {
56325653
reportID: CONCIERGE_REPORT_ID,
@@ -5641,31 +5662,14 @@ describe('actions/Report', () => {
56415662
},
56425663
},
56435664
});
5644-
await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {
5645-
[CONST.ACCOUNT_ID.CONCIERGE]: {
5646-
accountID: CONST.ACCOUNT_ID.CONCIERGE,
5647-
login: CONST.EMAIL.CONCIERGE,
5648-
displayName: 'Concierge',
5649-
},
5650-
[TEST_USER_ACCOUNT_ID]: {
5651-
accountID: TEST_USER_ACCOUNT_ID,
5652-
login: TEST_USER_LOGIN,
5653-
displayName: 'Test user account',
5654-
},
5655-
[PARTICIPANT_1_ACCOUNT_ID]: {
5656-
accountID: PARTICIPANT_1_ACCOUNT_ID,
5657-
login: PARTICIPANT_1_LOGIN,
5658-
displayName: 'Participant One',
5659-
},
5660-
});
56615665

56625666
// Set up introSelected and onboarding state for guided setup
56635667
await Onyx.set(ONYXKEYS.NVP_INTRO_SELECTED, TEST_INTRO_SELECTED);
56645668
await Onyx.set(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: false});
56655669
await waitForBatchedUpdates();
56665670

56675671
// When create group chat is called
5668-
Report.navigateToAndCreateGroupChat([TEST_USER_LOGIN, PARTICIPANT_1_LOGIN], GROUP_CHAT_NAME, TEST_USER_LOGIN, GROUP_CHAT_REPORT_ID, TEST_INTRO_SELECTED);
5672+
Report.navigateToAndCreateGroupChat([TEST_USER_LOGIN, PARTICIPANT_1_LOGIN], GROUP_CHAT_NAME, TEST_USER_LOGIN, GROUP_CHAT_REPORT_ID, TEST_INTRO_SELECTED, false);
56695673
await waitForBatchedUpdates();
56705674

56715675
// Then it should create a new group chat report in Onyx
@@ -5685,6 +5689,130 @@ describe('actions/Report', () => {
56855689
const introSelected = await getOnyxValue(ONYXKEYS.NVP_INTRO_SELECTED);
56865690
expect(introSelected?.isInviteOnboardingComplete).toBe(true);
56875691
});
5692+
5693+
it('should create group chat with avatar URI and isSelfTourViewed', async () => {
5694+
const GROUP_CHAT_NAME = 'Avatar Group';
5695+
const GROUP_CHAT_REPORT_ID = '12348';
5696+
const CONCIERGE_REPORT_ID = '99996';
5697+
const AVATAR_URI = 'https://example.com/avatar.png';
5698+
5699+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${CONCIERGE_REPORT_ID}`, {
5700+
reportID: CONCIERGE_REPORT_ID,
5701+
chatType: undefined,
5702+
type: CONST.REPORT.TYPE.CHAT,
5703+
participants: {
5704+
[CONST.ACCOUNT_ID.CONCIERGE]: {
5705+
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
5706+
},
5707+
[TEST_USER_ACCOUNT_ID]: {
5708+
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
5709+
},
5710+
},
5711+
});
5712+
5713+
await Onyx.set(ONYXKEYS.NVP_INTRO_SELECTED, TEST_INTRO_SELECTED);
5714+
await Onyx.set(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: false});
5715+
await waitForBatchedUpdates();
5716+
5717+
// When create group chat is called with an avatar URI and isSelfTourViewed=true
5718+
Report.navigateToAndCreateGroupChat([TEST_USER_LOGIN, PARTICIPANT_1_LOGIN], GROUP_CHAT_NAME, TEST_USER_LOGIN, GROUP_CHAT_REPORT_ID, TEST_INTRO_SELECTED, true, AVATAR_URI);
5719+
await waitForBatchedUpdates();
5720+
5721+
// Then it should create a new group chat report with the avatar
5722+
const newGroupChatReport: OnyxEntry<OnyxTypes.Report> = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${GROUP_CHAT_REPORT_ID}`);
5723+
expect(newGroupChatReport).not.toBeNull();
5724+
expect(newGroupChatReport?.reportName).toBe(GROUP_CHAT_NAME);
5725+
expect(newGroupChatReport?.chatType).toBe(CONST.REPORT.CHAT_TYPE.GROUP);
5726+
expect(newGroupChatReport?.avatarUrl).toBe(AVATAR_URI);
5727+
5728+
// Then guided setup data should have run via the isSelfTourViewed=true path, marking onboarding complete
5729+
const introSelectedAfter = await getOnyxValue(ONYXKEYS.NVP_INTRO_SELECTED);
5730+
expect(introSelectedAfter?.isInviteOnboardingComplete).toBe(true);
5731+
});
5732+
5733+
it('should create group chat when onboarding is already completed and isSelfTourViewed=true', async () => {
5734+
const GROUP_CHAT_NAME = 'Completed Onboarding Group';
5735+
const GROUP_CHAT_REPORT_ID = '12349';
5736+
5737+
// Set onboarding as already completed
5738+
await Onyx.set(ONYXKEYS.NVP_INTRO_SELECTED, {...TEST_INTRO_SELECTED, isInviteOnboardingComplete: true});
5739+
await Onyx.set(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
5740+
await waitForBatchedUpdates();
5741+
5742+
// When create group chat is called with isSelfTourViewed=true but onboarding already completed
5743+
Report.navigateToAndCreateGroupChat(
5744+
[TEST_USER_LOGIN, PARTICIPANT_1_LOGIN],
5745+
GROUP_CHAT_NAME,
5746+
TEST_USER_LOGIN,
5747+
GROUP_CHAT_REPORT_ID,
5748+
{...TEST_INTRO_SELECTED, isInviteOnboardingComplete: true},
5749+
true,
5750+
);
5751+
await waitForBatchedUpdates();
5752+
5753+
// Then the group chat should still be created
5754+
const newGroupChatReport: OnyxEntry<OnyxTypes.Report> = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${GROUP_CHAT_REPORT_ID}`);
5755+
expect(newGroupChatReport).not.toBeNull();
5756+
expect(newGroupChatReport?.reportName).toBe(GROUP_CHAT_NAME);
5757+
expect(newGroupChatReport?.chatType).toBe(CONST.REPORT.CHAT_TYPE.GROUP);
5758+
});
5759+
5760+
it('should include avatarFile in API request when provided', async () => {
5761+
const GROUP_CHAT_REPORT_ID = '12350';
5762+
const avatarFile = new File([''], 'avatar.png', {type: 'image/png'});
5763+
5764+
await Onyx.set(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
5765+
await waitForBatchedUpdates();
5766+
5767+
// When create group chat is called with an avatarFile
5768+
Report.navigateToAndCreateGroupChat(
5769+
[TEST_USER_LOGIN, PARTICIPANT_1_LOGIN],
5770+
'Avatar File Group',
5771+
TEST_USER_LOGIN,
5772+
GROUP_CHAT_REPORT_ID,
5773+
{choice: CONST.ONBOARDING_CHOICES.ADMIN},
5774+
false,
5775+
undefined,
5776+
avatarFile,
5777+
);
5778+
await waitForBatchedUpdates();
5779+
5780+
// Then the group chat report should be created
5781+
const newGroupChatReport: OnyxEntry<OnyxTypes.Report> = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${GROUP_CHAT_REPORT_ID}`);
5782+
expect(newGroupChatReport).not.toBeNull();
5783+
expect(newGroupChatReport?.chatType).toBe(CONST.REPORT.CHAT_TYPE.GROUP);
5784+
5785+
// Then the API should be called with the file parameter
5786+
TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.OPEN_REPORT, 1);
5787+
});
5788+
5789+
it('should add optimistic personal details for participants not in personal details', async () => {
5790+
const GROUP_CHAT_REPORT_ID = '12351';
5791+
const UNKNOWN_PARTICIPANT_LOGIN = 'unknown@test.com';
5792+
5793+
await Onyx.set(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
5794+
await waitForBatchedUpdates();
5795+
5796+
// When create group chat is called with a participant not in allPersonalDetails
5797+
Report.navigateToAndCreateGroupChat(
5798+
[TEST_USER_LOGIN, UNKNOWN_PARTICIPANT_LOGIN],
5799+
'Optimistic Group',
5800+
TEST_USER_LOGIN,
5801+
GROUP_CHAT_REPORT_ID,
5802+
{choice: CONST.ONBOARDING_CHOICES.ADMIN},
5803+
false,
5804+
);
5805+
await waitForBatchedUpdates();
5806+
5807+
// Then the group chat report should be created
5808+
const newGroupChatReport: OnyxEntry<OnyxTypes.Report> = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${GROUP_CHAT_REPORT_ID}`);
5809+
expect(newGroupChatReport).not.toBeNull();
5810+
5811+
// Then optimistic personal details should be added for the unknown participant
5812+
const personalDetails = await getOnyxValue(ONYXKEYS.PERSONAL_DETAILS_LIST);
5813+
const optimisticEntry = Object.values(personalDetails ?? {}).find((details) => details?.login === UNKNOWN_PARTICIPANT_LOGIN && details?.isOptimisticPersonalDetail === true);
5814+
expect(optimisticEntry).not.toBeUndefined();
5815+
});
56885816
});
56895817

56905818
describe('handleWalletStatementNavigation', () => {

0 commit comments

Comments
 (0)