Skip to content

Commit 60eebb2

Browse files
authored
Merge pull request #95047 from allgandalf/fix-travel-billing-lock-flicker
Fix flickering lock icon on Consolidated Travel Billing toggle
2 parents 9ecd1b5 + 11f7b95 commit 60eebb2

4 files changed

Lines changed: 51 additions & 2 deletions

File tree

src/CONST/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6002,6 +6002,7 @@ const CONST = {
60026002

60036003
DOT_INDICATOR_TEST_ID: 'DotIndicator',
60046004
ANIMATED_COLLAPSIBLE_CONTENT_TEST_ID: 'animated-collapsible-content',
6005+
SWITCH_LOCK_ICON_TEST_ID: 'SwitchLockIcon',
60056006

60066007
HORIZONTAL_SPACER: {
60076008
DEFAULT_BORDER_BOTTOM_WIDTH: 1,

src/components/Switch.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon, dis
125125
<Animated.View style={[styles.switchThumb, animatedThumbStyle]}>
126126
{(!!disabled || !!showLockIcon) && (
127127
<Icon
128+
testID={CONST.SWITCH_LOCK_ICON_TEST_ID}
128129
src={expensifyIcons.Lock}
129130
fill={isOn ? theme.text : theme.icon}
130131
width={styles.toggleSwitchLockIcon.width}

src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
146146
const isTravelInvoicingEnabled = getIsTravelInvoicingEnabled(travelSettings);
147147
const isOnWaitlist = !!cardOnWaitlist;
148148
const isLoading = !!cardSettings?.isLoading;
149+
const hasOutstandingBalance = hasOutstandingTravelBalance(travelSettings);
149150
const hasTravelProvisioningErrors = isTravelInvoicingEnabled && !!domainMemberData?.settings?.travelInvoicing?.errors?.length;
150151

151152
/**
@@ -232,7 +233,7 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
232233

233234
if (!isEnabled) {
234235
// Trying to disable - check for outstanding balance first
235-
if (hasOutstandingTravelBalance(travelSettings)) {
236+
if (hasOutstandingBalance) {
236237
// Show blocker modal with error message
237238
setIsOutstandingBalanceModalVisible(true);
238239
return;
@@ -412,7 +413,7 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
412413
isActive={isTravelInvoicingEnabled}
413414
disabled={!canWriteMoreFeatures || isLoading || isOnWaitlist}
414415
disabledAction={getToggleDisabledAction()}
415-
showLockIcon={!canWriteMoreFeatures || isOnWaitlist}
416+
showLockIcon={!canWriteMoreFeatures || isOnWaitlist || hasOutstandingBalance}
416417
pendingAction={togglePendingAction}
417418
errors={toggleErrors}
418419
onCloseError={() => clearTravelInvoicingErrors(workspaceAccountID)}

tests/ui/WorkspaceTravelInvoicingSectionTest.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,52 @@ describe('WorkspaceTravelInvoicingSection', () => {
505505
});
506506
});
507507

508+
describe('Lock icon (outstanding balance)', () => {
509+
const cardSettingsKey = getTravelInvoicingCardSettingsKey(WORKSPACE_ACCOUNT_ID);
510+
511+
it('shows the toggle lock icon when there is an outstanding travel balance', async () => {
512+
// Given a configured workspace with an unpaid travel balance
513+
await act(async () => {
514+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${POLICY_ID}`, mockPolicy);
515+
await Onyx.merge(cardSettingsKey, {
516+
TRAVEL_US: {
517+
isEnabled: true,
518+
paymentBankAccountID: 12345,
519+
currentBalance: 5000,
520+
},
521+
});
522+
await waitForBatchedUpdatesWithAct();
523+
});
524+
525+
renderWorkspaceTravelInvoicingSection();
526+
await waitForBatchedUpdatesWithAct();
527+
528+
// The lock stays on the toggle since the feature can't be turned off until the balance is paid
529+
expect(screen.getByTestId(CONST.SWITCH_LOCK_ICON_TEST_ID, {includeHiddenElements: true})).toBeTruthy();
530+
});
531+
532+
it('does not show the toggle lock icon when the balance is paid', async () => {
533+
// Given a configured workspace with no outstanding balance and no pending settlement
534+
await act(async () => {
535+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${POLICY_ID}`, mockPolicy);
536+
await Onyx.merge(cardSettingsKey, {
537+
TRAVEL_US: {
538+
isEnabled: true,
539+
paymentBankAccountID: 12345,
540+
currentBalance: 0,
541+
pendingSettlementAmount: 0,
542+
},
543+
});
544+
await waitForBatchedUpdatesWithAct();
545+
});
546+
547+
renderWorkspaceTravelInvoicingSection();
548+
await waitForBatchedUpdatesWithAct();
549+
550+
expect(screen.queryByTestId(CONST.SWITCH_LOCK_ICON_TEST_ID, {includeHiddenElements: true})).toBeNull();
551+
});
552+
});
553+
508554
describe('Currency Conversion Prompt', () => {
509555
const cardSettingsKey = getTravelInvoicingCardSettingsKey(WORKSPACE_ACCOUNT_ID);
510556

0 commit comments

Comments
 (0)