docs(e2e): зелёные отчёты auth/catalog/stock edge-прогонов
auth-edge 10/10, catalog-edge 12/12, stock-invariant-deep 10/10. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9f0f071193
commit
defe6860fc
105
tests/e2e/reports/auth-edge-2026-05-26T06-01-45-719Z.md
Normal file
105
tests/e2e/reports/auth-edge-2026-05-26T06-01-45-719Z.md
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# E2E report: auth-edge
|
||||||
|
|
||||||
|
Запущен: 2026-05-26T06:01:37.536Z
|
||||||
|
Длительность: 5.3с
|
||||||
|
|
||||||
|
**Итог:** 10 ✓ / 0 ✗ / 0 ⚠ / 0 ◯ (всего 10)
|
||||||
|
|
||||||
|
## ✓ Step step01_bootstrap_admin: SuperAdmin создаёт орг + админа, получаем access+refresh
|
||||||
|
|
||||||
|
Длительность: 2224мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Initial login → 200 | ✓ status=200 |
|
||||||
|
| api | Получили access + refresh | ✓ |
|
||||||
|
|
||||||
|
## ✓ Step step02_refresh_token_works: Refresh: старый access обменивается на новые access+refresh
|
||||||
|
|
||||||
|
Длительность: 394мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | POST /connect/token (refresh) → 200 | ✓ status=200 |
|
||||||
|
| api | Новый access ≠ старый | ✓ |
|
||||||
|
| api | Новый refresh ≠ старый (rotation) | ✓ |
|
||||||
|
| api | Новый access → /api/me 200 | ✓ status=200 |
|
||||||
|
|
||||||
|
## ✓ Step step03_refresh_token_rotates: После refresh — старый refresh-token больше не работает (rotation)
|
||||||
|
|
||||||
|
Длительность: 145мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Повторное использование старого refresh → 4xx | ✓ status=400 error=invalid_grant |
|
||||||
|
|
||||||
|
## ✓ Step step04_invalid_refresh_rejected: Невалидный refresh-token возвращает 400 invalid_grant
|
||||||
|
|
||||||
|
Длительность: 88мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Случайный refresh → 4xx | ✓ status=400 error=invalid_grant |
|
||||||
|
|
||||||
|
## ✓ Step step05_tampered_jwt_rejected: JWT с подделанным org_id (изменён без переподписи) отшивается 401
|
||||||
|
|
||||||
|
Длительность: 41мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Изменённый payload (подпись не сходится) → 401 | ✓ status=401 |
|
||||||
|
|
||||||
|
## ✓ Step step06_random_jwt_rejected: Случайный JWT-подобный токен из другого ключа отшивается 401
|
||||||
|
|
||||||
|
Длительность: 17мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Случайный HS256 «JWT» → 401 | ✓ status=401 |
|
||||||
|
|
||||||
|
## ✓ Step step07_deactivated_user_blocked: Деактивация User.IsActive=false: повторный login и refresh возвращают 400
|
||||||
|
|
||||||
|
Длительность: 503мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Login деактивированного → 4xx | ✓ status=400 |
|
||||||
|
| api | Refresh деактивированного → 4xx | ✓ status=400 error=invalid_grant |
|
||||||
|
|
||||||
|
## ✓ Step step08_archived_org_blocks_login: Архивная организация: login существующего админа возвращает 400 invalid_grant
|
||||||
|
|
||||||
|
Длительность: 489мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Архивация орг → 200/204 | ✓ status=204 |
|
||||||
|
| api | Login юзера архивной орги → 4xx | ✓ status=400 error=Организация удалена или архивирована. Обратитесь к владельцу. |
|
||||||
|
|
||||||
|
## ✓ Step step09_duplicate_signup_blocked: Повторный signup с тем же email живой орги отвергается 400
|
||||||
|
|
||||||
|
Длительность: 64мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Повторный signup на занятый email → 4xx | ✓ status=400 {"error":"Пользователь с таким email уже зарегистрирован."} |
|
||||||
|
|
||||||
|
## ✓ Step step10_orphan_signup_reactivates: Signup с email orphan-юзера (его org удалена) — реактивирует с новой org
|
||||||
|
|
||||||
|
Длительность: 1313мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | First signup → 200/201 | ✓ status=200 {"organizationId":"c629b9ea-ffe2-44ae-b091-f9fb61c27956","email":"orphan-1779775297536@example.kz"} |
|
||||||
|
| api | Re-signup orphan email → 200/201 (реактивация) | ✓ status=200 {"organizationId":"c536d5d9-f5fd-4d80-8e3e-91c2345ef2aa","email":"orphan-1779775297536@example.kz"} |
|
||||||
|
| api | Login после реактивации → 200 | ✓ status=200 |
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- Passed: 10
|
||||||
|
- Failed: 0
|
||||||
|
- Warnings: 0
|
||||||
|
- Skipped: 0
|
||||||
|
|
||||||
|
## Critical bugs
|
||||||
|
|
||||||
|
Нет.
|
||||||
119
tests/e2e/reports/catalog-edge-2026-05-26T06-02-05-506Z.md
Normal file
119
tests/e2e/reports/catalog-edge-2026-05-26T06-02-05-506Z.md
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
# E2E report: catalog-edge
|
||||||
|
|
||||||
|
Запущен: 2026-05-26T06:02:00.235Z
|
||||||
|
Длительность: 3.7с
|
||||||
|
|
||||||
|
**Итог:** 12 ✓ / 0 ✗ / 0 ⚠ / 0 ◯ (всего 12)
|
||||||
|
|
||||||
|
## ✓ Step step01_bootstrap: Орг + admin + lookups
|
||||||
|
|
||||||
|
Длительность: 1393мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Bootstrap lookups получены | ✓ |
|
||||||
|
|
||||||
|
## ✓ Step step02_empty_product_name_rejected: POST product с пустым name → 400
|
||||||
|
|
||||||
|
Длительность: 120мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | POST product с пустым name → 400 | ✓ status=400 {"type":"https://tools.ietf.org/html/rfc9110#section-15.5.1","title":"One or more validation errors occurred.","status": |
|
||||||
|
|
||||||
|
## ✓ Step step03_negative_price_rejected: POST product с отрицательной ценой amount=-100 → 400
|
||||||
|
|
||||||
|
Длительность: 11мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | POST product с amount=-100 → 400 | ✓ status=400 {"type":"https://tools.ietf.org/html/rfc9110#section-15.5.1","title":"One or more validation errors occurred.","status": |
|
||||||
|
|
||||||
|
## ✓ Step step04_oversized_name_truncated_or_rejected: POST product с name > 500 символов → 400 (превышение maxLength)
|
||||||
|
|
||||||
|
Длительность: 8мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | POST product с name=600 chars → 4xx | ✓ status=400 {"type":"https://tools.ietf.org/html/rfc9110#section-15.5.1","title":"One or more validation errors |
|
||||||
|
|
||||||
|
## ✓ Step step05_duplicate_product_article: POST второго product с тем же article → 4xx (если уникальный) или OK + проверка БД
|
||||||
|
|
||||||
|
Длительность: 1027мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | POST 1-й product с article OK | ✓ status=201 |
|
||||||
|
| api | POST 2-й product с тем же article (gap) | ✓ не запрещено сервером |
|
||||||
|
|
||||||
|
## ✓ Step step06_self_parent_group_rejected: POST product-group с parentId=собственный id (цикл) → 400
|
||||||
|
|
||||||
|
Длительность: 54мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | PUT product-group parentId=self → 4xx | ✓ status=400 {"error":"ParentId cannot be self"} |
|
||||||
|
|
||||||
|
## ✓ Step step07_delete_group_with_children: DELETE group у которой есть подгруппы → 409
|
||||||
|
|
||||||
|
Длительность: 80мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | DELETE group с детьми → 4xx | ✓ status=400 {"error":"Системную группу удалить нельзя."} |
|
||||||
|
|
||||||
|
## ✓ Step step08_delete_group_with_products: DELETE group в которой есть продукты → 409
|
||||||
|
|
||||||
|
Длительность: 11мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | DELETE group с продуктами → 4xx | ✓ status=400 {"error":"Системную группу удалить нельзя."} |
|
||||||
|
|
||||||
|
## ✓ Step step09_delete_unit_with_products: DELETE enable у unit, на которую ссылаются продукты → 409
|
||||||
|
|
||||||
|
Длительность: 34мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | DELETE enable у unit с продуктами → 4xx | ✓ status=409 {"error":"Единица используется в товарах. Перепривяжите товары на другую единицу прежде чем отключать.","products":["First","Second"]} |
|
||||||
|
|
||||||
|
## ✓ Step step10_delete_system_price_type: DELETE PriceType.IsSystem=true → 409
|
||||||
|
|
||||||
|
Длительность: 51мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | DELETE системной PriceType → 4xx | ✓ status=400 {"error":"Системная запись не может быть удалена."} |
|
||||||
|
|
||||||
|
## ✓ Step step11_second_retail_price_type: POST PriceType с IsRetail=true когда уже есть Retail → 409
|
||||||
|
|
||||||
|
Длительность: 64мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | POST второй IsRetail PriceType — 201 (флаг перенесён) или 4xx | ✓ status=201 |
|
||||||
|
| api | IsRetail=true ровно у одного PriceType (uniqueness) | ✓ count=1 |
|
||||||
|
|
||||||
|
## ✓ Step step12_delete_counterparty_with_supply: DELETE counterparty который использован в Supply → 409
|
||||||
|
|
||||||
|
Длительность: 800мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | DELETE counterparty с Supply → 4xx | ✓ status=409 {"error":"Нельзя удалить контрагента: он используется в документах или товарах.","usedAsSupplier":true,"usedAsCustomer": |
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- Passed: 12
|
||||||
|
- Failed: 0
|
||||||
|
- Warnings: 0
|
||||||
|
- Skipped: 0
|
||||||
|
|
||||||
|
## Critical bugs
|
||||||
|
|
||||||
|
Нет.
|
||||||
|
|
||||||
|
## Logic gaps
|
||||||
|
|
||||||
|
- Article у Product не уникален per-org — два товара могут иметь одинаковый артикул, путаница в учёте.
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
# E2E report: stock-invariant-deep
|
||||||
|
|
||||||
|
Запущен: 2026-05-26T06:02:08.247Z
|
||||||
|
Длительность: 6.5с
|
||||||
|
|
||||||
|
**Итог:** 10 ✓ / 0 ✗ / 0 ⚠ / 0 ◯ (всего 10)
|
||||||
|
|
||||||
|
## ✓ Step step01_bootstrap: Орг + admin + product (стартовый остаток 0)
|
||||||
|
|
||||||
|
Длительность: 1555мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Bootstrap product создан | ✓ 54af3580-d626-42e0-92b1-cc70bb3fb90d |
|
||||||
|
| db | Stock.Quantity == 0 | ✓ actual=0 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=0 sum=0 |
|
||||||
|
|
||||||
|
## ✓ Step step02_supply_a_qty_20: Supply A qty=20 → invariant stock=20, Σ movement=20
|
||||||
|
|
||||||
|
Длительность: 969мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Supply A qty=20 проведена | ✓ |
|
||||||
|
| db | Stock.Quantity == 20 | ✓ actual=20 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=20 sum=20 |
|
||||||
|
|
||||||
|
## ✓ Step step03_sale_a_qty_5: RetailSale A qty=5 → invariant stock=15, Σ movement=15
|
||||||
|
|
||||||
|
Длительность: 951мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Sale A qty=5 проведена | ✓ |
|
||||||
|
| db | Stock.Quantity == 15 | ✓ actual=15 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=15 sum=15 |
|
||||||
|
|
||||||
|
## ✓ Step step04_supply_b_qty_10: Supply B qty=10 → invariant stock=25, Σ movement=25
|
||||||
|
|
||||||
|
Длительность: 514мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Supply B qty=10 проведена | ✓ |
|
||||||
|
| db | Stock.Quantity == 25 | ✓ actual=25 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=25 sum=25 |
|
||||||
|
|
||||||
|
## ✓ Step step05_sale_b_qty_8: RetailSale B qty=8 → invariant stock=17, Σ movement=17
|
||||||
|
|
||||||
|
Длительность: 527мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Sale B qty=8 проведена | ✓ |
|
||||||
|
| db | Stock.Quantity == 17 | ✓ actual=17 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=17 sum=17 |
|
||||||
|
|
||||||
|
## ✓ Step step06_unpost_sale_a: Unpost RetailSale A → invariant stock=22, Σ movement=22
|
||||||
|
|
||||||
|
Длительность: 433мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Unpost Sale A → 200/204 | ✓ status=204 |
|
||||||
|
| db | Stock.Quantity == 22 | ✓ actual=22 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=22 sum=22 |
|
||||||
|
|
||||||
|
## ✓ Step step07_repost_sale_a: Re-post RetailSale A → invariant stock=17, Σ movement=17
|
||||||
|
|
||||||
|
Длительность: 424мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Re-post Sale A → 200/204 | ✓ status=204 |
|
||||||
|
| db | Stock.Quantity == 17 | ✓ actual=17 |
|
||||||
|
| db | Stock.Quantity == Σ StockMovement (invariant) | ✓ stock=17 sum=17 |
|
||||||
|
|
||||||
|
## ✓ Step step08_movement_count_correct: Всего StockMovement по продукту = 6 строк (2 supply + 2 sale + reverse sale + repost sale)
|
||||||
|
|
||||||
|
Длительность: 182мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| db | StockMovement содержит как минимум 4 строки | ✓ count=6 |
|
||||||
|
| db | StockMovement не более 8 строк (нет лишних дублей) | ✓ count=6 |
|
||||||
|
|
||||||
|
## ✓ Step step09_concurrent_sales_serialized: Два POST /post одновременно на один остаток — один 200, второй 409
|
||||||
|
|
||||||
|
Длительность: 600мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| api | Два Draft созданы | ✓ |
|
||||||
|
| api | Ровно один post 2xx, второй 4xx (5xx) | ✓ statuses=204,409 |
|
||||||
|
| db | Stock >= 0 (не минус из-за гонки) | ✓ stock=7 |
|
||||||
|
| db | Stock == Σ Movement после гонки | ✓ stock=7 sum=7 |
|
||||||
|
|
||||||
|
## ✓ Step step10_final_invariant: Финальный invariant после всех операций сохраняется
|
||||||
|
|
||||||
|
Длительность: 369мс
|
||||||
|
|
||||||
|
| Тип | Проверка | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| db | Финальный invariant Stock == Σ Movement | ✓ stock=7 sum=7 |
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- Passed: 10
|
||||||
|
- Failed: 0
|
||||||
|
- Warnings: 0
|
||||||
|
- Skipped: 0
|
||||||
|
|
||||||
|
## Critical bugs
|
||||||
|
|
||||||
|
Нет.
|
||||||
Loading…
Reference in a new issue