docs(frontend): complete debt backlog features with test conventions
This commit is contained in:
parent
9ad0f571d5
commit
d529d51612
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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`.
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Frontend Infrastructure Hardening
|
# Frontend Infrastructure Hardening
|
||||||
|
|
||||||
Дата: 2026-06-23
|
Дата: 2026-06-23
|
||||||
Статус: спецификация
|
Статус: выполнено
|
||||||
|
|
||||||
## Контекст
|
## Контекст
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Frontend Shared Boundary Cleanup
|
# Frontend Shared Boundary Cleanup
|
||||||
|
|
||||||
Дата: 2026-06-23
|
Дата: 2026-06-23
|
||||||
Статус: спецификация
|
Статус: выполнено
|
||||||
|
|
||||||
## Контекст
|
## Контекст
|
||||||
|
|
||||||
|
|||||||
@ -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-поведение
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Frontend Test Hygiene
|
# Frontend Test Hygiene
|
||||||
|
|
||||||
Дата: 2026-06-23
|
Дата: 2026-06-23
|
||||||
Статус: спецификация
|
Статус: выполнено
|
||||||
|
|
||||||
## Контекст
|
## Контекст
|
||||||
|
|
||||||
|
|||||||
@ -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] Убедиться, что изменения не меняют пользовательское поведение
|
||||||
|
|||||||
@ -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-таблицы
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user