Декларативные end-to-end сценарии в tests/e2e/. YAML описывает шаги, TypeScript-handler — конкретные API/UI/DB-проверки. Отчёт в Markdown. Структура: - runner.ts : entry, парсит YAML, прогоняет steps, пишет report - run.sh : pnpm install + tsx - lib/api.ts : axios + login() (через /connect/token + /api/me) - lib/db.ts : docker exec psql, resetTenantData(), countRows() - lib/report.ts : Markdown-аккумулятор (steps + bugs + ux + gap + perf) - scenarios/full-cycle.yml : 12 шагов - scenarios/full-cycle.steps.ts : handlers (один на шаг) - README.md : как добавить новый сценарий reset_db в preconditions: - TRUNCATE tenant-таблиц CASCADE - AspNet*/users — оставляем только admin@food-market.local - OpenIddict tokens — все valid → revoked - Реестр products + системные справочники + миграции + platform_settings — НЕ трогаем Запуск: tests/e2e/run.sh full-cycle [--api-only] Первый прогон (--api-only, baseline в reports/full-cycle-2026-05-07-baseline.md): - 8 ✓ / 1 ✗ / 3 ◯ из 12. - Critical bug: Cashier видит /api/organization/employees через API (нет [Authorize(Roles="Admin")] на List endpoint). - High: при CreateOrg через SuperAdmin не сидируются tenant-units — пустой каталог измерений у новой org (DevDataSeeder.SeedTenantReferencesAsync должен вызываться, но не вызывается). - Logic gaps: реестр products tenant-scoped и новая org стартует с пустым каталогом; SuperAdmin /organizations не валидирует ФЛК телефона; Cashier не получает Identity-роль "Cashier" при создании через /employees. UI-шаги (Playwright) в этом коммите не покрыты — runner работает в --api-only режиме. UI-extension добавим следующим коммитом, не блокирует получение полезного отчёта.
126 lines
5.5 KiB
Markdown
126 lines
5.5 KiB
Markdown
# E2E report: full-cycle
|
||
|
||
Запущен: 2026-05-07T19:04:04.557Z
|
||
Длительность: 6.3с
|
||
|
||
**Итог:** 8 ✓ / 1 ✗ / 0 ⚠ / 3 ◯ (всего 12)
|
||
|
||
## ✓ Step step01_create_organization: SuperAdmin создаёт «Test Shop {timestamp}» (KZ, KZT, ФЛК телефона)
|
||
|
||
Длительность: 2060мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | POST /api/super-admin/organizations → 200 | ✓ org=Test Shop 1778180644557 |
|
||
| api | GET /api/super-admin/organizations включает созданную org | ✓ |
|
||
|
||
## ✓ Step step02_create_first_admin: SuperAdmin создаёт первого Admin сотрудника организации (Employee + AppUser)
|
||
|
||
Длительность: 630мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | Temp password возвращён CreateOrgResult | ✓ len=12 |
|
||
| db | employees содержит ровно 1 запись для новой org | ✓ count=1 |
|
||
| db | AspNetUserRoles содержит role=Admin для нового user | ✓ Admin |
|
||
|
||
## ✓ Step step03_login_as_admin: Логин под admin (не SuperAdmin override) — JWT с org_id и role=Admin
|
||
|
||
Длительность: 565мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | /connect/token password-grant выдал токен | ✓ |
|
||
| api | /api/me содержит role=Admin | ✓ Admin |
|
||
| api | /api/me содержит правильный orgId | ✓ c607c097-9333-4533-a23a-0042dc24b851 |
|
||
|
||
## ✓ Step step04_create_storekeeper_and_cashier: Admin создаёт Storekeeper и Cashier через /settings/employees
|
||
|
||
Длительность: 1688мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | employee-roles list | ✓ 200, total=3 |
|
||
| api | Системная роль «Кладовщик» существует | ✓ |
|
||
| api | Системная роль «Кассир» существует | ✓ |
|
||
| api | POST /api/organization/employees (Кладовщик) | ✓ 200 |
|
||
| api | POST /api/organization/employees (Кассир) | ✓ 200 |
|
||
| db | employees total = 3 (admin + keeper + cashier) | ✓ count=3 |
|
||
| api | Невалидный email отвергается при createAccount | ✓ 400 |
|
||
|
||
## ✗ Step step05_login_as_cashier: Логин под Cashier — role-guard проверяется (sidebar/role guard)
|
||
|
||
Длительность: 670мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | /api/me содержит роль соответствующую системной Cashier | ✗ no Identity roles |
|
||
| api | Cashier → GET /api/organization/employees → 403 | ✗ 200 |
|
||
| api | Cashier → GET /api/sales/retail-sales — доступен | ✓ 404 |
|
||
|
||
## ✓ Step step06_create_counterparty: Admin создаёт «ТОО Тест Поставщик» (БИН + телефон)
|
||
|
||
Длительность: 452мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | POST /api/catalog/counterparties | ✓ 201 |
|
||
|
||
## ✓ Step step07_ensure_main_store: Проверить что есть main store (из bootstrap), иначе создать
|
||
|
||
Длительность: 81мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | GET /api/catalog/stores | ✓ 200 |
|
||
| db | Main store существует (от bootstrap) | ✓ Основной склад |
|
||
|
||
## ✓ Step step08_create_supply: Admin создаёт Supply Draft (3-5 товаров) и проводит (Posted)
|
||
|
||
Длительность: 99мс
|
||
|
||
## ◯ Step step09_check_stock_after_supply: GET /api/inventory/stock — quantity увеличился на supplied amount
|
||
|
||
Длительность: 1мс
|
||
|
||
## ✓ Step step10_ensure_retail_point: Проверить или создать розничную точку (кассу)
|
||
|
||
Длительность: 83мс
|
||
|
||
| Тип | Проверка | Результат |
|
||
|---|---|---|
|
||
| api | RetailPoint существует | ✓ Касса 1 |
|
||
|
||
## ◯ Step step11_create_retail_sale: Admin создаёт RetailSale, 2 позиции из приёмки, cash, Post
|
||
|
||
Длительность: 1мс
|
||
|
||
## ◯ Step step12_check_stock_after_sale: GET /api/inventory/stock — quantity уменьшился на sold amount
|
||
|
||
Длительность: 0мс
|
||
|
||
## Summary
|
||
|
||
- Passed: 8
|
||
- Failed: 1
|
||
- Warnings: 0
|
||
- Skipped: 3
|
||
|
||
## Critical bugs
|
||
|
||
### CRITICAL
|
||
|
||
- **[05] Cashier ВИДИТ список сотрудников через API**
|
||
- GET /api/organization/employees вернул 200 для Cashier; ожидается 403 (нет [Authorize(Roles="Admin")] на List? или Cashier имеет Identity-Admin)
|
||
- Fix: Поставить [Authorize(Roles="Admin")] на List + проверить что AddToRoleAsync(...,"Cashier") а не "Admin")
|
||
|
||
### HIGH
|
||
|
||
- **[08] В реестре товаров < 3 позиций**
|
||
- Сценарий ожидает что после reset_db реестр сохранён. Проверь что preconditions не зачищают products.
|
||
|
||
## Logic gaps
|
||
|
||
- SuperAdmin /organizations принимает любой текст в поле phone — серверной валидации ФЛК нет (только в /api/auth/signup для самозаполнения).
|
||
- Cashier у созданного через POST /employees не получает Identity-роль "Cashier" — серверная авторизация на /api/sales/retail требует роли Admin или Cashier; нужно либо сидить Identity-роль из org-роли, либо переделать [Authorize] на permissions.
|