|
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Sprint 23 (adversarial): атаковали систему как недоброжелатель. Найдено 4 бага, все починены. Bug #001 (Medium): NULL-byte в Product.Name вызывал 500 без тела. Postgres TEXT не принимает \x00. Добавил NoControlChars() в ProductInputValidator + CounterpartyInputValidator. Bug #002 (Low): ProductInputValidator MaximumLength(200) конфликтовал со StringLength(500) в DTO и schema HasMaxLength(500). Сделал 500 везде. Counterparty: 200 → 255 (matches HasMaxLength). Bug #003 (CRITICAL): параллельные posting'и под Serializable выбрасывали PostgresException 40001 → middleware → 500 empty body. Добавил SerializationConflictMiddleware который мапит 40001 → 409 Conflict с {error, retryable: true}. Также SerializableRetry helper для явного retry внутри endpoint'ов с exp backoff. Применил retry-wrap к RetailSalesController.Post (PostCoreAsync extracted). Bug #004 (Low): цена 0.0000001 округлялась до 0 уже после прохождения required-price check (check был ДО RoundIfNeeded). FindMissing- RequiredPriceAsync теперь округляет перед сравнением — required цена реально > 0 после rounding. Bug reports: tests/e2e/reports/bugs/bug-00[1-4]-*.md (github-issue format). Multi-tenant attacks (cat 3): clean — все cross-org GET/PUT/DELETE дают 404, bulk-update affected=0, lists не утекают. Auth-edge (cat 2): clean — JWT tampering 401, garbage 401, CORS evil.com не получает allow-origin, fake refresh 400 invalid_grant. DOS (cat 7): clean — 50MB body 413, 200 headers 431, long URL 200. Hangfire safety (cat 8): clean — regular Admin → /hangfire 403, seed-demo использует tenant context, body org-id игнорируется. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| lib | ||
| reports | ||
| scenarios | ||
| scripts | ||
| .gitignore | ||
| package.json | ||
| playwright.config.ts | ||
| pnpm-lock.yaml | ||
| README.md | ||
| run.sh | ||
| runner.ts | ||
| tsconfig.json | ||
tests/e2e
Декларативные end-to-end сценарии. Один YAML описывает шаги, TypeScript-handler — конкретные API/UI/DB-проверки. Отчёт в Markdown.
Запуск
tests/e2e/run.sh full-cycle # полный прогон (API + UI)
tests/e2e/run.sh full-cycle --api-only # без Playwright, только axios + DB
Первый запуск установит node_modules/ (axios, pg, playwright, js-yaml, tsx).
Отчёт: tests/e2e/reports/<scenario>-<timestamp>.md.
Структура
tests/e2e/
├── runner.ts # entry: парсит YAML, прогоняет steps, пишет report
├── run.sh # wrapper: pnpm install + tsx
├── lib/
│ ├── api.ts # axios + login()
│ ├── db.ts # docker exec psql, resetTenantData(), countRows()
│ └── report.ts # markdown-аккумулятор
└── scenarios/
├── full-cycle.yml # декларация шагов
└── full-cycle.steps.ts # код handler'ов
Preconditions
Поле reset_db: true в YAML вызывает resetTenantData() в lib/db.ts. Что чистится:
- Tenant-таблицы (organizations, employees, supplies, retail_sales, …) — TRUNCATE … CASCADE.
- AspNetUsers / users / AspNetUserRoles — оставляем только
admin@food-market.local. - OpenIddict tokens — все valid → revoked.
Что НЕ чистится (берегём как baseline):
- Реестр товаров:
products,product_groups,units_of_measure,product_packagings,product_barcodes,product_prices,product_images. - Системные справочники:
countries,currencies,price_types,employee_roles. __EFMigrationsHistory,OpenIddict*таблицы (структура),platform_settings,system_settings.
После TRUNCATE — smoke login(admin@food-market.local). Если падает — runner выходит с кодом 3.
Добавление сценария
scenarios/<name>.yml— мета + списокsteps[].id.scenarios/<name>.steps.ts— экспортируй функции с теми же id (async function stepXX_foo({ ctx, step, report })).- Запусти
tests/e2e/run.sh <name>.
ctx — общий объект между шагами для прокидывания id'ов созданных сущностей и токенов сессий.
step.checks — массив проверок (api/ui/db). Если хоть одна ok=false — шаг помечен как fail.
report.bug() / report.ux() / report.gap() / report.perf() — категоризованные находки в финальной секции.
Зависимости
- Postgres контейнер
food-market-postgres(psql вызывается через docker exec). - API на
https://admin.food-market.kz(илиE2E_ADMIN_URLenv). - Playwright headless chromium для UI-проверок (
pnpm exec playwright install chromiumесли нет).