view --main tdesign-test-component-skill-dlya-testirovaniya-react-komponentov.md
tdesign-test-component: Скилл для тестирования React компонентов
readonly
--- lines
---
name: tdesign-test-component
description: This skill should be used when writing or maintaining unit tests for TDesign React components. It provides testing patterns, best practices, and SOP for Vitest-based component testing including snapshot tests.
---
# Руководство по тестированию компонентов TDesign
Этот документ предоставляет полное руководство и лучшие практики для модульного тестирования компонентов TDesign React.
## Условия активации
Используйте этот инструмент, когда вам необходимо:
- Написать модульные тесты для компонента.
- Обновить или исправить существующие тесты.
- Запустить тесты со снимками.
- Повысить покрытие тестами.
## Фреймворки и инструменты для тестирования
| Инструмент | Назначение |
|---|---|
| Vitest | Тестовый фреймворк |
| @testing-library/react | Инструмент для тестирования React-компонентов |
| @testing-library/user-event | Эмуляция взаимодействия пользователя |
| @testing-library/jest-dom | Расширения для утверждений DOM |
## Стандарты файлов тестов
### Расположение и наименование файлов
```
packages/components/[название-компонента]/
└── __tests__/
├── vitest-[название-компонента].test.jsx # Модульные тесты
└── __snapshots__/ # Файлы снимков (генерируются автоматически)
```
**Формат наименования:** `vitest-[название-компонента].test.jsx`
⚠️ **Внимание:** Файлы тестов генерируются платформой API и содержат комментарии-маркеры в заголовке.
### Импорт инструментов тестирования
```javascript
import { render, fireEvent, vi } from '@test/utils';
import { ComponentName } from '..';
```
`@test/utils` содержит часто используемые инструменты, включая:
- `render` - Рендеринг компонента
- `fireEvent` - Эмуляция событий
- `vi` - Инструменты мокирования Vitest
- `act` - Обертка React для асинхронных операций
- `userEvent` - Эмуляция взаимодействия пользователя
- `mockDelay` - Эмуляция асинхронной задержки
- `simulateInputChange` - Эмуляция ввода
- `simulateKeydownEvent` - Эмуляция нажатия клавиш
## Процесс (SOP)
### Шаг 1: Базовое тестирование рендеринга
Проверьте, правильно ли компонент отображается:
```javascript
describe('ExampleComponent', () => {
it('отображается корректно', () => {
const { container } = render(<ExampleComponent />);
expect(container.firstChild).toHaveClass('t-example-component');
});
});
```
### Шаг 2: Тестирование props
Напишите тестовые примеры для каждого prop:
```javascript
// Пример тестирования boolean prop
it('props.disabled работает корректно', () => {
// Тестирование значения по умолчанию
const { container: container1 } = render(<Button>Text</Button>);
expect(container1.querySelector('.t-is-disabled')).toBeFalsy();
// disabled = true
const { container: container2 } = render(<Button disabled={true}>Text</Button>);
expect(container2.firstChild).toHaveClass('t-is-disabled');
expect(container2).toMatchSnapshot();
// disabled = false
const { container: container3 } = render(<Button disabled={false}>Text</Button>);
expect(container3.querySelector('.t-is-disabled')).toBeFalsy();
});
// Пример тестирования enum prop
['small', 'medium', 'large'].forEach((item) => {
it(`props.size равен ${item}`, () => {
const { container } = render(<Button size={item}>Text</Button>);
// medium - значение по умолчанию, не добавляем дополнительные классы
if (item !== 'medium') {
expect(container.firstChild).toHaveClass(`t-size-${item[0]}`);
}
expect(container).toMatchSnapshot();
});
});
```
### Шаг 3: Тестирование рендеринга TNode
Проверьте пользовательский рендеринг:
```javascript
it('props.children работает корректно', () => {
const { container } = render(
<Button>
<span className="custom-node">TNode</span>
</Button>
);
expect(container.querySelector('.custom-node')).toBeTruthy();
expect(container).toMatchSnapshot();
});
it('props.icon работает корректно', () => {
const { container } = render(
<Button icon={<span className="custom-icon">Icon</span>}>Text</Button>
);
expect(container.querySelector('.custom-icon')).toBeTruthy();
});
```
### Шаг 4: Тестирование событий
Проверьте вызов обратных функций для событий:
```javascript
it('events.click работает корректно', () => {
const fn = vi.fn();
const { container } = render(<Button onClick={fn}>Click</Button>);
fireEvent.click(container.firstChild);
expect(fn).toHaveBeenCalled();
expect(fn.mock.calls[0][0].type).toBe('click');
});
// Событие не должно вызываться, если кнопка отключена
it('отключенная кнопка не должна вызывать клик', () => {
const fn = vi.fn();
const { container } = render(<Button disabled onClick={fn}>Click</Button>);
fireEvent.click(container.firstChild);
expect(fn).not.toHaveBeenCalled();
});
```
### Шаг 5: Тестирование асинхронных операций
Проверьте асинхронное поведение:
```javascript
import { mockDelay } from '@test/utils';
it('асинхронная операция работает корректно', async () => {
const { container } = render(<AsyncComponent />);
// Запускаем асинхронную операцию
fireEvent.click(container.querySelector('.trigger'));
// Ждем завершения асинхронной операции
await mockDelay(300);
expect(container.querySelector('.result')).toBeTruthy();
});
```
### Шаг 6: Тестирование взаимодействия пользователя
Используйте `userEvent` для сложных тестов взаимодействия:
```javascript
import { userEvent } from '@test/utils';
it('ввод пользователя работает корректно', async () => {
const user = userEvent.setup();
const onChange = vi.fn();
const { container } = render(<Input onChange={onChange} />);
const input = container.querySelector('input');
await user.type(input, 'hello');
expect(onChange).toHaveBeenCalled();
expect(input.value).toBe('hello');
});
```
## Тесты со снимками
### CSR (Client-Side Rendering) тесты со снимками
Расположение: `test/snap/csr.test.jsx`
Автоматически генерируются снимки для всех файлов `_example/*.tsx`:
```bash
# Запуск CSR тестов со снимками
NODE_ENV=test-snap pnpm test
```
### SSR (Server-Side Rendering) тесты со снимками
Расположение: `test/snap/ssr.test.jsx`
Тестирование рендеринга на сервере.
### Обновление снимков
```bash
# Обновление всех снимков
pnpm test -- --update
# Обновление снимков для конкретного компонента
pnpm test button -- --update
```
## Команды для запуска тестов
```bash
# Запуск всех модульных тестов
pnpm test
# Запуск тестов для конкретного компонента
pnpm test button
# Запуск тестов с генерацией отчета о покрытии
pnpm test -- --coverage
# Запуск тестов со снимками
NODE_ENV=test-snap pnpm test
# Интерактивный режим тестирования
pnpm test -- --ui
```
## Распространенные шаблоны тестирования
### Тестирование состояния загрузки
```javascript
it('состояние загрузки отображает индикатор загрузки', () => {
const { container } = render(<Button loading>Text</Button>);
expect(container.firstChild).toHaveClass('t-is-loading');
expect(container.querySelector('.t-loading')).toBeTruthy();
});
```
### Тестирование атрибутов DOM
```javascript
it('атрибут href работает корректно', () => {
const { container } = render(<Button href="https://example.com">Link</Button>);
expect(container.firstChild.getAttribute('href')).toBe('https://example.com');
expect(container.firstChild.tagName.toLowerCase()).toBe('a');
});
```
### Тестирование комбинаций классов
```javascript
it('пользовательский класс добавляется', () => {
const { container } = render(<Button className="custom-class">Text</Button>);
expect(container.firstChild).toHaveClass('t-button');
expect(container.firstChild).toHaveClass('custom-class');
});
```
### Мокирование ResizeObserver
```javascript
class ResizeObserver {
observe() { return this; }
unobserve() { return this; }
}
beforeAll(() => {
global.ResizeObserver = ResizeObserver;
});
```
### Мокирование времени
```javascript
import MockDate from 'mockdate';
beforeEach(() => {
MockDate.set('2020-12-28 00:00:00');
});
afterEach(() => {
MockDate.reset();
});
```
## Чек-лист для тестирования
При написании тестов убедитесь, что они охватывают:
- [ ] Базовое отображение
- [ ] Все boolean props (значения true/false)
- [ ] Все значения enum props
- [ ] TNode типы props
- [ ] Вызов обратных функций для событий
- [ ] Поведение в отключенном состоянии
- [ ] Состояние загрузки
- [ ] Граничные случаи (пустые значения, экстремальные значения)
- [ ] Тесты со снимками
## Требования к покрытию тестами
- Общая цель покрытия: > 80%
- Новые компоненты: > 90% построчного покрытия
- Основная логика: 100% ветвления
## Часто задаваемые вопросы
### В: Можно ли редактировать файлы тестов вручную?
A: Файлы `vitest-*.test.jsx` генерируются платформой API и содержат комментарии-маркеры в заголовке. Вы можете добавлять дополнительные тесты на основе этих файлов, но основное тестирование должно поддерживаться платформой API.
### В: Как обрабатывать асинхронные компоненты?
A: Используйте `mockDelay` или `act wrapper`, чтобы убедиться, что асинхронные операции завершены, прежде чем выполнять утверждения.
### В: Что делать, если тест со снимком не проходит?
A: Сначала проверьте, являются ли изменения ожидаемыми. Если изменения ожидаемые, обновите снимок с помощью параметра `--update`.
Инициализация мануала...
//
$ ls -R related_skills/
2026-04-08
⭐ 3467
build-prevail: Скилл для проверки и тестирования eBPF
2026-04-08
⭐ 348
130-java-testing-strategies: Скилл для автоматизации тестирования Java
2026-04-09
⭐ 10126
skill-tester: Тестирование и оценка навыков
2026-03-28
⭐ 28101
performance-testing-review-ai-review — Автоматизированный AI-инструмент для проверки кода
package.json
$ install --global
skills.sh
npx skills add https://github.com/Tencent/tdesign-react/tree/develop/.codebuddy/skills/tdesign-test-component
$ download --local
man
[HINT] Скачивает всю директорию скилла с GitHub: SKILL.md и все связанные файлы