diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx
index fe343876f8bc..891b51dd4483 100755
--- a/src/components/HeaderWithBackButton/index.tsx
+++ b/src/components/HeaderWithBackButton/index.tsx
@@ -82,6 +82,10 @@ function HeaderWithBackButton({
shouldDisplaySearchRouter = false,
progressBarPercentage,
style,
+ shouldDisplayResponsiveChildrenInSeparateLine = false,
+ responsiveChildren,
+ responsiveChildrenContainerStyle,
+ bottomContent,
subTitleLink = '',
shouldMinimizeMenuButton = false,
openParentReportInCurrentTab = false,
@@ -232,22 +236,55 @@ function HeaderWithBackButton({
shouldSetModalVisibility,
]);
+ const shouldUseMultiLineLayout = shouldDisplayResponsiveChildrenInSeparateLine || !!bottomContent;
+ const movableChildrenContent = !!responsiveChildren && (
+
+ {responsiveChildren}
+
+ );
+
return (
Keyboard.dismiss() : undefined}
>
-
+
{shouldShowBackButton && (
)}
{middleContent}
-
+
+ {!shouldDisplayResponsiveChildrenInSeparateLine && movableChildrenContent}
+
+
{children}
{shouldShowDownloadButton &&
@@ -375,6 +418,15 @@ function HeaderWithBackButton({
{shouldDisplaySearchRouter && }
{shouldDisplayHelpButton && }
+ {!!bottomContent && (
+
+ {bottomContent}
+
+ )}
+ {shouldDisplayResponsiveChildrenInSeparateLine && movableChildrenContent}
);
}
diff --git a/src/components/HeaderWithBackButton/types.ts b/src/components/HeaderWithBackButton/types.ts
index 8d3cfc6a9917..929edafeefc5 100644
--- a/src/components/HeaderWithBackButton/types.ts
+++ b/src/components/HeaderWithBackButton/types.ts
@@ -166,6 +166,18 @@ type HeaderWithBackButtonProps = Partial & {
/** Additional styles to add to the component */
style?: StyleProp;
+ /** Whether responsive children should be displayed in a full-width line below the main header row */
+ shouldDisplayResponsiveChildrenInSeparateLine?: boolean;
+
+ /** Header actions that can move to a separate line. Regular children always stay in the main row. */
+ responsiveChildren?: ReactNode;
+
+ /** Additional styles for the responsive children container */
+ responsiveChildrenContainerStyle?: StyleProp;
+
+ /** Full-width content displayed below the main header row and above responsive children */
+ bottomContent?: ReactNode;
+
/** The URL link associated with the attachment's subtitle, if available */
subTitleLink?: string;
diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx
index 1fba8db9c14a..9bab0e38b60b 100644
--- a/src/components/MoneyReportHeader.tsx
+++ b/src/components/MoneyReportHeader.tsx
@@ -131,24 +131,17 @@ function MoneyReportHeaderContent({reportID: reportIDProp, shouldDisplayBackButt
shouldShowBorderBottom={false}
shouldEnableDetailPageNavigation
openParentReportInCurrentTab
- >
- {shouldShowHeaderButtonsInHeaderRow && (
+ shouldDisplayResponsiveChildrenInSeparateLine={!shouldShowHeaderButtonsInHeaderRow}
+ responsiveChildrenContainerStyle={!shouldShowHeaderButtonsInHeaderRow && styles.ph0}
+ responsiveChildren={
- )}
-
- {!shouldShowHeaderButtonsInHeaderRow && (
-
- )}
+ }
+ />
diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx
index def715741ef2..e05cec14fd15 100644
--- a/src/components/MoneyRequestHeader.tsx
+++ b/src/components/MoneyRequestHeader.tsx
@@ -178,13 +178,14 @@ function MoneyRequestHeader({reportID: reportIDProp, onBackButtonPress}: MoneyRe
onBackButtonPress={() => onBackButtonPress(isFromReviewDuplicates)}
shouldEnableDetailPageNavigation
openParentReportInCurrentTab={shouldOpenParentReportInCurrentTab}
- >
- {!shouldDisplayButtonsInSeparateLine && (
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={
- )}
+ }
+ >
{shouldDisplayTransactionNavigation && !!transaction && (
)}
- {shouldDisplayButtonsInSeparateLine && (
-
- )}
{!!statusBarProps && (
- {!shouldDisplayButtonsInSeparateLine && headerContent}
-
- {shouldDisplayButtonsInSeparateLine && !!headerContent && {headerContent}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={headerContent}
+ />
- {!shouldDisplayButtonsInSeparateLine && !!headerContent && {headerContent}}
-
- {shouldDisplayButtonsInSeparateLine && !!headerContent && {headerContent}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={!!headerContent && {headerContent}}
+ />
- {!shouldDisplayButtonsInSeparateLine && {createGroupHeaderButton}}
-
- {shouldDisplayButtonsInSeparateLine && {createGroupHeaderButton}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={createGroupHeaderButton}
+ />
- {!shouldDisplayButtonsInSeparateLine && hasRules && headerButton}
-
- {shouldDisplayButtonsInSeparateLine && hasRules && {headerButton}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={hasRules && headerButton}
+ />
{translate('expenseRulesPage.subtitle')}
diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index 6ee5d9799be5..2b561f1dbe8f 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -702,11 +702,10 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
const shouldDisplayButtonsInSeparateLine = useShouldDisplayButtonsInSeparateLine();
- const getHeaderButtons = () => {
- if (!canWriteMembers) {
- return null;
- }
- return (shouldUseNarrowLayout ? canSelectMultiple : selectedEmployees.length > 0) ? (
+ const shouldShowBulkActions = shouldUseNarrowLayout ? canSelectMultiple : selectedEmployees.length > 0;
+ let headerButtons = null;
+ if (canWriteMembers) {
+ headerButtons = shouldShowBulkActions ? (
variant={CONST.BUTTON_VARIANT.SUCCESS}
shouldAlwaysShowDropdownMenu
@@ -742,7 +741,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
/>
);
- };
+ }
const selectionModeHeader = isMobileSelectionModeEnabled && shouldUseNarrowLayout;
@@ -751,7 +750,8 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
headerText={selectionModeHeader ? translate('common.selectMultiple') : translate('workspace.common.members')}
route={route}
icon={!selectionModeHeader ? illustrations.ReceiptWrangler : undefined}
- headerContent={!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
+ headerContent={headerButtons}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
testID="WorkspaceMembersPage"
shouldShowLoading={false}
shouldUseHeadlineHeader={!selectionModeHeader}
@@ -769,7 +769,6 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
>
{() => (
<>
- {shouldDisplayButtonsInSeparateLine && {getHeaderButtons()}}
- {shouldDisplayButtonsInSeparateLine && {headerButtons}}
& {
+ Pick<
+ HeaderWithBackButtonProps,
+ | 'shouldShowThreeDotsButton'
+ | 'threeDotsMenuItems'
+ | 'shouldShowBackButton'
+ | 'onBackButtonPress'
+ | 'shouldDisplayResponsiveChildrenInSeparateLine'
+ | 'responsiveChildrenContainerStyle'
+ | 'bottomContent'
+ > & {
shouldSkipVBBACall?: boolean;
/** The text to display in the header */
@@ -146,6 +155,9 @@ function WorkspacePageWithSections({
shouldUseHeadlineHeader = true,
addBottomSafeAreaPadding = false,
modals,
+ shouldDisplayResponsiveChildrenInSeparateLine = false,
+ responsiveChildrenContainerStyle,
+ bottomContent,
}: WorkspacePageWithSectionsProps) {
const styles = useThemeStyles();
const policyID = route.params?.policyID;
@@ -246,9 +258,11 @@ function WorkspacePageWithSections({
threeDotsMenuItems={threeDotsMenuItems}
shouldUseHeadlineHeader={shouldUseHeadlineHeader}
shouldDisplayHelpButton
- >
- {headerContent}
-
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayResponsiveChildrenInSeparateLine}
+ responsiveChildrenContainerStyle={responsiveChildrenContainerStyle}
+ responsiveChildren={headerContent}
+ bottomContent={bottomContent}
+ />
{!isOffline && (isLoading || shouldShowInitialLoading) && shouldShowLoading && isFocused ? (
{
if (isMobileSelectionModeEnabled) {
clearTableSelection();
@@ -674,10 +675,8 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) {
Navigation.goBack();
}}
- >
- {!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
-
- {shouldDisplayButtonsInSeparateLine && !!getHeaderButtons() && {getHeaderButtons()}}
+ responsiveChildren={getHeaderButtons()}
+ />
{(!hasVisibleCategories || isLoading) && headerContent}
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index a09e16bfcdfa..68b77156ac90 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -470,10 +470,9 @@ function PolicyDistanceRatesPage({
}
Navigation.goBack();
}}
- >
- {!shouldDisplayButtonsInSeparateLine && headerButtons}
-
- {shouldDisplayButtonsInSeparateLine && !!headerButtons && {headerButtons}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={headerButtons}
+ />
{isLoading && (
- {!shouldShowSelector && !shouldDisplayButtonsInSeparateLine && isBankAccountVerified && shouldShowHeaderButtons && getHeaderButtons()}
-
- {!shouldShowSelector && shouldDisplayButtonsInSeparateLine && isBankAccountVerified && shouldShowHeaderButtons && {getHeaderButtons()}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={!shouldShowSelector && isBankAccountVerified && shouldShowHeaderButtons && getHeaderButtons()}
+ />
{shouldShowSelector && (
- {!shouldDisplayButtonsInSeparateLine && headerButtons}
-
- {!!headerButtons && shouldDisplayButtonsInSeparateLine && {headerButtons}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={headerButtons}
+ />
{(!hasVisibleSubRates || isLoading) && subtitleContent}
{isLoading && (
- {!shouldDisplayButtonsInSeparateLine && headerButtons}
-
- {shouldDisplayButtonsInSeparateLine && {headerButtons}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={headerButtons}
+ />
{translate('workspace.reportFields.listInputSubtitle')}
diff --git a/src/pages/workspace/rules/PolicyRulesPage.tsx b/src/pages/workspace/rules/PolicyRulesPage.tsx
index 3628e417bf5e..59d4c3265122 100644
--- a/src/pages/workspace/rules/PolicyRulesPage.tsx
+++ b/src/pages/workspace/rules/PolicyRulesPage.tsx
@@ -59,6 +59,7 @@ function PolicyRulesPage(props: PolicyRulesPageProps) {
const {canWrite: canWriteRules, showReadOnlyModal, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.RULES);
const {isBetaEnabled} = usePermissions();
const isRulesRevampEnabled = isBetaEnabled(CONST.BETAS.RULES_REVAMP);
+
const isCustomAgentBetaEnabled = isBetaEnabled(CONST.BETAS.CUSTOM_AGENT);
const [isAgentsRulesBannerDismissed = false] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {selector: agentsRulesBannerDismissedSelector});
diff --git a/src/pages/workspace/rules/PolicyRulesPageRevamp.tsx b/src/pages/workspace/rules/PolicyRulesPageRevamp.tsx
index a82020acb847..e298965e23dd 100644
--- a/src/pages/workspace/rules/PolicyRulesPageRevamp.tsx
+++ b/src/pages/workspace/rules/PolicyRulesPageRevamp.tsx
@@ -315,28 +315,29 @@ function PolicyRulesPageRevamp({route}: PolicyRulesPageRevampProps) {
shouldShowNotFoundPage={false}
shouldShowLoading={false}
addBottomSafeAreaPadding
- headerContent={!shouldDisplayButtonsInSeparateLine && headerButtons}
+ headerContent={headerButtons}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildrenContainerStyle={shouldDisplayButtonsInSeparateLine && styles.pb5}
+ bottomContent={
+
+
+ {
+ if (!isRulesTab(key)) {
+ return;
+ }
+ setSelectedRuleKeysByTab({});
+ turnOffMobileSelectionMode();
+ Tab.setSelectedTab(CONST.TAB.RULES_TAB_TYPE, key);
+ }}
+ />
+
+
+ }
>
-
-
-
- {
- if (!isRulesTab(key)) {
- return;
- }
- setSelectedRuleKeysByTab({});
- turnOffMobileSelectionMode();
- Tab.setSelectedTab(CONST.TAB.RULES_TAB_TYPE, key);
- }}
- />
-
-
-
- {shouldDisplayButtonsInSeparateLine && !!headerButtons && {headerButtons}}
{activeTab === RULES_TAB.GENERAL && (
- {!shouldDisplayButtonsInSeparateLine && headerButtons}
-
- {shouldDisplayButtonsInSeparateLine && !!headerButtons && {headerButtons}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={headerButtons}
+ />
{!hasDependentTags && (
- {!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
-
- {shouldDisplayButtonsInSeparateLine && !!getHeaderButtons() && {getHeaderButtons()}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={getHeaderButtons()}
+ />
{(!hasVisibleTags || isLoading) && headerContent}
{isLoading && (
- {!shouldDisplayButtonsInSeparateLine && headerButtons}
-
- {shouldDisplayButtonsInSeparateLine && !!headerButtons && {headerButtons}}
+ shouldDisplayResponsiveChildrenInSeparateLine={shouldDisplayButtonsInSeparateLine}
+ responsiveChildren={headerButtons}
+ />
{(!hasVisibleTaxes || isLoading) && headerContent}
{isLoading && (
width: '100%',
},
+ headerBarWithSeparateLine: {
+ height: 'auto',
+ flexWrap: 'wrap',
+ alignItems: 'flex-start',
+ paddingLeft: 0,
+ },
+
+ headerBarSeparateLineChildren: {
+ width: '100%',
+ paddingHorizontal: 20,
+ },
+
reportSearchHeaderBar: {
justifyContent: 'center',
display: 'flex',
diff --git a/tests/ui/WorkspaceMembersTest.tsx b/tests/ui/WorkspaceMembersTest.tsx
index 0b542bc18c65..6735df60a009 100644
--- a/tests/ui/WorkspaceMembersTest.tsx
+++ b/tests/ui/WorkspaceMembersTest.tsx
@@ -8,6 +8,7 @@ import OnyxListItemProvider from '@components/OnyxListItemProvider';
import {CurrentReportIDContextProvider} from '@hooks/useCurrentReportID';
import * as useResponsiveLayoutModule from '@hooks/useResponsiveLayout';
import type ResponsiveLayoutResult from '@hooks/useResponsiveLayout/types';
+import * as useShouldDisplayButtonsInSeparateLineModule from '@hooks/useShouldDisplayButtonsInSeparateLine';
import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
@@ -34,25 +35,34 @@ TestHelper.setupGlobalFetchMock();
const Stack = createPlatformStackNavigator();
+const getPage = (initialRouteName: typeof SCREENS.WORKSPACE.MEMBERS, initialParams: WorkspaceSplitNavigatorParamList[typeof SCREENS.WORKSPACE.MEMBERS]) => (
+
+
+
+
+
+
+
+
+
+);
+
const renderPage = (initialRouteName: typeof SCREENS.WORKSPACE.MEMBERS, initialParams: WorkspaceSplitNavigatorParamList[typeof SCREENS.WORKSPACE.MEMBERS]) => {
- return render(
-
-
-
-
-
-
-
-
- ,
- );
+ return render(getPage(initialRouteName, initialParams));
};
-const selectCheckboxByMemberName = (memberName: string) => {
+const defaultResponsiveLayout = {
+ isSmallScreenWidth: false,
+ shouldUseNarrowLayout: false,
+} as ResponsiveLayoutResult;
+let responsiveLayout = defaultResponsiveLayout;
+let shouldDisplayButtonsInSeparateLine = false;
+
+const getRowByMemberName = (memberName: string) => {
const memberEmailByName: Record = {
Owner: 'owner@gmail.com',
Admin: 'admin@example.com',
@@ -61,7 +71,11 @@ const selectCheckboxByMemberName = (memberName: string) => {
Self: 'test@example.com',
};
const displayName = memberName === 'Owner' || memberName === 'Self' ? memberName : `${memberName} User`;
- const row = screen.getByLabelText(new RegExp(`^${displayName}, ${memberEmailByName[memberName]}`));
+ return screen.getByLabelText(new RegExp(`^${displayName}, ${memberEmailByName[memberName]}`));
+};
+
+const selectCheckboxByMemberName = (memberName: string) => {
+ const row = getRowByMemberName(memberName);
fireEvent.press(within(row).getByLabelText(TestHelper.translateLocal('common.select')));
};
@@ -114,10 +128,10 @@ describe('WorkspaceMembers', () => {
});
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy);
});
- jest.spyOn(useResponsiveLayoutModule, 'default').mockReturnValue({
- isSmallScreenWidth: false,
- shouldUseNarrowLayout: false,
- } as ResponsiveLayoutResult);
+ responsiveLayout = defaultResponsiveLayout;
+ shouldDisplayButtonsInSeparateLine = false;
+ jest.spyOn(useResponsiveLayoutModule, 'default').mockImplementation(() => responsiveLayout);
+ jest.spyOn(useShouldDisplayButtonsInSeparateLineModule, 'default').mockImplementation(() => shouldDisplayButtonsInSeparateLine);
});
afterEach(async () => {
@@ -427,6 +441,35 @@ describe('WorkspaceMembers', () => {
});
describe('Removing members who are approvers and non-approvers', () => {
+ it('keeps the bulk menu action working after an orientation change', async () => {
+ const routeParams = {policyID: policy.id};
+ const {rerender, unmount} = renderPage(SCREENS.WORKSPACE.MEMBERS, routeParams);
+ await waitForBatchedUpdatesWithAct();
+ await screen.findByText(ADMIN_OPTION);
+
+ selectCheckboxByMemberName('Admin');
+ fireEvent.press(await screen.findByTestId('WorkspaceMembersPage-header-dropdown-menu-button'));
+ await waitForBatchedUpdatesWithAct();
+
+ const removeText = TestHelper.translateLocal('workspace.people.removeMembersTitle', {count: 1});
+ expect(screen.getByTestId(`PopoverMenuItem-${removeText}`)).toBeOnTheScreen();
+
+ shouldDisplayButtonsInSeparateLine = true;
+ rerender(getPage(SCREENS.WORKSPACE.MEMBERS, routeParams));
+
+ const removeMenuItem = await screen.findByTestId(`PopoverMenuItem-${removeText}`);
+ fireEvent.press(removeMenuItem, {
+ nativeEvent: {},
+ type: 'press',
+ target: removeMenuItem,
+ currentTarget: removeMenuItem,
+ });
+ await waitForBatchedUpdatesWithAct();
+
+ expect(await screen.findByLabelText(TestHelper.translateLocal('common.remove'))).toBeOnTheScreen();
+ unmount();
+ });
+
it('should call workflow actions once when removing multiple members including an approver', async () => {
const {unmount} = renderPage(SCREENS.WORKSPACE.MEMBERS, {policyID: policy.id});
await waitForBatchedUpdatesWithAct();
diff --git a/tests/ui/components/ButtonWithDropdownMenuTest.tsx b/tests/ui/components/ButtonWithDropdownMenuTest.tsx
index 15d7611fc431..18e74179b820 100644
--- a/tests/ui/components/ButtonWithDropdownMenuTest.tsx
+++ b/tests/ui/components/ButtonWithDropdownMenuTest.tsx
@@ -1,8 +1,11 @@
-import {fireEvent, render, renderHook, screen} from '@testing-library/react-native';
+import {fireEvent, render, renderHook, screen, waitFor} from '@testing-library/react-native';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import * as usePopoverPositionModule from '@hooks/usePopoverPosition';
+import * as useWindowDimensionsModule from '@hooks/useWindowDimensions';
import CONST from '@src/CONST';
@@ -127,3 +130,71 @@ describe('ButtonWithDropdownMenu (dropdown arrow flip)', () => {
expect(arrowIcon).not.toHaveStyle({transform: 'rotate(180deg)'});
});
});
+
+describe('ButtonWithDropdownMenu in a responsive header', () => {
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('stays open and keeps its action when moved to a separate line', () => {
+ const onSelected = jest.fn();
+ const options = [{value: 'action', text: 'Responsive action', onSelected, shouldCloseModalOnSelect: false}];
+ const renderHeader = (shouldDisplayResponsiveChildrenInSeparateLine: boolean) => (
+ {}}
+ customText="More"
+ shouldAlwaysShowDropdownMenu
+ isSplitButton={false}
+ />
+ }
+ />
+ );
+ const {rerender} = render(renderHeader(false));
+
+ fireEvent.press(screen.getByText('More'));
+ expect(screen.getByText('Responsive action')).toBeOnTheScreen();
+
+ rerender(renderHeader(true));
+ expect(screen.getByText('Responsive action')).toBeOnTheScreen();
+
+ const menuItem = screen.getByTestId('PopoverMenuItem-Responsive action');
+ fireEvent.press(menuItem, {
+ nativeEvent: {},
+ type: 'press',
+ target: menuItem,
+ currentTarget: menuItem,
+ });
+ expect(onSelected).toHaveBeenCalledTimes(1);
+ });
+
+ it('remeasures an open menu when the window dimensions change', async () => {
+ const calculatePopoverPosition = jest.fn().mockResolvedValue({horizontal: 100, vertical: 100, width: 40, height: 40});
+ let windowDimensions = {windowWidth: 800, windowHeight: 600};
+ jest.spyOn(usePopoverPositionModule, 'default').mockReturnValue({calculatePopoverPosition});
+ jest.spyOn(useWindowDimensionsModule, 'default').mockImplementation(() => windowDimensions);
+ const renderDropdown = () => (
+ {}}
+ customText="More"
+ shouldAlwaysShowDropdownMenu
+ isSplitButton={false}
+ />
+ );
+ const {rerender} = render(renderDropdown());
+
+ fireEvent.press(screen.getByText('More'));
+ await waitFor(() => expect(calculatePopoverPosition).toHaveBeenCalledTimes(1));
+
+ windowDimensions = {windowWidth: 600, windowHeight: 800};
+ rerender(renderDropdown());
+
+ await waitFor(() => expect(calculatePopoverPosition).toHaveBeenCalledTimes(2));
+ });
+});