Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,10 @@ function MoneyRequestReportPreviewContent({
}, [carouselTransactions.length]);

return (
<View onLayout={onWrapperLayout}>
<View
onLayout={onWrapperLayout}
testID="MoneyRequestReportPreviewContent-wrapper"
>
<OfflineWithFeedback
pendingAction={iouReport?.pendingFields?.preview}
shouldDisableOpacity={!!(action.pendingAction ?? action.isOptimisticAction)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useCallback, useMemo, useState} from 'react';
import React, {useCallback, useMemo, useRef, useState} from 'react';
import type {LayoutChangeEvent, ListRenderItem} from 'react-native';
import {usePersonalDetails} from '@components/OnyxProvider';
import TransactionPreview from '@components/ReportActionItem/TransactionPreview';
Expand Down Expand Up @@ -52,11 +52,42 @@ function MoneyRequestReportPreview({
const lastTransactionViolations = useTransactionViolations(lastTransaction?.transactionID);
const isTrackExpenseAction = isTrackExpenseActionReportActionsUtils(action);
const isSplitBillAction = isSplitBillActionReportActionsUtils(action);
const [currentWidth, setCurrentWidth] = useState<number>(0);
const [currentWrapperWidth, setCurrentWrapperWidth] = useState<number>(0);

const widthsRef = useRef<{currentWidth: number | null; currentWrapperWidth: number | null}>({currentWidth: null, currentWrapperWidth: null});
const [widths, setWidths] = useState({currentWidth: 0, currentWrapperWidth: 0});

const updateWidths = useCallback(() => {
const {currentWidth, currentWrapperWidth} = widthsRef.current;

if (currentWidth && currentWrapperWidth) {
setWidths({currentWidth, currentWrapperWidth});
}
}, []);

const onCarouselLayout = useCallback(
(e: LayoutChangeEvent) => {
const newWidth = e.nativeEvent.layout.width;
if (widthsRef.current.currentWidth !== newWidth) {
widthsRef.current.currentWidth = newWidth;
updateWidths();
}
},
[updateWidths],
);
const onWrapperLayout = useCallback(
(e: LayoutChangeEvent) => {
const newWrapperWidth = e.nativeEvent.layout.width;
if (widthsRef.current.currentWrapperWidth !== newWrapperWidth) {
widthsRef.current.currentWrapperWidth = newWrapperWidth;
updateWidths();
}
},
[updateWidths],
);

const reportPreviewStyles = useMemo(
() => StyleUtils.getMoneyRequestReportPreviewStyle(shouldUseNarrowLayout, transactions.length, currentWidth, currentWrapperWidth),
[StyleUtils, currentWidth, currentWrapperWidth, shouldUseNarrowLayout, transactions.length],
() => StyleUtils.getMoneyRequestReportPreviewStyle(shouldUseNarrowLayout, transactions.length, widths.currentWidth, widths.currentWrapperWidth),
[StyleUtils, widths, shouldUseNarrowLayout, transactions.length],
);
const shouldShowPayerAndReceiver = useMemo(() => {
if (!isIOUReport(iouReport) && action.childType !== CONST.REPORT.TYPE.IOU) {
Expand Down Expand Up @@ -121,13 +152,9 @@ function MoneyRequestReportPreview({
invoiceReceiverPolicy={invoiceReceiverPolicy}
lastTransactionViolations={lastTransactionViolations}
renderTransactionItem={renderItem}
onCarouselLayout={(e: LayoutChangeEvent) => {
setCurrentWidth(e.nativeEvent.layout.width);
}}
onWrapperLayout={(e: LayoutChangeEvent) => {
setCurrentWrapperWidth(e.nativeEvent.layout.width);
}}
currentWidth={currentWidth}
onCarouselLayout={onCarouselLayout}
onWrapperLayout={onWrapperLayout}
currentWidth={widths.currentWidth}
reportPreviewStyles={reportPreviewStyles}
shouldDisplayContextMenu={shouldDisplayContextMenu}
isInvoice={isInvoice}
Expand Down
15 changes: 12 additions & 3 deletions tests/ui/MoneyRequestReportPreview.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {PortalProvider} from '@gorhom/portal';
import * as NativeNavigation from '@react-navigation/native';
import {fireEvent, render, screen} from '@testing-library/react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry, OnyxMergeInput} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import ComposeProviders from '@components/ComposeProviders';
import {LocaleContextProvider} from '@components/LocaleContextProvider';
Expand All @@ -10,7 +10,6 @@ import OptionsListContextProvider from '@components/OptionListContextProvider';
import MoneyRequestReportPreview from '@components/ReportActionItem/MoneyRequestReportPreview';
import type {MoneyRequestReportPreviewProps} from '@components/ReportActionItem/MoneyRequestReportPreview/types';
import ScreenWrapper from '@components/ScreenWrapper';
import TransactionPreviewSkeletonView from '@components/TransactionPreviewSkeletonView';
import {convertToDisplayString} from '@libs/CurrencyUtils';
import DateUtils from '@libs/DateUtils';
import {translateLocal} from '@libs/Localize';
Expand Down Expand Up @@ -100,6 +99,9 @@ const getTransactionDisplayAmountAndHeaderText = (transaction: Transaction) => {
};

const setCurrentWidth = () => {
fireEvent(screen.getByTestId('MoneyRequestReportPreviewContent-wrapper'), 'layout', {
nativeEvent: {layout: {width: 600}},
});
fireEvent(screen.getByTestId('carouselWidthSetter'), 'layout', {
nativeEvent: {layout: {width: 500}},
});
Expand Down Expand Up @@ -147,6 +149,7 @@ describe('MoneyRequestReportPreview', () => {
await waitForBatchedUpdatesWithAct();
setCurrentWidth();
await Onyx.mergeCollection(ONYXKEYS.COLLECTION.TRANSACTION, mockOnyxTransactions).then(waitForBatchedUpdates);
await waitForBatchedUpdatesWithAct();
const {reportName: moneyRequestReportPreviewName = ''} = mockChatReport;
for (const transaction of arrayOfTransactions) {
const {transactionDisplayAmount, transactionHeaderText} = getTransactionDisplayAmountAndHeaderText(transaction);
Expand All @@ -163,13 +166,19 @@ describe('MoneyRequestReportPreview', () => {
await waitForBatchedUpdatesWithAct();
setCurrentWidth();
await Onyx.multiSet({...mockOnyxTransactions, ...mockOnyxViolations});
await waitForBatchedUpdatesWithAct();
expect(screen.getAllByText(translateLocal('violations.reviewRequired'))).toHaveLength(2);
});

it('renders a skeleton if the transaction is empty', async () => {
renderPage({});
await waitForBatchedUpdatesWithAct();
setCurrentWidth();
expect(screen.getAllByTestId(TransactionPreviewSkeletonView.displayName)).toHaveLength(2);

await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${mockTransaction.transactionID}`, {} as OnyxMergeInput<`transactions_${string}`>);
await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${mockSecondTransactionID}`, {} as OnyxMergeInput<`transactions_${string}`>);
await waitForBatchedUpdatesWithAct();

expect(screen.getAllByTestId('TransactionPreviewSkeletonView')).toHaveLength(2);
});
});