docs(frontend): complete debt backlog features with test conventions

This commit is contained in:
Sergey Krylov 2026-06-24 08:51:42 +03:00
parent 9ad0f571d5
commit d529d51612
10 changed files with 182 additions and 68 deletions

View File

@ -39,17 +39,68 @@ npm run test:watch -w apps/backend
## Тесты frontend ## Тесты frontend
Фреймворк: **Vitest 4** + **React Testing Library** + **MSW**. Фреймворк: **Vitest** + **React Testing Library** + **MSW**.
Запуск: ### Запуск
```bash ```bash
npm run test:frontend npm run test:frontend # все тесты
# или npm run test -w apps/frontend # или напрямую
npm run test -w apps/frontend npx vitest run apps/frontend/src/pages/profile/ProfilePage.test.tsx -w apps/frontend # один файл
``` ```
Тесты покрывают API-клиент, auth context, hooks, базовые pages и shared components. ### Helpers (`src/shared/lib/test/`)
| Файл | Назначение |
|---|---|
| `test-utils.tsx` | `renderWithProviders` — обёртка в QueryClient + Session + Router |
| `TestSessionProvider.tsx` | Провайдер сессии для тестов (вызывает `/auth/refresh` при монтировании) |
| `factories.ts` | Фабрики mock-данных (`createMockShare`, `createMockBond` и др.) |
| `setup.ts` | Глобальный setup: jest-dom, MSW lifecycle, jsdom polyfills |
| `README.md` | Конвенции и правила тестирования |
### Шаблоны
**Компонент без auth/routing** — просто `render` + фабрика:
```tsx
import { render, screen } from '@testing-library/react'
import { createMockShare } from '@/shared/lib/test/factories'
const stock = createMockShare()
render(<StockDetails stock={stock} />)
expect(screen.getByText('Сбер (SBER)')).toBeInTheDocument()
```
**Компонент с auth/Router** — `renderWithProviders`:
```tsx
import { renderWithProviders } from '@/shared/lib/test/test-utils'
renderWithProviders(<ProfilePage />, { route: '/profile' })
```
**Ошибка API** — переопределить MSW handler:
```ts
server.use(
http.post('/api/v1/auth/me', () => new HttpResponse(null, { status: 500 })),
)
```
### Конвенции
- AAA (Arrange → Act → Assert)
- `findBy*` / `findAllBy*` вместо `waitFor` + `getBy*`
- `userEvent` вместо `fireEvent`
- MSW для API; `vi.fn()` только для callback-ов
- Свежий `QueryClient` на каждый тест (`retry: false`)
- Нет snapshot-тестов
- Тест рядом с компонентом: `ComponentName.test.tsx` рядом с `ComponentName.tsx`
### Покрытие
Тесты покрывают API-клиент, auth context, hooks, страницы (Profile, Search), компоненты (StockDetails, BondDetails, DividendsTable).
## Тесты design system ## Тесты design system

View File

@ -1,9 +1,75 @@
# Tests # Frontend Testing Conventions
## Common issues ## Helpers
### Auth loading screen ### renderWithProviders (`test-utils.tsx`)
Components rendered through `renderWithProviders` are wrapped in AuthProvider which shows
a loading screen until `POST /api/v1/auth/refresh` resolves. Wraps component in `QueryClientProvider` + `TestSessionProvider` + `RouterProvider`.
- Use `await screen.findByText()` to wait for auth to complete.
- For components that don't need auth, render with just QueryClientProvider + MemoryRouter. Use for components that depend on auth or routing.
```ts
import { renderWithProviders } from '@/shared/lib/test/test-utils'
renderWithProviders(<ProfilePage />, { route: '/profile' })
```
Options: `queryClient` (fresh by default with `retry: false`), `route` (default `/`).
### Plain render
For components that only need factory data (no auth, no query):
```ts
import { render } from '@testing-library/react'
render(<StockDetails stock={createMockShare()} />)
```
### TestSessionProvider (`TestSessionProvider.tsx`)
Calls `POST /api/v1/auth/refresh` on mount. Always resolves successfully via MSW by default.
Override by adding a `server.use()` before rendering.
### Factories (`factories.ts`)
| Factory | Returns |
|---|---|
| `createMockShare(overrides?)` | `ShareResponse` |
| `createMockBond(overrides?)` | `BondResponse` |
| `createMockUser(overrides?)` | `UserResponse` |
| `createMockAuth(overrides?)` | `AuthResponse` |
| `createMockMarketData(overrides?)` | `StockMarketData` |
| `createMockBondMarketData(overrides?)` | `BondMarketData` |
| `createMockCandles(count?)` | `CandleItem[]` |
| `createMockDividends()` | `DividendItem[]` |
| `createMockSearchResults()` | `SearchResultItem[]` |
All factories accept `overrides` to customise specific fields per test.
## Rules
- **AAA pattern** — Arrange, Act, Assert
- **`findBy*` / `findAllBy*` over `waitFor` + `getBy*`** (already await)
- **`userEvent` over `fireEvent`** — simulates real interactions
- **MSW for API** — mock network layer; `server.use()` per test for error cases
- **`vi.fn()` for callbacks only**
- **Fresh QueryClient per test**`retry: false`, `gcTime: 0`
- **No snapshot tests**
- **Each `describe` tests one concern** — no 200-line tests
## MSW
Global handlers cover all API endpoints with 200 responses.
Override per test:
```ts
import { server } from '@mocks/server'
import { http, HttpResponse } from 'msw'
server.use(
http.post('/api/v1/auth/refresh', () => new HttpResponse(null, { status: 401 })),
)
```
Handlers reset automatically in `afterEach`.

View File

@ -1,6 +1,6 @@
# Frontend Debt Backlog # Frontend Debt Backlog
Статус: запланировано Статус: завершено
Порядок реализации: Порядок реализации:
@ -12,6 +12,6 @@
Features: Features:
- [ ] [frontend-debt-audit](../features/frontend-debt-audit/spec.md) — аудит frontend-техдолга и приоритизация backlog - [ ] [frontend-debt-audit](../features/frontend-debt-audit/spec.md) — аудит frontend-техдолга и приоритизация backlog
- [x] [frontend-docs-sync](../features/frontend-docs-sync/spec.md) — синхронизация inbox/roadmap и устаревшей frontend-документации - [x] [frontend-docs-sync](../features/frontend-docs-sync/spec.md) — синхронизация inbox/roadmap и устаревшей frontend-документации
- [ ] [frontend-infrastructure-hardening](../features/frontend-infrastructure-hardening/spec.md) — завершение infrastructure/tooling debt - [x] [frontend-infrastructure-hardening](../features/frontend-infrastructure-hardening/spec.md) — завершение infrastructure/tooling debt
- [ ] [frontend-shared-boundary-cleanup](../features/frontend-shared-boundary-cleanup/spec.md) — сужение shared/public API и границ слоёв - [x] [frontend-shared-boundary-cleanup](../features/frontend-shared-boundary-cleanup/spec.md) — сужение shared/public API и границ слоёв
- [ ] [frontend-test-hygiene](../features/frontend-test-hygiene/spec.md) — упрощение и нормализация frontend-test infrastructure - [x] [frontend-test-hygiene](../features/frontend-test-hygiene/spec.md) — упрощение и нормализация frontend-test infrastructure

View File

@ -1,7 +1,7 @@
# Frontend Infrastructure Hardening # Frontend Infrastructure Hardening
Дата: 2026-06-23 Дата: 2026-06-23
Статус: спецификация Статус: выполнено
## Контекст ## Контекст

View File

@ -1,34 +1,34 @@
# Frontend Infrastructure Hardening — tasks # Frontend Infrastructure Hardening — tasks
Статус: pending Статус: completed
## 1. Включить browser mock mode ## 1. Включить browser mock mode
- [ ] Добавить `apps/frontend/mocks/browser.ts` с `setupWorker` - [x] Добавить `apps/frontend/mocks/browser.ts` с `setupWorker`
- [ ] Подключить worker в `apps/frontend/src/main.tsx` через `VITE_API_MOCK` - [x] Подключить worker в `apps/frontend/src/main.tsx` через `VITE_API_MOCK`
- [ ] Обновить frontend docs, чтобы явно описать mock-free vs mock-enabled dev flow - [x] Обновить frontend docs, чтобы явно описать mock-free vs mock-enabled dev flow
## 2. Валидация env ## 2. Валидация env
- [ ] Описать обязательные `VITE_*` переменные в `apps/frontend/src/shared/config/env.ts` - [x] Описать обязательные `VITE_*` переменные в `apps/frontend/src/shared/config/env.ts`
- [ ] Провалить старт приложения на невалидной конфигурации до рендера - [x] Провалить старт приложения на невалидной конфигурации до рендера
- [ ] Проверить, что сообщение об ошибке не раскрывает секреты - [x] Проверить, что сообщение об ошибке не раскрывает секреты
## 3. Tooling consistency ## 3. Tooling consistency
- [ ] Проверить `apps/frontend/package.json` и синхронизировать скрипты с текущим состоянием проекта - [x] Проверить `apps/frontend/package.json` и синхронизировать скрипты с текущим состоянием проекта
- [ ] Обновить docs, где перечислены команды разработки, lint и build - [x] Обновить docs, где перечислены команды разработки, lint и build
- [ ] Удалить или переписать устаревшие упоминания старых миграционных шагов - [x] Удалить или переписать устаревшие упоминания старых миграционных шагов
## 4. Contract freshness ## 4. Contract freshness
- [ ] Привести frontend API docs к текущему source of truth - [x] Привести frontend API docs к текущему source of truth
- [ ] Проверить, что generated types остаются generated, а не редактируются вручную - [x] Проверить, что generated types остаются generated, а не редактируются вручную
- [ ] Убедиться, что frontend shared API entrypoints не ссылаются на устаревшие слойные соглашения - [x] Убедиться, что frontend shared API entrypoints не ссылаются на устаревшие слойные соглашения
## 5. Финальная проверка ## 5. Финальная проверка
- [ ] Запустить `npm run lint -w apps/frontend` - [x] Запустить `npm run lint -w apps/frontend`
- [ ] Запустить `npm run test -w apps/frontend` - [x] Запустить `npm run test -w apps/frontend`
- [ ] Запустить `npm run build -w apps/frontend` - [x] Запустить `npm run build -w apps/frontend`
- [ ] Проверить `VITE_API_MOCK=true npm run dev -w apps/frontend` на локальном старте без backend - [x] Проверить `VITE_API_MOCK=true npm run dev -w apps/frontend` на локальном старте без backend

View File

@ -1,7 +1,7 @@
# Frontend Shared Boundary Cleanup # Frontend Shared Boundary Cleanup
Дата: 2026-06-23 Дата: 2026-06-23
Статус: спецификация Статус: выполнено
## Контекст ## Контекст

View File

@ -1,28 +1,28 @@
# Frontend Shared Boundary Cleanup — tasks # Frontend Shared Boundary Cleanup — tasks
Статус: pending Статус: completed
## 1. Найти boundary ambiguity ## 1. Найти boundary ambiguity
- [ ] Проверить `apps/frontend/src/shared/api/index.ts` на слишком широкие exports - [x] Проверить `apps/frontend/src/shared/api/index.ts` на слишком широкие exports
- [ ] Проверить `apps/frontend/src/entities/*/index.ts` на недостающие public entrypoints - [x] Проверить `apps/frontend/src/entities/*/index.ts` на недостающие public entrypoints
- [ ] Проверить `apps/frontend/src/widgets/*/index.ts` на конфликтующие или неявные зависимости - [x] Проверить `apps/frontend/src/widgets/*/index.ts` на конфликтующие или неявные зависимости
## 2. Сузить shared/public surface ## 2. Сузить shared/public surface
- [ ] Убрать из `shared/api` то, что является доменной convenience-обёрткой, а не shared infrastructure - [x] Убрать из `shared/api` то, что является доменной convenience-обёрткой, а не shared infrastructure
- [ ] Переключить доменные потребители на entity barrels - [x] Переключить доменные потребители на entity barrels
- [ ] Убедиться, что новые imports не обходят public API слои - [x] Убедиться, что новые imports не обходят public API слои
## 3. Обновить документацию слоёв ## 3. Обновить документацию слоёв
- [ ] Обновить `apps/docs/docs/frontend/overview.md` - [x] Обновить `apps/docs/docs/frontend/overview.md`
- [ ] Обновить `apps/docs/docs/frontend/api-client.md` - [x] Обновить `apps/docs/docs/frontend/api-client.md`
- [ ] Зафиксировать правила публичных API слоёв для shared/entities/widgets - [x] Зафиксировать правила публичных API слоёв для shared/entities/widgets
## 4. Финальная проверка ## 4. Финальная проверка
- [ ] Запустить `npm run lint -w apps/frontend` - [x] Запустить `npm run lint -w apps/frontend`
- [ ] Запустить `npm run test -w apps/frontend` - [x] Запустить `npm run test -w apps/frontend`
- [ ] Запустить `npm run build -w apps/frontend` - [x] Запустить `npm run build -w apps/frontend`
- [ ] Убедиться, что изменения не затронули runtime-поведение - [x] Убедиться, что изменения не затронули runtime-поведение

View File

@ -1,7 +1,7 @@
# Frontend Test Hygiene # Frontend Test Hygiene
Дата: 2026-06-23 Дата: 2026-06-23
Статус: спецификация Статус: выполнено
## Контекст ## Контекст

View File

@ -1,28 +1,28 @@
# Frontend Test Hygiene — tasks # Frontend Test Hygiene — tasks
Статус: pending Статус: completed
## 1. Проверить тестовые helpers ## 1. Проверить тестовые helpers
- [ ] Проверить `apps/frontend/src/test/test-utils.tsx` на избыточные обёртки - [x] Проверить `apps/frontend/src/shared/lib/test/test-utils.tsx` на избыточные обёртки
- [ ] Проверить `apps/frontend/src/test/factories.ts` на слишком широкие mock fixtures - [x] Проверить `apps/frontend/src/shared/lib/test/factories.ts` на слишком широкие mock fixtures
- [ ] Проверить `apps/frontend/src/test/handlers.ts` на лишние defaults - [x] Проверить `apps/frontend/src/shared/lib/test/handlers.ts` на лишние defaults
## 2. Сузить test layer ## 2. Сузить test layer
- [ ] Убрать лишнюю глобальную магию из shared test setup - [x] Убрать лишнюю глобальную магию из shared test setup
- [ ] Перенести one-off setup в конкретные тесты, если он не нужен всем - [x] Перенести one-off setup в конкретные тесты, если он не нужен всем
- [ ] Оставить только действительно shared helpers - [x] Оставить только действительно shared helpers
## 3. Нормализовать conventions ## 3. Нормализовать conventions
- [ ] Обновить frontend docs, описывающие test strategy и conventions - [x] Обновить frontend docs, описывающие test strategy и conventions
- [ ] Убедиться, что global setup не распухает и остаётся понятным - [x] Убедиться, что global setup не распухает и остаётся понятным
- [ ] Сверить conventions с `frontend-test-coverage` как отдельной фичей - [x] Сверить conventions с `frontend-test-coverage` как отдельной фичей
## 4. Финальная проверка ## 4. Финальная проверка
- [ ] Запустить `npm run test -w apps/frontend` - [x] Запустить `npm run test -w apps/frontend`
- [ ] Запустить `npm run lint -w apps/frontend` - [x] Запустить `npm run lint -w apps/frontend`
- [ ] Запустить `npm run build -w apps/frontend` - [x] Запустить `npm run build -w apps/frontend`
- [ ] Убедиться, что изменения не меняют пользовательское поведение - [x] Убедиться, что изменения не меняют пользовательское поведение

View File

@ -83,9 +83,6 @@ Roadmap отражает порядок продуктовой работы, н
## Кандидаты следующих фич ## Кандидаты следующих фич
- [ ] [Frontend infrastructure hardening](features/frontend-infrastructure-hardening/spec.md) — завершение infrastructure/tooling debt.
- [ ] [Frontend shared boundary cleanup](features/frontend-shared-boundary-cleanup/spec.md) — сужение shared/public API и границ слоёв.
- [ ] [Frontend test hygiene](features/frontend-test-hygiene/spec.md) — упрощение и нормализация frontend test infrastructure.
- [ ] [Frontend debt audit and backlog](features/frontend-debt-audit/spec.md) — audit текущего - [ ] [Frontend debt audit and backlog](features/frontend-debt-audit/spec.md) — audit текущего
frontend-техдолга, разделение open items на follow-up фичи, синхронизация inbox/roadmap. frontend-техдолга, разделение open items на follow-up фичи, синхронизация inbox/roadmap.
- [ ] [Миграция таблиц на дизайн-систему](features/table-migration/spec.md) — перевести legacy-таблицы - [ ] [Миграция таблиц на дизайн-систему](features/table-migration/spec.md) — перевести legacy-таблицы