Горячие клавиши и комбинации клавиш играют важную роль при разработке и тестировании React-приложений. Они позволяют эмулировать пользовательское взаимодействие с интерфейсом без необходимости прямого клика мышью. В контексте React Testing Library (RTL) это означает возможность имитации нажатий клавиш на элементах, что критично для проверки поведения компонентов, управляемых с клавиатуры.
В RTL основной инструмент для работы с клавиатурой — утилита
fireEvent и более современный userEvent из
пакета @testing-library/user-event.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import MyComponent from './MyComponent';
test('симуляция нажатия клавиши Enter', async () => {
render( );
const input = screen.getByRole('textbox');
await userEvent.type(input, '{enter}');
expect(screen.getByText('Отправлено')).toBeInTheDocument();
});
Ключевые моменты:
{enter}, {tab}, {backspace} и
другие специальные клавиши заключаются в фигурные скобки.userEvent.type автоматически эмулирует фокус и
последовательность событий (keydown, keypress,
input, keyup).Комбинации клавиш (например, Ctrl + S или
Shift + Tab) требуют указания модификаторов.
userEvent.keyboard позволяет передавать такие комбинации
через синтаксис с модификаторами [ и ].
test('комбинация Ctrl + A выделяет текст', async () => {
render();
const input = screen.getByRole('textbox');
input.focus();
await userEvent.keyboard('[Control>a]');
expect(input.selectionStart).toBe(0);
expect(input.selectionEnd).toBe(input.value.length);
});
Модификаторы, поддерживаемые RTL:
Control (Ctrl)ShiftAltMeta (Cmd на macOS)Синтаксис [Modifier1+Modifier2+Key] позволяет
эмулировать одновременное нажатие нескольких клавиш.
При симуляции клавиш важно понимать, какие события создаются:
или .userEvent автоматически воспроизводит эту
последовательность, тогда как fireEvent требует ручного
вызова каждого события:
import { fireEvent } from '@testing-library/react';
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter', charCode: 13 });
fireEvent.keyUp(input, { key: 'Enter', code: 'Enter', charCode: 13 });
Навигация с помощью клавиатуры — важный аспект доступности. RTL
позволяет проверять перемещение фокуса с помощью клавиши
Tab:
test('перемещение фокуса с Tab', async () => {
render(
<>
>
);
const [button1, button2] = screen.getAllByRole('button');
button1.focus();
await userEvent.tab();
expect(button2).toHaveFocus();
});
Особенности:
userEvent.tab() перемещает фокус на следующий
фокусируемый элемент.userEvent.tab({ shift: true }) — перемещение в обратном
порядке (Shift + Tab).Для клавиш вроде Escape, ArrowUp,
ArrowDown также используется синтаксис {Key}
или [Modifier+Key]. Примеры:
await userEvent.keyboard('{Escape}');
await userEvent.keyboard('[Shift+ArrowUp]');
Важно указывать точные имена клавиш, совпадающие с
KeyboardEvent.key.
userEvent вместо
fireEvent для более реалистичной эмуляции
пользователя.Разные браузеры по-разному обрабатывают сочетания клавиш. RTL старается имитировать нативное поведение, но есть нюансы:
Meta на macOS соответствует Control на
Windows. и
по-разному в зависимости от типа
элемента.Ctrl+Z) может
требовать дополнительной проверки состояния компонента.Хоткей для сохранения формы:
test('сохранение формы через Ctrl+S', async () => {
const handleSave = jest.fn();
render();
const input = screen.getByRole('textbox');
input.focus();
await userEvent.keyboard('[Control+s]');
expect(handleSave).toHaveBeenCalled();
});
Навигация и выбор элементов с клавиатуры:
test('выбор элемента списка с помощью ArrowDown и Enter', async () => {
render(
- Элемент 1
- Элемент 2
);
const items = screen.getAllByRole('listitem');
items[0].focus();
await userEvent.keyboard('{ArrowDown}');
expect(items[1]).toHaveFocus();
await userEvent.keyboard('{Enter}');
expect(screen.getByText('Элемент 2 выбран')).toBeInTheDocument();
});
Эти примеры демонстрируют интеграцию клавиатурного взаимодействия в реальные сценарии тестирования React-компонентов.