Skip to content

Commit c3d3c38

Browse files
committed
adds test
1 parent ae911bc commit c3d3c38

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

tests/Menu.spec.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { act } from 'react-dom/test-utils';
88
import type { MenuRef } from '../src';
99
import Menu, { Divider, MenuItem, MenuItemGroup, SubMenu } from '../src';
1010
import { isActive, last } from './util';
11+
import { spyElementPrototypes } from '@rc-component/util/lib/test/domHook';
1112

1213
jest.mock('@rc-component/trigger', () => {
1314
const react = require('react');
@@ -790,5 +791,73 @@ describe('Menu', () => {
790791
expect(catItem).toBe(container.querySelectorAll('li')[1]);
791792
expect(nonExistentItem).toBe(null);
792793
});
794+
795+
it('should correctly handle invalid mergedActiveKey and fallback to focusable elements', async () => {
796+
// Mock to force make menu item visible
797+
spyElementPrototypes(HTMLElement, {
798+
offsetParent: {
799+
get() {
800+
return this.parentElement;
801+
},
802+
},
803+
});
804+
805+
const menuRef = React.createRef<MenuRef>();
806+
const focusSpy = jest.fn();
807+
808+
const TestApp = () => {
809+
const [items, setItems] = React.useState([
810+
{ key: 'item1', label: 'First Item' },
811+
{ key: 'item2', label: 'Second Item' },
812+
{ key: 'item3', label: 'Third Item' },
813+
]);
814+
815+
const removeSecondItem = () => {
816+
setItems(prevItems => prevItems.filter(item => item.key !== 'item2'));
817+
};
818+
819+
return (
820+
<div>
821+
<Menu data-testid="menu" activeKey="item2" tabIndex={0} ref={menuRef}>
822+
{items.map(item => (
823+
<MenuItem key={item.key} data-testid={item.key}>
824+
{item.label}
825+
</MenuItem>
826+
))}
827+
</Menu>
828+
<button data-testid="remove-button" onClick={removeSecondItem} tabIndex={0}>
829+
Remove Second Item
830+
</button>
831+
</div>
832+
);
833+
};
834+
835+
const { getByTestId } = await act(async () => render(<TestApp />));
836+
837+
const removeButton = getByTestId('remove-button');
838+
839+
// Verify initial state - item2 should be active
840+
expect(getByTestId('item2')).toHaveClass('rc-menu-item-active');
841+
842+
// Remove the active item (item2)
843+
await act(async () => {
844+
fireEvent.click(removeButton);
845+
});
846+
847+
// Verify the item is removed
848+
expect(() => getByTestId('item2')).toThrow();
849+
850+
// mock focus on item 1 to make sure it gets focused
851+
const item1 = getByTestId('item1');
852+
item1.focus = focusSpy;
853+
854+
// when we call focus(), it should properly handle the case where
855+
// mergedActiveKey ("item2") no longer exists
856+
await act(async () => {
857+
menuRef.current.focus();
858+
});
859+
860+
expect(focusSpy).toHaveBeenCalled();
861+
});
793862
});
794863
/* eslint-enable */

0 commit comments

Comments
 (0)