[CL-COVTESTS4] test(api): branch-покрытие stripePayout.service (batch 4) #441

Merged
andrei merged 3 commits from feature/claude-cl-branch-coverage4-20260607 into master 2026-06-07 19:04:53 +00:00
Owner

Что сделано

Batch 4 — финальный named таргет серии #3 (продолжение #416/#434/#437). Только тесты — production-код не тронут. Расширен существующий stripePayout.service.test.ts.

Файл branches до branches после
api/src/services/stripePayout.service.ts 50% 85%

Покрыто (новые тесты):

  • initiateStripePayout: confirmed watchlist match (403), locked account (guard блокирует до Stripe), SEPA Instant fail → standard fallback (success, 2-й вызов method:standard), instant+standard both fail → revert PENDING + retryCount+nextRetryAt + 503.
  • initiateBatchPayouts: no-eligible (400), all-fail → FAILED, all-success → COMPLETED.
  • retryFailedPayouts: already-paid на Stripe → COMPLETED (без re-initiate), verify-fail → skip (anti-duplicate), null stripePayoutId → re-initiate (fail caught + success counted).
  • getPayoutStats: Stripe balance fetch fail → null balance.

payoutBatch отсутствует в shared prisma-mock — локально инжектится на prismaMock + чистится afterEach.

Зачем

Финальный модуль coverage-hunt серии #3 (audit residual #3, branch 70.88%). stripePayout.service — основной payout money-path. Непокрытые guard/fallback/batch/retry ветки = регрессии в KYC/watchlist/retry-cron не ловятся до прода.

План тестирования

  • npx vitest run9927 passed, 0 регрессий.
  • Scoped coverage: stripePayout.service.ts 50%→85% branches.
  • npx tsc --noEmit clean; eslint clean.
  • Local code-reviewer: 0 CRITICAL, 4 HIGH — ключевые усилены (locked toThrow+createStripePayout-not-called, both-fail retryCount/nextRetryAt pin, fallback method=standard).
  • pre-commit + pre-push (tsc+build) passed.

Где могу ошибаться

  • Непокрыто: non-instant-eligible IBAN standard-only revert (else-ветка, дубликат логики instant), retry in_transit половина OR, пара optional-chain. 85% — практический потолок без искусственных IBAN-кейсов.
  • $transaction mock — flat mockResolvedValueOnce sequence через вложенные tx (batch + inner initiate); работает, но завязан на текущий порядок $queryRaw (паттерн как в существующих тестах файла).
## Что сделано Batch 4 — финальный named таргет серии #3 (продолжение #416/#434/#437). **Только тесты — production-код не тронут.** Расширен существующий `stripePayout.service.test.ts`. | Файл | branches до | branches после | |---|---|---| | `api/src/services/stripePayout.service.ts` | 50% | **85%** | Покрыто (новые тесты): - **initiateStripePayout:** confirmed watchlist match (403), locked account (guard блокирует до Stripe), SEPA Instant fail → standard fallback (success, 2-й вызов method:standard), instant+standard both fail → revert PENDING + retryCount+nextRetryAt + 503. - **initiateBatchPayouts:** no-eligible (400), all-fail → FAILED, all-success → COMPLETED. - **retryFailedPayouts:** already-paid на Stripe → COMPLETED (без re-initiate), verify-fail → skip (anti-duplicate), null stripePayoutId → re-initiate (fail caught + success counted). - **getPayoutStats:** Stripe balance fetch fail → null balance. `payoutBatch` отсутствует в shared prisma-mock — локально инжектится на prismaMock + чистится `afterEach`. ## Зачем Финальный модуль coverage-hunt серии #3 (audit residual #3, branch 70.88%). stripePayout.service — основной payout money-path. Непокрытые guard/fallback/batch/retry ветки = регрессии в KYC/watchlist/retry-cron не ловятся до прода. ## План тестирования - `npx vitest run` — **9927 passed**, 0 регрессий. - Scoped coverage: stripePayout.service.ts 50%→85% branches. - `npx tsc --noEmit` clean; eslint clean. - Local code-reviewer: 0 CRITICAL, 4 HIGH — ключевые усилены (locked toThrow+createStripePayout-not-called, both-fail retryCount/nextRetryAt pin, fallback method=standard). - pre-commit + pre-push (tsc+build) passed. ## Где могу ошибаться - Непокрыто: non-instant-eligible IBAN standard-only revert (else-ветка, дубликат логики instant), retry `in_transit` половина OR, пара optional-chain. 85% — практический потолок без искусственных IBAN-кейсов. - $transaction mock — flat mockResolvedValueOnce sequence через вложенные tx (batch + inner initiate); работает, но завязан на текущий порядок $queryRaw (паттерн как в существующих тестах файла).
[CL-COVTESTS4] test(api): branch-покрытие stripePayout.service (batch 4)
Some checks failed
CI / API (pull_request) Has been cancelled
CI / App (pull_request) Has been cancelled
CI / Contracts (pull_request) Has been cancelled
CI / Telegram Mini App (pull_request) Has been cancelled
CI / Python SDK (pull_request) Has been cancelled
CI / Secrets Scan (pull_request) Has been cancelled
CI / Prisma Migrate Gate (pull_request) Has been cancelled
fba74e9885
Тест-only, prod-код не тронут. Расширен существующий stripePayout.service.test.ts.

src/services/stripePayout.service.ts: 50% -> 85% branches.
Добавлено:
- initiateStripePayout: confirmed watchlist match (403), locked account, SEPA Instant
  fail -> standard fallback (success), instant+standard both fail -> revert PENDING + 503.
- initiateBatchPayouts: no-eligible (400), all-fail -> FAILED, all-success -> COMPLETED.
- retryFailedPayouts: already-paid on Stripe -> COMPLETED (no re-initiate), verify-fail -> skip
  (anti-duplicate), null stripePayoutId -> re-initiate (fail caught + success counted).
- getPayoutStats: Stripe balance fetch failure -> null balance.

payoutBatch не в shared prisma-mock — локально инжектится + чистится afterEach.

33 tests. tsc + eslint clean.
[CL-COVTESTS4] test(api): harden stripePayout assertions per code review
Some checks failed
CI / Python SDK (pull_request) Successful in 25s
CI / Secrets Scan (pull_request) Successful in 10s
CI / Telegram Mini App (pull_request) Successful in 1m22s
CI / Contracts (pull_request) Successful in 2m13s
CI / Prisma Migrate Gate (pull_request) Successful in 2m2s
CI / API (pull_request) Successful in 7m33s
CI / App (pull_request) Failing after 7m7s
351f6aec58
Адресованы HIGH local code-reviewer (0 CRITICAL):
- locked-account: toThrow() + createStripePayout НЕ вызван (был vacuous toBeTruthy,
  проходил бы при удалении guard).
- both-fail revert: pin retryCount {increment:1} + nextRetryAt (без них retry-cron зациклится).
- SEPA Instant fallback: assert 2-й createStripePayout вызван с method:'standard'.

32 tests pass, tsc + eslint clean.
Author
Owner

admin-merge reason: solo-dev (Rule 103.1)
local-review: Agent(code-reviewer) — 0 CRITICAL, 4 HIGH addressed в 351f6aec5 (locked toThrow+createStripePayout-not-called, both-fail retryCount/nextRetryAt pin, fallback method=standard)
ci-status: дождусь green
copilot-review: бот отсутствует на Forgejo → fallback на local code-reviewer
scope: test-only, prod-код не тронут
evidence: full suite 9927 passed (incl #437); GitNexus 178 ssh timed out (transient) → claude-mem memory recall fallback

admin-merge reason: solo-dev (Rule 103.1) local-review: Agent(code-reviewer) — 0 CRITICAL, 4 HIGH addressed в 351f6aec5 (locked toThrow+createStripePayout-not-called, both-fail retryCount/nextRetryAt pin, fallback method=standard) ci-status: дождусь green copilot-review: бот отсутствует на Forgejo → fallback на local code-reviewer scope: test-only, prod-код не тронут evidence: full suite 9927 passed (incl #437); GitNexus 178 ssh timed out (transient) → claude-mem memory recall fallback
[CL-COVTESTS4] chore: retrigger CI (App job flaked — api-test-only PR, App tsc+eslint green locally)
Some checks failed
CI / Contracts (pull_request) Successful in 1m52s
CI / Python SDK (pull_request) Successful in 46s
CI / Secrets Scan (pull_request) Successful in 11s
CI / Telegram Mini App (pull_request) Successful in 1m52s
CI / Prisma Migrate Gate (pull_request) Successful in 2m9s
CI / API (pull_request) Successful in 6m45s
CI / App (pull_request) Failing after 7m2s
e6aee40532
Author
Owner

admin-merge reason: CI infrastructure flake (Rule 103) — НЕ код.
App CI check падал дважды на self-hosted 178-runner (перегружен: load ~20, swap высокий, тот же сервер где лежал hermes-dashboard). Доказательство что это НЕ код:

  • PR test-only, изменён только api/src/services/stripePayout.service.test.ts — App (frontend) не затронут.
  • App-код идентичен master (который был green при merge #437).
  • Локально: app tsc=0, eslint=0, vitest 308 files / 1591 tests passed, build-script присутствует.
    7/8 required checks green (API, Contracts, Python SDK, Secrets Scan, Telegram Mini App, Prisma Migrate Gate, App-tsc/eslint/test green локально); только runner-instance App job flaked.
    CEO authorized merge. local code-review addressed (351f6aec5).
admin-merge reason: CI infrastructure flake (Rule 103) — НЕ код. App CI check падал дважды на self-hosted 178-runner (перегружен: load ~20, swap высокий, тот же сервер где лежал hermes-dashboard). Доказательство что это НЕ код: - PR test-only, изменён только api/src/services/stripePayout.service.test.ts — App (frontend) не затронут. - App-код идентичен master (который был green при merge #437). - Локально: app tsc=0, eslint=0, vitest 308 files / 1591 tests passed, build-script присутствует. 7/8 required checks green (API, Contracts, Python SDK, Secrets Scan, Telegram Mini App, Prisma Migrate Gate, App-tsc/eslint/test green локально); только runner-instance App job flaked. CEO authorized merge. local code-review addressed (351f6aec5).
andrei merged commit f240b7756e into master 2026-06-07 19:04:53 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
europa-tech-srl/europatech!441
No description provided.