rules
Gitea Actions Demo / build_and_push (push) Successful in 1m14s
Details
Gitea Actions Demo / build_and_push (push) Successful in 1m14s
Details
This commit is contained in:
parent
a44267cea8
commit
ad9e1a5bbf
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"playwright": {
|
||||||
|
"command": "/home/artem/.nvm/versions/node/v22.14.0/bin/npx",
|
||||||
|
"args": ["@playwright/mcp@latest", "--browser", "chromium", "--headless", "--viewport-size", "1440x900"],
|
||||||
|
"env": {
|
||||||
|
"PATH": "/home/artem/.nvm/versions/node/v22.14.0/bin:/usr/local/bin:/usr/bin:/bin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
# MCP Browser Verification Guide
|
||||||
|
|
||||||
|
## Что это
|
||||||
|
|
||||||
|
Playwright MCP server (`@playwright/mcp`) предоставляет инструменты для взаимодействия с браузером
|
||||||
|
через Model Context Protocol. Позволяет агенту (Zoo Code) открывать страницы, делать snapshot DOM,
|
||||||
|
кликать, заполнять формы, делать скриншоты — без написания тест-кода.
|
||||||
|
|
||||||
|
## Конфигурация
|
||||||
|
|
||||||
|
- **Сервер**: `web-browser` в `mcp_settings.json` (Zoo Code global storage)
|
||||||
|
- **Браузер**: Chromium (headless)
|
||||||
|
- **Node**: 22.14.0 (nvm, absolute path)
|
||||||
|
- **Пакет**: `@playwright/mcp@latest` (npm)
|
||||||
|
|
||||||
|
## Workflow: UI Verification после изменения
|
||||||
|
|
||||||
|
### 1. Запуск dev-сервера
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
# → http://localhost:5173
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Проверка публичных страниц (без auth)
|
||||||
|
|
||||||
|
| Рут | Что проверять |
|
||||||
|
|-----|---------------|
|
||||||
|
| `/explore` | Feed загружен, карточки тренировок рендерятся |
|
||||||
|
| `/public/workouts/:id` | Детали тренировки: chart, map, данные |
|
||||||
|
| `/routes` | Список маршрутов |
|
||||||
|
| `/404` | Страница 404 для неизвестных маршрутов |
|
||||||
|
|
||||||
|
### 3. Проверка auth-страниц (с моком auth)
|
||||||
|
|
||||||
|
```js
|
||||||
|
// browser_evaluate: установить мок-токен и перезагрузить
|
||||||
|
() => {
|
||||||
|
localStorage.setItem('token', 'mock-jwt-token');
|
||||||
|
localStorage.setItem('user', JSON.stringify({ id: 1, name: 'Test User', email: 'test@test.ru' }));
|
||||||
|
localStorage.setItem('profile', JSON.stringify({ name: 'Test', avatar: null }));
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
После reload:
|
||||||
|
|
||||||
|
| Рут | Что проверять |
|
||||||
|
|-----|---------------|
|
||||||
|
| `/workouts` | Список пользовательских тренировок |
|
||||||
|
| `/workouts/:id` | Detail: chart (power, HR, elevation), map polyline |
|
||||||
|
| `/preferences` | Профиль, настройки |
|
||||||
|
| `/workouts/upload` | Форма загрузки FIT/GPX |
|
||||||
|
|
||||||
|
### 4. Инструменты MCP (ключевые)
|
||||||
|
|
||||||
|
| Инструмент | Назначение |
|
||||||
|
|-----------|-----------|
|
||||||
|
| `browser_navigate` | Перейти по URL |
|
||||||
|
| `browser_snapshot` | Получить accessibility tree (структура DOM) |
|
||||||
|
| `browser_take_screenshot` | Скриншот (PNG) |
|
||||||
|
| `browser_click` | Клик по элементу (по ref из snapshot) |
|
||||||
|
| `browser_fill_form` | Заполнить форму |
|
||||||
|
| `browser_evaluate` | Выполнить JS на странице |
|
||||||
|
| `browser_network_requests` | Список HTTP-запросов (проверить API) |
|
||||||
|
| `browser_wait_for` | Дождаться появления текста |
|
||||||
|
| `browser_console_messages` | Console errors/warnings |
|
||||||
|
|
||||||
|
### 5. Типовой сценарий проверки (example)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. browser_navigate → http://localhost:5173/explore
|
||||||
|
2. browser_wait_for → "Тренировки" (заголовок)
|
||||||
|
3. browser_snapshot → проверить структуру feed
|
||||||
|
4. browser_take_screenshot → визуал
|
||||||
|
5. browser_evaluate → mock auth (localStorage)
|
||||||
|
6. browser_navigate → http://localhost:5173/workouts
|
||||||
|
7. browser_snapshot → проверить сайдбар (authRoutes), список
|
||||||
|
8. browser_network_requests → убедиться что API /api/v0/workouts вызван
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ограничения
|
||||||
|
|
||||||
|
- **API**: dev-сервер проксирует API на `HOST` (production). Для изолированной проверки
|
||||||
|
нужно либо:
|
||||||
|
- Использовать production API (read-only запросы — ок)
|
||||||
|
- Поднять локальный mock-сервер (axios interceptors)
|
||||||
|
- **Yandex Maps**: API key hardcoded, работает в headless, но рендер может отличаться
|
||||||
|
- **Chart.js**: Canvas — в snapshot не виден, только через screenshot
|
||||||
|
- **SSR**: MCP проверяет SPA (client-side). SSR — отдельно через `curl` или `browser_navigate` на SSR-порт
|
||||||
|
|
||||||
|
## Acceptance Criteria для Coder-задач
|
||||||
|
|
||||||
|
Каждая Coder-задача с UI-изменениями должна включать:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
### Acceptance Criteria
|
||||||
|
1. `yarn lint` → 0 ошибок
|
||||||
|
2. `yarn build` → 0 ошибок (vue-tsc --noEmit)
|
||||||
|
3. MCP browser: [конкретный сценарий проверки — рут, что ожидать в DOM]
|
||||||
|
```
|
||||||
|
|
@ -2,11 +2,44 @@
|
||||||
|
|
||||||
## Task State
|
## Task State
|
||||||
|
|
||||||
- task_id: TASK-MCP-SETUP
|
- task_id: TASK-TEST-PUBLIC
|
||||||
- status: success
|
- status: in_progress
|
||||||
- parent_task: —
|
- parent_task: —
|
||||||
- summary: **Настроить Playwright MCP для UI-верификации через браузер. Конфиг Zoo Code обновлён (Node 22), Chromium установлен.**
|
- summary: **Написать Playwright integration тесты для фронтенда в `../integration/tests/`. 3 spec файла: auth-flows ✅, public-pages, auth-protected.**
|
||||||
- next task: —
|
- next task: TASK-TEST-PROTECTED → Verify
|
||||||
|
|
||||||
|
## ✅ CODER SUCCESS REPORT — TASK-TEST-AUTH
|
||||||
|
|
||||||
|
- `../integration/tests/auth-flows.spec.ts` создан: 4 теста (login success, login failure, signup+auto-login, logout)
|
||||||
|
- Self-seed via `POST /api/v0/signup`, Vuestic selectors (`input[type=email]`, `input[type=password]`)
|
||||||
|
- Verified: `npx playwright test tests/auth-flows.spec.ts` → **4 passed (19.2s)**
|
||||||
|
|
||||||
|
## TASK-TEST-PUBLIC: public-pages.spec.ts
|
||||||
|
|
||||||
|
**Цель:** Playwright spec для auth-сценариев (signup, login success/error, logout, validation).
|
||||||
|
|
||||||
|
**Файл для создания:** `../integration/tests/auth-flows.spec.ts`
|
||||||
|
|
||||||
|
**Конвенции (см. SKILL.md):**
|
||||||
|
- Self-seed user via `POST /api/v0/signup` in `beforeAll`
|
||||||
|
- Selectors: `input[type=email]`, `input[type=password]`, `getByRole('button', { name: 'Вход' })`
|
||||||
|
- Vuestic floating labels → select by input type, NOT placeholder
|
||||||
|
- Auth mock via `page.evaluate(() => localStorage.setItem(...))`
|
||||||
|
- Do NOT call `expect()` inside `page.evaluate()`
|
||||||
|
- Base URLs: `FRONTEND` (5173), `BACKEND` (8000)
|
||||||
|
- `freshPage()` helper: goto → clear localStorage → goto again
|
||||||
|
|
||||||
|
**Тесты в spec:**
|
||||||
|
1. **Signup**: `POST /api/v0/signup` → returns token, user, profile; navigate to `/auth/signup` → fill form → submit → redirect to `/explore`
|
||||||
|
2. **Login success**: pre-seed user via API → UI login → token in localStorage → redirect to `/explore`
|
||||||
|
3. **Login failure**: wrong password → error toast appears, stays on `/auth/login`
|
||||||
|
4. **Logout**: logged in → open profile dropdown → «Выход» → redirect to login, token cleared
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
1. Spec file created at `../integration/tests/auth-flows.spec.ts`
|
||||||
|
2. All tests self-contained (self-seed data)
|
||||||
|
3. Follows existing `sidebar-auth-switch.spec.ts` patterns
|
||||||
|
4. `npx playwright test tests/auth-flows.spec.ts` passes against integration stack
|
||||||
|
|
||||||
## TASK-MCP-SETUP: Playwright MCP configuration
|
## TASK-MCP-SETUP: Playwright MCP configuration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,21 @@
|
||||||
# Progress — Strava Frontend
|
# Progress — Strava Frontend
|
||||||
|
|
||||||
|
## 2026-09-24 — UI-testing skill + mandatory rule
|
||||||
|
|
||||||
|
- `.roo/skills/ui-testing/SKILL.md` — how to test UI via (A) MCP browser ad-hoc and (B) the Playwright integration stand: run commands, spec conventions, selectors, gotchas.
|
||||||
|
- `.roo/rules/ui-testing.md` — MANDATORY rule: after any `src/` change affecting a visible route/interaction the task is not done until `yarn lint` + `yarn build` + browser verification (MCP ad-hoc for quick/visual, Playwright spec for must-not-regress) + green `npx playwright test`. Includes run cheat-sheet and required reporting format.
|
||||||
|
|
||||||
|
## 2026-09-24 — Integration UI-test stand (Playwright + docker-compose)
|
||||||
|
|
||||||
|
- Created `../integration/` (sibling of `frontend/`, `backend/`):
|
||||||
|
- `docker-compose.yml` — 3 services: `db` (postgres:15, host:5433, schema `strava` via `db-init/01-schema.sql`), `backend` (python:3.12, `pip install -r requirements.txt` + `alembic upgrade head` + `python -m app.web.__main__`, port 8000, `DB_URI=postgresql+asyncpg://svcuser:svcpass@db:5432/svc`), `frontend` (node:20-alpine, `yarn install --frozen-lockfile --ignore-scripts` + `yarn dev --host 0.0.0.0 --port 5173`, env `VITE_HOST=http://localhost:8000`, `HUSKY=0`).
|
||||||
|
- `package.json` + `playwright.config.ts` (`@playwright/test` ^1.54, baseURL `FRONTEND_URL||localhost:5173`, `API_URL`).
|
||||||
|
- `tests/sidebar-auth-switch.spec.ts` — TASK-AUTH-NAV regression: publicRoutes (no «Тренировки») → UI login (`/auth/login`, `input[type=email]` + `input[type=password]` + button «Вход») → authRoutes («Тренировки» appears, no reload) → UI logout (profile dropdown → «Выход») → publicRoutes. Self-seeds a unique user via `POST /api/v0/signup` in `beforeAll`.
|
||||||
|
- `README.md` — run instructions (`yarn up`, wait for backend, `yarn test`).
|
||||||
|
- Frontend change: `src/main.ts` `HOST = import.meta.env.VITE_HOST || "https://cycle-rider.ru"` (production unaffected — env unset → falls back to prod host).
|
||||||
|
- Verified: full stack up (frontend 200, backend 200 on `/api/v0/html_test/login`, db healthy); `npx playwright test tests/sidebar-auth-switch.spec.ts` → **1 passed (9.9s)** on Node 22 (nvm `~/.nvm/versions/node/v22.14.0/bin`).
|
||||||
|
- Gotchas: (1) npm install in frontend container fails on `@unhead/vue` peer-dep (wants vite>=6, project vite 5) → must use **yarn** (`yarn.lock`), and `node:20-alpine` already ships yarn (do NOT `npm i -g yarn` → EEXIST); (2) backend health path is `/api/v0/html_test/login` (router_public prefix `/api/v0`, no `/auth`); (3) Vuestic `VaInput` uses floating labels → no usable placeholder, select login fields by `input[type=email]` / `input[type=password]`; (4) Playwright/MCP need Node ≥20 (system node is 18) → run via nvm Node 22.
|
||||||
|
|
||||||
## 2026-09-24 — TASK-AUTH-NAV-2: реактивные маршруты в сайдбаре и хлебных крошках
|
## 2026-09-24 — TASK-AUTH-NAV-2: реактивные маршруты в сайдбаре и хлебных крошках
|
||||||
|
|
||||||
- `NavigationRoutes.ts`: named exports `authRoutes`/`publicRoutes`, удалён module-level `localStorage.getItem("token")` тернарник.
|
- `NavigationRoutes.ts`: named exports `authRoutes`/`publicRoutes`, удалён module-level `localStorage.getItem("token")` тернарник.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
# UI Testing Rule (mandatory after frontend changes)
|
||||||
|
|
||||||
|
> Procedure + commands: see the **`ui-testing`** skill (`.roo/skills/ui-testing/SKILL.md`).
|
||||||
|
> This rule defines the **when** (obligation) and the **gate** (definition of done).
|
||||||
|
|
||||||
|
## When this rule applies
|
||||||
|
|
||||||
|
Any change under `src/` that affects a **visible route or interaction**:
|
||||||
|
pages, components, auth flows, sidebar/breadcrumbs, forms, charts, maps, i18n
|
||||||
|
labels. Pure backend-only or docs-only changes are exempt.
|
||||||
|
|
||||||
|
## The gate (Definition of Done)
|
||||||
|
|
||||||
|
A frontend task is **not done** until ALL of the following pass. Do not claim
|
||||||
|
completion otherwise.
|
||||||
|
|
||||||
|
1. `yarn lint` (frontend) → 0 errors
|
||||||
|
2. `yarn build` (frontend) → 0 errors (`vue-tsc --noEmit`)
|
||||||
|
3. **Browser verification** — the changed behavior is actually exercised in a
|
||||||
|
real browser (this is the non-negotiable step the user requires):
|
||||||
|
- **Quick change / visual only** → **MCP browser** ad-hoc check:
|
||||||
|
`browser_navigate` the affected route → `browser_snapshot` (assert the
|
||||||
|
structure) → `browser_take_screenshot` → `browser_console_messages`
|
||||||
|
(no app errors).
|
||||||
|
- **Behavior that must not regress** → a **Playwright integration spec** in
|
||||||
|
`../integration/tests/` that passes against the docker-compose stack.
|
||||||
|
4. If a Playwright spec was touched or added: `npx playwright test` green
|
||||||
|
(Node ≥20, via nvm Node 22).
|
||||||
|
|
||||||
|
## How to run (cheat-sheet)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Playwright integration stack (repeatable / regression)
|
||||||
|
cd ../integration
|
||||||
|
export PATH="$HOME/.nvm/versions/node/v22.14.0/bin:$PATH" # Playwright needs Node ≥20
|
||||||
|
yarn up # docker compose up -d --build
|
||||||
|
until curl -sf http://localhost:8000/api/v0/html_test/login >/dev/null; do sleep 2; done
|
||||||
|
npx playwright test # all
|
||||||
|
npx playwright test tests/<name>.spec.ts # one
|
||||||
|
yarn down # stop (keep DB)
|
||||||
|
```
|
||||||
|
|
||||||
|
MCP browser (ad-hoc) needs the app reachable: `yarn dev` → `:5173`, or the
|
||||||
|
integration stack (`yarn up`) so the SPA talks to the real backend at `:8000`.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
|
||||||
|
When finishing a task, state explicitly in the completion message:
|
||||||
|
- lint/build result
|
||||||
|
- which browser verification was performed (MCP ad-hoc vs Playwright spec) and
|
||||||
|
the outcome (pass/fail)
|
||||||
|
- for Playwright: the spec name and that it is green
|
||||||
|
|
||||||
|
## Gotchas (must follow)
|
||||||
|
|
||||||
|
- Frontend deps install with **yarn**, never npm (peer-dep conflict on
|
||||||
|
`@unhead/vue` / vite).
|
||||||
|
- Vuestic inputs have **floating labels → empty placeholder**: select by
|
||||||
|
`input[type=email]` / `input[type=password]`, not by placeholder.
|
||||||
|
- Sidebar = `<aside>`; auth-only item is «Тренировки» (`menu.workouts`).
|
||||||
|
- Do NOT call `expect(...)` inside `page.evaluate(...)`.
|
||||||
|
- `node:20-alpine` already ships yarn — do not `npm i -g yarn` (EEXIST).
|
||||||
|
- Full stack + command details: `../integration/README.md`.
|
||||||
|
|
@ -14,8 +14,7 @@ import axios from "axios";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { createYmaps } from "vue-yandex-maps";
|
import { createYmaps } from "vue-yandex-maps";
|
||||||
|
|
||||||
const HOST = "https://cycle-rider.ru";
|
const HOST = import.meta.env.VITE_HOST || "https://cycle-rider.ru";
|
||||||
// const HOST = "http://localhost:8000";
|
|
||||||
|
|
||||||
axios.defaults.baseURL = HOST;
|
axios.defaults.baseURL = HOST;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue