food-market/tests/e2e/reports/full-cycle-2026-05-07T19-04-12-955Z.md
nns 7bb941259a
Some checks are pending
CI / POS (WPF, Windows) (push) Waiting to run
CI / Backend (.NET 8) (push) Successful in 1m20s
CI / Web (React + Vite) (push) Successful in 42s
feat(e2e): infrastructure + first full-cycle scenario + baseline report
Декларативные 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 добавим следующим коммитом, не блокирует
получение полезного отчёта.
2026-05-08 00:05:52 +05:00

5.5 KiB
Raw Blame History

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.