feat: RBAC E2E тесты и фикс admin-прав для редактирования постов

Основные изменения:
- Добавлены E2E тесты для проверки ownership (TC-E2E-102/103):
  * test_admin_can_edit_any_post — admin может редактировать любой пост
  * test_user_cannot_edit_other_users_post — user не может редактировать чужой пост
- Исправлены use cases (UpdatePost, DeletePost, PublishPost) — добавлена проверка роли admin
- Обновлены web routes и API routes для передачи роли в use cases
- Добавлены unit тесты для admin-сценариев

Реструктуризация тестов:
- Удалены старые API тесты (tests/api/) — требуют переработки
- Удалены старые integration тесты (tests/integration/)
- Переработаны E2E тесты: удалены старые, добавлены новые с POM
- Добавлена документация тестов: FEATURE_*.md, TEST_MODEL.md, AGENTS.md

Инфраструктура:
- Добавлен MockKeycloakClient для dev-режима
- Добавлены статические файлы: EasyMDE, Highlight.js, стили markdown
- Обновлены шаблоны: base.html, post_form.html, post_detail.html
- Обновлена DI конфигурация и провайдеры

Документация:
- tests/FEATURE_RBAC.md — матрица тестов RBAC
- tests/FEATURE_POST_LIFECYCLE.md — тесты жизненного цикла поста
- tests/FEATURE_DOMAIN_FOUNDATION.md — тесты доменного слоя
- tests/FEATURE_INFRASTRUCTURE.md — тесты инфраструктуры
- tests/TEST_MODEL.md — глобальная матрица покрытия
- app/presentation/web/AGENTS.md — гайд по Web UI
- tests/AGENTS.md — гайд по тестированию
This commit is contained in:
2026-05-07 19:55:15 +03:00
parent 41f2a3d98e
commit 46cc06b596
58 changed files with 4234 additions and 4014 deletions

View File

@@ -1,5 +1,9 @@
# Blog AGENTS.md
**Generated:** 2026-05-03 22:15 UTC
**Commit:** 41f2a3d
**Branch:** feature/tests
## Stack
- Python 3.13+, FastAPI, pydantic, uvicorn
- SQLAlchemy 2.0 (async), aiosqlite
@@ -89,6 +93,34 @@ tests/
└── e2e/ # End-to-end tests
```
## Where to Look
| Task | Location | Notes |
|------|----------|-------|
| Add a new use case | `app/application/use_cases/` | Follow naming: `{action}_post.py` |
| Add a new API endpoint | `app/presentation/api/v1/posts.py` | Or create new module in `v1/` |
| Add a new web page | `app/presentation/web/routes.py` | Integrate real use cases, not mocks |
| Add a domain entity | `app/domain/entities/` | Inherit from `BaseEntity`, add to `domain/__init__.py` |
| Add a repository method | `app/infrastructure/repositories/post.py` | Mirror in `app/domain/repositories/post.py` |
| Configure DI provider | `app/infrastructure/di/providers.py` | Add to existing provider class or create new one |
| Change database schema | `app/infrastructure/database/models.py` | Mirror changes in domain entity |
| Add/modify tests | `tests/unit/{layer}/` | Mirror `app/` structure exactly |
| Run linting | `uv run ruff check . --fix` | Pre-commit: ruff → ruff format → isort → mypy |
| Run tests | `uv run pytest` | Coverage auto-collected, HTML report at `htmlcov/` |
| Run type check | `uv run mypy .` | Strict mode; excludes `tests/e2e` |
## Code Map
| Symbol | Type | Location | Refs | Role |
|--------|------|----------|------|------|
| `app_factory` | Function | `app/main.py:50` | 3 | FastAPI app factory with DI lifespan |
| `SQLAlchemyPostRepository` | Class | `app/infrastructure/repositories/post.py:18` | 1 | Concrete repository implementation |
| `Post` | Class | `app/domain/entities/post.py:17` | 1 | Core domain entity |
| `PostRepository` | Class | `app/domain/repositories/post.py:13` | 1 | Repository interface |
| `CreatePostUseCase` | Class | `app/application/use_cases/create_post.py:14` | 1 | Use case for creating posts |
| `home` | Function | `app/presentation/web/routes.py:189` | 1 | Web home page route |
| `create_post` | Function | `app/presentation/api/v1/posts.py:35` | 1 | API create post endpoint |
## Key Conventions
### Dependency Rule
@@ -99,9 +131,6 @@ tests/
### Testing
- **Unit tests**: Test domain logic without DB/external services
- **Integration tests**: Test repository implementations with real DB
- **API tests**: Test endpoints with mocked use cases
- **E2E tests**: Full workflow testing
### Code Patterns
- Use **dataclasses** for entities and value objects
@@ -110,6 +139,17 @@ tests/
- Use **Repository** pattern for data access
- Use **Dependency Injection** via FastAPI's Depends()
## Anti-Patterns (This Project)
- **NO inline comments** — Self-documenting code only; Google-style docstrings required
- **NO type suppression** — Never use `typing.Any` casts or `# type: ignore` to bypass mypy strict mode
- **Dead code**: `create_container()` in `app/infrastructure/di/container.py` is defined but never used; `main.py` calls `make_async_container()` directly
- **Empty directories**: `app/domain/exceptions/` and `app/presentation/api/deps/` are empty dirs that co-exist with `.py` files of the same name — import ambiguity risk
- **Missing `__main__.py`**: `python -m app` fails; use `uv run blog` or `python app/main.py`
- **Stale config**: `pyproject.toml` excludes `tests/e2e` but the directory does not exist
- **Unused dependency**: `black` is in `[dependency-groups] lints` but never invoked; ruff format is used instead
- **Pre-commit excludes `__init__.py`**: All `__init__.py` files skip linting and import sorting
## AI Code Generation Requirements
### Documentation Standards
@@ -313,3 +353,12 @@ response.set_cookie(
- SQLite by default (aiosqlite)
- Tables auto-created on startup
- Use `init_db()` and `close_db()` in lifespan
## Notes
- Web routes (`app/presentation/web/routes.py`) currently use `MockPost` and `MOCK_POSTS` instead of real use cases — integrate with actual use cases when ready
- `alembic/` directory exists but is non-functional (no `alembic.ini`, no migration scripts)
- `tests/integration/`, `tests/api/`, `tests/e2e/` are documented in architecture but do not exist yet
- `app/domain/roles.py` exists but its symbols are not exported in `app/domain/__init__.py`
- Woodpecker CI uses `.woodpecker/` directory (3 separate YAML files) instead of single `.woodpecker.yml` — valid but non-standard
- CI pipelines have copy-paste boilerplate; `test.yaml` uses `--group tests` while `lint.yaml` and `type.yaml` use `--only-group <X>`