diff --git a/.gitignore b/.gitignore
index e0ab4f2..c26be44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,5 @@ Thumbs.db
# Kubernetes secrets
k8s/secrets.yaml
+
+.playwright-mcp
diff --git a/.playwright-mcp/keycloak-login-current.png b/.playwright-mcp/keycloak-login-current.png
deleted file mode 100644
index 1237f7a..0000000
Binary files a/.playwright-mcp/keycloak-login-current.png and /dev/null differ
diff --git a/.playwright-mcp/keycloak-login-nested.png b/.playwright-mcp/keycloak-login-nested.png
deleted file mode 100644
index 0774276..0000000
Binary files a/.playwright-mcp/keycloak-login-nested.png and /dev/null differ
diff --git a/CLAUDE.md b/CLAUDE.md
index 0620ca1..33f8f78 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -9,6 +9,7 @@
2. CONTEXT.md — текущий статус
3. ROADMAP.md — план и задачи
4. REQUIREMENTS.md / ARCHITECTURE.md — по необходимости
+5. E2E_TESTING.md — **перед написанием тестов!**
После работы обнови CONTEXT.md.
@@ -23,13 +24,15 @@
- [ROADMAP.md](ROADMAP.md) — план разработки, задачи по фазам
- [REQUIREMENTS.md](REQUIREMENTS.md) — требования к продукту
- [ARCHITECTURE.md](ARCHITECTURE.md) — C4, sequence diagrams, API контракты, UI прототипы
+- [E2E_TESTING.md](E2E_TESTING.md) — **читай перед написанием тестов!** Гайд по e2e тестированию
## Структура проекта
```
team-planner/
├── backend/ # NestJS API
-└── frontend/ # React + TypeScript
+├── frontend/ # React + TypeScript
+└── tests/ # E2E тесты (Playwright)
```
## Ключевые сущности
@@ -51,3 +54,18 @@ team-planner/
Используется ai-proxy service для оценки трудозатрат.
Гайд: `/Users/vigdorov/dev/gptunnel-service/INTEGRATION.md`
+
+## E2E Тестирование
+
+**Перед написанием тестов обязательно прочитай [E2E_TESTING.md](E2E_TESTING.md)!**
+
+Ключевые правила:
+- Тесты следуют требованиям из ROADMAP.md, а не адаптируются под код
+- Используй `data-testid` для стабильных селекторов (не `tbody tr`, `.nth()`, CSS классы)
+- При добавлении новых компонентов сразу добавляй `data-testid`
+- Группируй тесты по фичам/сценариям, а не по компонентам
+
+```bash
+# Запуск тестов
+cd tests && npx playwright test
+```
diff --git a/CONTEXT.md b/CONTEXT.md
index 971c335..bb7ae77 100644
--- a/CONTEXT.md
+++ b/CONTEXT.md
@@ -6,9 +6,9 @@
## Текущий статус
-**Этап:** Фаза 2 — Drag & Drop ✅, Авторизация ✅, далее цвета/комментарии/команда
-**Фаза MVP:** Базовый функционал + авторизация готовы
-**Последнее обновление:** 2026-01-14
+**Этап:** Фаза 2 завершена ✅, E2E тесты готовы ✅, далее Фаза 3 (AI-интеграция)
+**Фаза MVP:** Базовый функционал + авторизация + расширенный функционал готовы
+**Последнее обновление:** 2026-01-15
---
@@ -49,6 +49,15 @@
| 2026-01-14 | **Infra:** Добавлен KEYCLOAK_REALM_URL в k8s/backend-deployment.yaml |
| 2026-01-14 | **Keycloak Theme:** Кастомная тема для Keycloak (MUI стиль) — keycloak-theme/ |
| 2026-01-14 | **CI/CD:** Добавлены steps build-keycloak-theme и deploy-keycloak-theme в .drone.yml |
+| 2026-01-14 | **Фаза 2:** Цветовая маркировка — ColorPickerCell, цветной фон строки, фильтр по цвету |
+| 2026-01-14 | **Фаза 2:** Комментарии — backend модуль (entity, service, controller, миграция), frontend (CommentsPanel, раскрывающаяся панель) |
+| 2026-01-14 | **UX:** Хук useAuth для данных пользователя, имя в header, автор комментариев из Keycloak |
+| 2026-01-14 | **Фаза 2:** Управление командой — backend (TeamMember entity, CRUD, summary), frontend (TeamPage, табы навигации) |
+| 2026-01-14 | **Фаза 2:** Динамические роли — Role entity вместо enum, CRUD API (/api/roles), RolesManager UI, миграция данных |
+| 2026-01-15 | **Testing:** E2E тесты Фазы 2 (Playwright) — 54 теста покрывают D&D, цвета, комментарии, команду |
+| 2026-01-15 | **Testing:** Рефакторинг тестов на data-testid — стабильные селекторы вместо tbody/tr/.nth() |
+| 2026-01-15 | **Testing:** Добавлены data-testid во все компоненты фронтенда (IdeasTable, TeamPage, CommentsPanel и др.) |
+| 2026-01-15 | **Docs:** Создан E2E_TESTING.md — гайд по написанию e2e тестов, соглашения по data-testid |
---
@@ -56,7 +65,7 @@
> Смотри [ROADMAP.md](ROADMAP.md) для полного плана разработки
-**Сейчас:** Фаза 2 — цветовая маркировка, комментарии, управление командой
+**Сейчас:** Фаза 2 завершена ✅ — далее Фаза 3 (AI-интеграция)
---
@@ -70,6 +79,7 @@ team-planner/
├── REQUIREMENTS.md # Требования к продукту
├── ARCHITECTURE.md # Архитектура, API, UI
├── ROADMAP.md # План разработки
+├── E2E_TESTING.md # Гайд по E2E тестированию ✅
├── docker-compose.yml # PostgreSQL и сервисы
├── .drone.yml # CI/CD pipeline (Drone CI)
├── keycloak-theme/ # Кастомная тема Keycloak ✅
@@ -84,10 +94,10 @@ team-planner/
├── tests/
│ ├── package.json # Зависимости для тестов
│ ├── playwright.config.ts # Конфигурация Playwright
-│ └── e2e/ # Playwright E2E тесты
+│ └── e2e/ # Playwright E2E тесты (54 теста) ✅
│ ├── auth.setup.ts # Авторизация для тестов (Keycloak)
-│ ├── phase1.spec.ts # Тесты Фазы 1 (11 тестов)
-│ └── phase2.spec.ts # Тесты Фазы 2 (D&D, цвета, комментарии, команда)
+│ ├── phase1.spec.ts # Тесты Фазы 1 (17 тестов)
+│ └── phase2.spec.ts # Тесты Фазы 2 (37 тестов — D&D, цвета, комментарии, команда)
├── backend/ # NestJS API
│ ├── src/
│ │ ├── auth/ # Модуль авторизации ✅
@@ -99,7 +109,7 @@ team-planner/
│ │ │ │ └── reorder-ideas.dto.ts # DTO для изменения порядка
│ │ │ ├── ideas.controller.ts # PATCH /ideas/reorder
│ │ │ └── ideas.service.ts # reorder() с транзакцией
-│ │ ├── team/ # Модуль команды (Фаза 2)
+│ │ ├── team/ # Модуль команды (Фаза 2) — TeamMember + Role entities
│ │ ├── comments/ # Модуль комментариев (Фаза 2)
│ │ └── ai/ # AI-оценка (Фаза 3)
│ └── ...
@@ -114,13 +124,21 @@ team-planner/
│ │ │ ├── columns.tsx # Колонки + drag handle
│ │ │ └── ...
│ │ ├── IdeasFilters/ # Фильтры
- │ │ └── CreateIdeaModal/ # Модалка создания
+ │ │ ├── CreateIdeaModal/ # Модалка создания
+ │ │ ├── TeamPage/ # Страница команды (Фаза 2)
+ │ │ │ ├── TeamPage.tsx # Табы: Участники / Роли
+ │ │ │ ├── TeamMemberModal.tsx # Модалка участника
+ │ │ │ └── RolesManager.tsx # Управление ролями
+ │ │ └── CommentsPanel/ # Комментарии к идеям
│ ├── hooks/
│ │ └── useIdeas.ts # React Query хуки + useReorderIdeas
│ ├── services/
│ │ ├── api.ts # Axios + auth interceptors
│ │ ├── keycloak.ts # Keycloak instance ✅
- │ │ └── ideas.ts # API методы + reorder()
+ │ │ ├── ideas.ts # API методы + reorder()
+ │ │ ├── team.ts # API команды
+ │ │ ├── roles.ts # API ролей
+ │ │ └── comments.ts # API комментариев
│ ├── store/
│ │ └── ideas.ts # Zustand store
│ └── types/
@@ -166,3 +184,4 @@ team-planner/
- **Keycloak Theme:** Кастомная тема `team-planner` в стиле MUI, образ `registry.vigdorov.ru/library/keycloak-team-planner`
- **Production URL:** https://team-planner.vigdorov.ru (добавлен в Valid redirect URIs и Web origins клиента Keycloak)
- **CI/CD:** Drone CI (.drone.yml) — сборка backend/frontend/keycloak-theme, деплой в K8s namespace `team-planner`
+- **E2E тесты:** Все компоненты имеют `data-testid` для стабильных селекторов. Перед написанием тестов читай E2E_TESTING.md!
diff --git a/E2E_TESTING.md b/E2E_TESTING.md
new file mode 100644
index 0000000..8734cee
--- /dev/null
+++ b/E2E_TESTING.md
@@ -0,0 +1,283 @@
+# E2E Testing Guide
+
+Руководство по написанию e2e тестов для Team Planner.
+
+## Принципы
+
+### 1. Тесты следуют требованиям, а не коду
+
+Тесты должны проверять **пользовательские сценарии** из требований, а не адаптироваться под текущую реализацию.
+
+```
+❌ Плохо: "Проверить что кнопка имеет класс .MuiButton-contained"
+✅ Хорошо: "Проверить что пользователь может создать новую идею"
+```
+
+**Порядок работы:**
+1. Прочитать требования к фазе/фиче в `ROADMAP.md` и `REQUIREMENTS.md`
+2. Выделить пользовательские сценарии
+3. Написать тесты для каждого сценария
+4. Убедиться что тесты проверяют бизнес-логику, а не детали реализации
+
+### 2. Стабильные селекторы через data-testid
+
+**Никогда не использовать:**
+- Позиционные селекторы: `tbody tr`, `.nth(2)`, `:first-child`
+- CSS классы MUI: `.MuiButton-root`, `.MuiTableCell-body`
+- Структурные селекторы: `table > tbody > tr > td`
+
+**Всегда использовать:**
+- `data-testid` для уникальной идентификации элементов
+- `[role="..."]` только для стандартных ARIA ролей (tab, dialog, listbox)
+- Текстовые селекторы только для статичного контента
+
+```typescript
+// ❌ Плохо - сломается при изменении структуры
+const row = page.locator('tbody tr').nth(2);
+const button = page.locator('.MuiIconButton-root').first();
+
+// ✅ Хорошо - стабильно при рефакторинге
+const row = page.locator('[data-testid="idea-row-123"]');
+const button = page.locator('[data-testid="delete-idea-button"]');
+```
+
+## Соглашения по data-testid
+
+### Именование
+
+| Паттерн | Пример | Использование |
+|---------|--------|---------------|
+| `{component}-{element}` | `ideas-table` | Основные элементы |
+| `{component}-{element}-{id}` | `idea-row-123` | Динамические элементы |
+| `{action}-{target}-button` | `delete-idea-button` | Кнопки действий |
+| `{name}-input` | `member-name-input` | Поля ввода |
+| `{name}-modal` | `team-member-modal` | Модальные окна |
+| `filter-{name}` | `filter-status` | Фильтры |
+
+### Обязательные data-testid по компонентам
+
+#### Таблицы
+```
+{name}-table - сам table элемент
+{name}-table-container - обёртка таблицы
+{name}-empty-state - состояние "нет данных"
+{item}-row-{id} - строка с данными
+```
+
+#### Формы и модалки
+```
+{name}-modal - Dialog компонент
+{name}-form - form элемент
+{field}-input - поля ввода (TextField)
+{field}-select - выпадающие списки (FormControl)
+submit-{action}-button - кнопка отправки
+cancel-{action}-button - кнопка отмены
+```
+
+#### Действия в строках
+```
+edit-{item}-button - редактирование
+delete-{item}-button - удаление
+toggle-{feature}-button - переключение
+```
+
+## Работа с MUI компонентами
+
+### Popover / Menu
+
+MUI Popover рендерится через Portal в `
`. Для добавления `data-testid` используй `slotProps`:
+
+```tsx
+,
+ }}
+>
+```
+
+### Dialog
+
+Dialog также использует Portal. Добавляй `data-testid` напрямую:
+
+```tsx
+