Skip to content

Commit 5a55a01

Browse files
author
叶文俊
committed
test: add unit tests for focus scenarios with and without selection support
1 parent 27b456e commit 5a55a01

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

tests/Focus.spec.tsx

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* eslint-disable no-undef */
22
import { act, fireEvent, render } from '@testing-library/react';
33
import { spyElementPrototypes } from '@rc-component/util/lib/test/domHook';
4+
import KeyCode from '@rc-component/util/lib/KeyCode';
45
import React from 'react';
56
import Menu, { MenuItem, MenuItemGroup, MenuRef, SubMenu } from '../src';
7+
import { isActive } from './util';
68

79
describe('Focus', () => {
810
beforeAll(() => {
@@ -26,6 +28,24 @@ describe('Focus', () => {
2628
jest.useRealTimers();
2729
});
2830

31+
function keyDown(container: HTMLElement, keyCode: number) {
32+
fireEvent.keyDown(container.querySelector('ul.rc-menu-root'), {
33+
which: keyCode,
34+
keyCode,
35+
charCode: keyCode,
36+
});
37+
38+
// SubMenu raf need slow than accessibility
39+
for (let i = 0; i < 20; i += 1) {
40+
act(() => {
41+
jest.advanceTimersByTime(10);
42+
});
43+
}
44+
act(() => {
45+
jest.runAllTimers();
46+
});
47+
}
48+
2949
it('Get focus', async () => {
3050
const { container } = await act(async () =>
3151
render(
@@ -186,5 +206,98 @@ describe('Focus', () => {
186206
expect(document.activeElement).toBe(getByTitle('Submenu'));
187207
expect(getByTestId('sub-menu')).toHaveClass('rc-menu-submenu-active');
188208
});
209+
210+
it('When selectable is not configured, the focus should move to the first available item instead of keeping the previously focused item', async () => {
211+
const menuRef = React.createRef<MenuRef>();
212+
const items = [
213+
{ key: '0', label: 'First Item' },
214+
{ key: '1', label: 'Second Item' },
215+
{ key: '2', label: 'Third Item' },
216+
];
217+
const TestApp = () => {
218+
return (
219+
<div>
220+
<Menu data-testid="menu" selectable={false} ref={menuRef}>
221+
{items.map(item => (
222+
<MenuItem key={item.key} data-testid={item.key}>
223+
{item.label}
224+
</MenuItem>
225+
))}
226+
</Menu>
227+
</div>
228+
);
229+
};
230+
const { getByTestId, container } = render(<TestApp />);
231+
// ================ check keydown ==============
232+
// first item
233+
keyDown(container, KeyCode.DOWN);
234+
isActive(container, 0);
235+
// second item
236+
keyDown(container, KeyCode.DOWN);
237+
isActive(container, 1);
238+
// select second item
239+
keyDown(container, KeyCode.ENTER);
240+
241+
// mock focus on item 0 to make sure it gets focused
242+
const item0 = getByTestId('0');
243+
const focusSpy = jest.spyOn(item0, 'focus').mockImplementation(() => {});
244+
menuRef.current.focus();
245+
expect(focusSpy).toHaveBeenCalled();
246+
247+
// ================ check click ==============
248+
// click third item
249+
const item2 = getByTestId('2');
250+
fireEvent.click(item2);
251+
menuRef.current.focus();
252+
expect(focusSpy).toHaveBeenCalled();
253+
// cleanup
254+
focusSpy.mockRestore();
255+
});
256+
it('When selectable is configured, the focus should move to the selected item if there is a selection, else to the first item, not retain on last focused item', async () => {
257+
const menuRef = React.createRef<MenuRef>();
258+
const items = [
259+
{ key: '0', label: 'First Item' },
260+
{ key: '1', label: 'Second Item' },
261+
{ key: '2', label: 'Third Item' },
262+
];
263+
const TestApp = () => {
264+
return (
265+
<div>
266+
<Menu data-testid="menu" selectable ref={menuRef}>
267+
{items.map(item => (
268+
<MenuItem key={item.key} data-testid={item.key}>
269+
{item.label}
270+
</MenuItem>
271+
))}
272+
</Menu>
273+
</div>
274+
);
275+
};
276+
const { getByTestId, container } = render(<TestApp />);
277+
// ================ check keydown ==============
278+
// first item
279+
keyDown(container, KeyCode.DOWN);
280+
isActive(container, 0);
281+
// second item
282+
keyDown(container, KeyCode.DOWN);
283+
isActive(container, 1);
284+
// select second item
285+
keyDown(container, KeyCode.ENTER);
286+
// mock focus on item 1 to make sure it gets focused
287+
const item1 = getByTestId('1');
288+
const focusSpy = jest.spyOn(item1, 'focus').mockImplementation(() => {});
289+
menuRef.current.focus();
290+
expect(focusSpy).toHaveBeenCalled();
291+
292+
// ================ check click ==============
293+
// click third item
294+
const item2 = getByTestId('2');
295+
fireEvent.click(item2);
296+
menuRef.current.focus();
297+
// mock focus on item 2 to make sure it gets focused
298+
expect(focusSpy).toHaveBeenCalled();
299+
// cleanup
300+
focusSpy.mockRestore();
301+
});
189302
});
190303
/* eslint-enable */

0 commit comments

Comments
 (0)