Skip to content

Commit da69a09

Browse files
authored
Merge pull request Expensify#87636 from ZhenjaHorbach/fix-getting-started-slot
Fix issues with getting started slot
2 parents 207349f + 4b18b5f commit da69a09

3 files changed

Lines changed: 94 additions & 17 deletions

File tree

src/pages/home/GettingStartedSection/hooks/useGettingStartedItems.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import useOnyx from '@hooks/useOnyx';
44
import useResponsiveLayout from '@hooks/useResponsiveLayout';
55
import {hasCompanyCardFeeds} from '@libs/CardUtils';
66
import Navigation from '@libs/Navigation/Navigation';
7-
import {hasAccountingConnections, hasCustomCategories, hasNonDefaultRules, isPaidGroupPolicy, isPendingDeletePolicy} from '@libs/PolicyUtils';
7+
import {hasAccountingConnections, hasCustomCategories, hasNonDefaultRules, isPaidGroupPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils';
88
import isWithinGettingStartedPeriod from '@pages/home/GettingStartedSection/utils/isWithinGettingStartedPeriod';
99
import {enablePolicyCategories} from '@userActions/Policy/Category';
1010
import {enableCompanyCards, enablePolicyConnections, enablePolicyRules} from '@userActions/Policy/Policy';
@@ -58,6 +58,10 @@ function useGettingStartedItems(): UseGettingStartedItemsResult {
5858
return emptyResult;
5959
}
6060

61+
if (!isPolicyAdmin(policy)) {
62+
return emptyResult;
63+
}
64+
6165
if (!isWithinGettingStartedPeriod(firstDayFreeTrial)) {
6266
return emptyResult;
6367
}
@@ -103,14 +107,16 @@ function useGettingStartedItems(): UseGettingStartedItemsResult {
103107
enableFeature: () => enableCompanyCards(activePolicyID, true, false),
104108
});
105109

106-
items.push({
107-
key: 'setupRules',
108-
label: translate('homePage.gettingStartedSection.setupRules'),
109-
isComplete: hasNonDefaultRules(policy),
110-
route: ROUTES.WORKSPACE_RULES.getRoute(activePolicyID),
111-
isFeatureEnabled: policy.areRulesEnabled,
112-
enableFeature: () => enablePolicyRules(policy, true, false),
113-
});
110+
if (policy.areRulesEnabled) {
111+
items.push({
112+
key: 'setupRules',
113+
label: translate('homePage.gettingStartedSection.setupRules'),
114+
isComplete: hasNonDefaultRules(policy),
115+
route: ROUTES.WORKSPACE_RULES.getRoute(activePolicyID),
116+
isFeatureEnabled: policy.areRulesEnabled,
117+
enableFeature: () => enablePolicyRules(policy, true, false),
118+
});
119+
}
114120

115121
return {shouldShowSection: true, items};
116122
}

tests/unit/hooks/useGettingStartedItems.test.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ function buildPolicy(overrides: Partial<Policy> = {}): Policy {
3131
...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM, 'Test Workspace'),
3232
id: POLICY_ID,
3333
pendingAction: undefined,
34+
role: CONST.POLICY.ROLE.ADMIN,
3435
areCompanyCardsEnabled: false,
3536
areRulesEnabled: false,
3637
connections: undefined,
@@ -416,10 +417,10 @@ describe('useGettingStartedItems', () => {
416417
});
417418

418419
describe('row 4 - Set up spend rules', () => {
419-
it('should always be shown', async () => {
420+
it('should be shown when areRulesEnabled is true', async () => {
420421
await setupManageTeamScenario({
421422
accounting: CONST.POLICY.CONNECTIONS.NAME.QBO,
422-
policy: {areRulesEnabled: false},
423+
policy: {areRulesEnabled: true},
423424
});
424425

425426
const {result} = renderHook(() => useGettingStartedItems());
@@ -428,6 +429,18 @@ describe('useGettingStartedItems', () => {
428429
expect(rulesItem).toBeDefined();
429430
});
430431

432+
it('should not be shown when areRulesEnabled is false', async () => {
433+
await setupManageTeamScenario({
434+
accounting: CONST.POLICY.CONNECTIONS.NAME.QBO,
435+
policy: {areRulesEnabled: false},
436+
});
437+
438+
const {result} = renderHook(() => useGettingStartedItems());
439+
440+
const rulesItem = result.current.items.find((item) => item.key === 'setupRules');
441+
expect(rulesItem).toBeUndefined();
442+
});
443+
431444
it('should have isFeatureEnabled=true when rules feature is enabled', async () => {
432445
await setupManageTeamScenario({
433446
accounting: CONST.POLICY.CONNECTIONS.NAME.QBO,
@@ -440,7 +453,7 @@ describe('useGettingStartedItems', () => {
440453
expect(rulesItem?.isFeatureEnabled).toBe(true);
441454
});
442455

443-
it('should have isFeatureEnabled=false when rules feature is not enabled', async () => {
456+
it('should not be included in items when rules feature is not enabled', async () => {
444457
await setupManageTeamScenario({
445458
accounting: CONST.POLICY.CONNECTIONS.NAME.QBO,
446459
policy: {areRulesEnabled: false},
@@ -449,7 +462,7 @@ describe('useGettingStartedItems', () => {
449462
const {result} = renderHook(() => useGettingStartedItems());
450463

451464
const rulesItem = result.current.items.find((item) => item.key === 'setupRules');
452-
expect(rulesItem?.isFeatureEnabled).toBe(false);
465+
expect(rulesItem).toBeUndefined();
453466
});
454467

455468
it('should navigate to workspace rules route', async () => {
@@ -540,7 +553,7 @@ describe('useGettingStartedItems', () => {
540553
expect(keys).toEqual(['createWorkspace', 'customizeCategories', 'linkCompanyCards', 'setupRules']);
541554
});
542555

543-
it('should always contain all four rows even when optional features are disabled', async () => {
556+
it('should contain three rows when areRulesEnabled is false', async () => {
544557
await setupManageTeamScenario({
545558
accounting: CONST.POLICY.CONNECTIONS.NAME.QBO,
546559
policy: {areCompanyCardsEnabled: false, areRulesEnabled: false},
@@ -549,7 +562,7 @@ describe('useGettingStartedItems', () => {
549562
const {result} = renderHook(() => useGettingStartedItems());
550563

551564
const keys = result.current.items.map((item) => item.key);
552-
expect(keys).toEqual(['createWorkspace', 'connectAccounting', 'linkCompanyCards', 'setupRules']);
565+
expect(keys).toEqual(['createWorkspace', 'connectAccounting', 'linkCompanyCards']);
553566
});
554567
});
555568

tests/unit/pages/home/GettingStartedSection/GettingStartedSectionTest.tsx

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ async function setManageTeamUserState(overrides?: {
6262
id: TEST_POLICY_ID,
6363
name: 'Test Workspace',
6464
type: CONST.POLICY.TYPE.TEAM,
65+
role: CONST.POLICY.ROLE.ADMIN,
6566
areCompanyCardsEnabled: overrides?.areCompanyCardsEnabled ?? true,
6667
areRulesEnabled: overrides?.areRulesEnabled ?? true,
6768
};
@@ -114,6 +115,62 @@ describe('GettingStartedSection', () => {
114115
expect(screen.queryByText('homePage.gettingStartedSection.title')).toBeNull();
115116
});
116117

118+
it('does not render when user is not an admin (role is user)', async () => {
119+
await Onyx.set(ONYXKEYS.NVP_INTRO_SELECTED, {
120+
choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM,
121+
});
122+
await Onyx.set(ONYXKEYS.NVP_ACTIVE_POLICY_ID, TEST_POLICY_ID);
123+
await Onyx.set(ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL, '2026-03-01');
124+
await Onyx.set(
125+
`${ONYXKEYS.COLLECTION.POLICY}${TEST_POLICY_ID}` as never,
126+
{
127+
id: TEST_POLICY_ID,
128+
name: 'Test Workspace',
129+
type: CONST.POLICY.TYPE.TEAM,
130+
role: CONST.POLICY.ROLE.USER,
131+
areCompanyCardsEnabled: true,
132+
areRulesEnabled: true,
133+
} as never,
134+
);
135+
await waitForBatchedUpdates();
136+
137+
renderGettingStartedSection();
138+
139+
expect(screen.queryByText('homePage.gettingStartedSection.title')).toBeNull();
140+
});
141+
142+
it('does not render when user is not an admin (role is auditor)', async () => {
143+
await Onyx.set(ONYXKEYS.NVP_INTRO_SELECTED, {
144+
choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM,
145+
});
146+
await Onyx.set(ONYXKEYS.NVP_ACTIVE_POLICY_ID, TEST_POLICY_ID);
147+
await Onyx.set(ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL, '2026-03-01');
148+
await Onyx.set(
149+
`${ONYXKEYS.COLLECTION.POLICY}${TEST_POLICY_ID}` as never,
150+
{
151+
id: TEST_POLICY_ID,
152+
name: 'Test Workspace',
153+
type: CONST.POLICY.TYPE.TEAM,
154+
role: CONST.POLICY.ROLE.AUDITOR,
155+
areCompanyCardsEnabled: true,
156+
areRulesEnabled: true,
157+
} as never,
158+
);
159+
await waitForBatchedUpdates();
160+
161+
renderGettingStartedSection();
162+
163+
expect(screen.queryByText('homePage.gettingStartedSection.title')).toBeNull();
164+
});
165+
166+
it('renders when user is an admin', async () => {
167+
await setManageTeamUserState();
168+
169+
renderGettingStartedSection();
170+
171+
expect(screen.getByText('homePage.gettingStartedSection.title')).toBeTruthy();
172+
});
173+
117174
it('renders when manage-team intent is set via fallback ONBOARDING_PURPOSE_SELECTED', async () => {
118175
await Onyx.set(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, CONST.ONBOARDING_CHOICES.MANAGE_TEAM as never);
119176
await Onyx.set(ONYXKEYS.NVP_ACTIVE_POLICY_ID, TEST_POLICY_ID);
@@ -124,6 +181,7 @@ describe('GettingStartedSection', () => {
124181
id: TEST_POLICY_ID,
125182
name: 'Test Workspace',
126183
type: CONST.POLICY.TYPE.TEAM,
184+
role: CONST.POLICY.ROLE.ADMIN,
127185
areCompanyCardsEnabled: true,
128186
areRulesEnabled: true,
129187
} as never,
@@ -212,12 +270,12 @@ describe('GettingStartedSection', () => {
212270
expect(screen.getByText('homePage.gettingStartedSection.setupRules')).toBeTruthy();
213271
});
214272

215-
it('always shows "Set up spend rules" row even when rules feature is disabled', async () => {
273+
it('does not show "Set up spend rules" row when rules feature is disabled', async () => {
216274
await setManageTeamUserState({areRulesEnabled: false});
217275

218276
renderGettingStartedSection();
219277

220-
expect(screen.getByText('homePage.gettingStartedSection.setupRules')).toBeTruthy();
278+
expect(screen.queryByText('homePage.gettingStartedSection.setupRules')).toBeNull();
221279
});
222280

223281
it('renders rows in the expected order: workspace, accounting, cards, rules', async () => {

0 commit comments

Comments
 (0)