diff --git a/packages/react/src/components/tabs/tabs.test.tsx b/packages/react/src/components/tabs/tabs.test.tsx
index 41721e8fc1..e83211e8a7 100644
--- a/packages/react/src/components/tabs/tabs.test.tsx
+++ b/packages/react/src/components/tabs/tabs.test.tsx
@@ -2,7 +2,12 @@ import { ReactWrapper } from 'enzyme';
import ReactDOM from 'react-dom';
import { findByTestId, getByTestId } from '../../test-utils/enzyme-selectors';
import { expectFocusToBeOn } from '../../test-utils/enzyme-utils';
-import { mountWithProviders, mountWithTheme, renderWithProviders } from '../../test-utils/renderer';
+import {
+ actAndWaitForEffects,
+ mountWithProviders,
+ mountWithTheme,
+ renderWithProviders,
+} from '../../test-utils/renderer';
import { Tab, Tabs } from './tabs';
function givenTabs(amount: number): Tab[] {
@@ -82,44 +87,52 @@ describe('Tabs', () => {
expect(getByTestId(wrapper, 'tab-panel-1').exists()).toBe(false);
});
- test('tab panel should not change if onBeforeUnload cancels tab selection', () => {
+ test('tab panel should not change if onBeforeUnload cancels tab selection', async () => {
const tabs: Tab[] = givenTabs(2);
- const shouldConfirmTabUnload = false;
+ const shouldConfirmTabUnload = Promise.resolve(false);
tabs[0] = {
...tabs[0],
onBeforeUnload: () => shouldConfirmTabUnload,
};
const wrapper = mountWithProviders();
- getByTestId(wrapper, 'tab-button-2').simulate('click');
+ await actAndWaitForEffects(wrapper, () => {
+ getByTestId(wrapper, 'tab-button-2').prop('onClick')();
+ });
- expectPanelToBeRendered(wrapper, 'tab-panel-1');
+ expect(getByTestId(wrapper, 'tab-panel-1').exists()).toBe(true);
});
- test('tab panel should change if no onBeforeUnload callback was provided', () => {
+ test('tab panel should change if no onBeforeUnload callback was provided', async () => {
const tabs: Tab[] = givenTabs(2);
tabs[0] = {
...tabs[0],
};
const wrapper = mountWithProviders();
- getByTestId(wrapper, 'tab-button-2').simulate('click');
+ await actAndWaitForEffects(wrapper, () => {
+ const tabButton = getByTestId(wrapper, 'tab-button-2');
+ tabButton.prop('onClick')();
+ });
- expectPanelToBeRendered(wrapper, 'tab-panel-2');
+ expect(getByTestId(wrapper, 'tab-panel-2').exists()).toBeTruthy();
});
- test('tab panel should change if onBeforeUnload confirms tab selection', () => {
+ test('tab panel should change if onBeforeUnload confirms tab selection', async () => {
const tabs: Tab[] = givenTabs(2);
- const shouldConfirmTabOnClick = true;
+ const shouldConfirmTabOnClick = Promise.resolve(true);
tabs[0] = {
...tabs[0],
onBeforeUnload: () => shouldConfirmTabOnClick,
};
const wrapper = mountWithProviders();
- getByTestId(wrapper, 'tab-button-2').simulate('click');
+ await actAndWaitForEffects(wrapper, () => {
+ const tabButton2 = getByTestId(wrapper, 'tab-button-2');
+ tabButton2.prop('onClick')();
+ });
- expectPanelToBeRendered(wrapper, 'tab-panel-2');
+ expect(getByTestId(wrapper, 'tab-panel-2').exists()).toBeTruthy();
});
test('tab-panels should all be initially mounted when forceRenderTabPanels is set to true', () => {
diff --git a/packages/react/src/components/tabs/tabs.tsx b/packages/react/src/components/tabs/tabs.tsx
index 32df277e9c..4ecc3d88e2 100644
--- a/packages/react/src/components/tabs/tabs.tsx
+++ b/packages/react/src/components/tabs/tabs.tsx
@@ -26,14 +26,14 @@ export interface Tab {
leftIcon?: IconName;
rightIcon?: IconName;
panelContent: ReactNode;
- onBeforeUnload?: () => boolean;
+ onBeforeUnload?(): Promise;
}
interface TabItem extends Tab {
id: string;
panelId: string;
buttonRef: RefObject;
- onBeforeUnload?: () => boolean;
+ onBeforeUnload?(): Promise;
}
interface Props {
@@ -58,9 +58,10 @@ export const Tabs: VoidFunctionComponent = ({
), [tabs]);
const [selectedTab, setSelectedTab] = useState(tabItems[0]);
- function handleTabSelected(tabItem: TabItem): void {
+ async function handleTabSelected(tabItem: TabItem): Promise {
if (selectedTab?.onBeforeUnload) {
- if (selectedTab.onBeforeUnload?.()) {
+ const isConfirmed = await selectedTab.onBeforeUnload();
+ if (isConfirmed) {
setSelectedTab(tabItem);
}
} else {
diff --git a/packages/storybook/stories/tabs.stories.tsx b/packages/storybook/stories/tabs.stories.tsx
index bec2d718fa..11e05bfc5c 100644
--- a/packages/storybook/stories/tabs.stories.tsx
+++ b/packages/storybook/stories/tabs.stories.tsx
@@ -169,28 +169,22 @@ export const Contained: Story = () => {
export const UnloadTabCallback: Story = () => {
const tabs: Tab[] = [
{
- title: 'First Button',
+ title: 'Tab that cannot change because onBeforeUnload resolves to false',
panelContent: First tab content,
onBeforeUnload: () => {
- console.info('cannot change tab because callback return false');
- return false;
+ console.info('cannot change tab because onBeforeUnload promise resolves to false here');
+ return Promise.resolve(false);
},
},
{
title: 'Second Button',
panelContent: Second tab content,
- onBeforeUnload: () => {
- console.info('second tab unload confirmed');
- return true;
- },
+ onBeforeUnload: () => Promise.resolve(true),
},
{
title: 'Third Button',
panelContent: Third tab content,
- onBeforeUnload: () => {
- console.info('third tab unload confirmed');
- return true;
- },
+ onBeforeUnload: () => Promise.resolve(true),
},
];