Integration-тесты на PortfolioRepository.publish: откат транзакции при сбое посреди записи и защита от устаревшей попытки (claimed fence). Сбой внедряется через jest.spyOn(prisma, '$transaction'), как решил владелец в Issue.
Только test/tbank-portfolio-publish.e2e-spec.ts; production-код не изменён.
Rollback: snapshot с RUB и USD; первая tbankPortfolioValuePoint.upsert проходит в БД, вторая падает. Проверяется по SQLite: snapshot, fetchedAt, dataRevision прежние, новых points нет, work остался running.
Claimed fence на реальной БД без spy: устаревший attemptId, work в complete, invalidToken: true → publish() === false, ничего не записано.
Фикстуры типизированы через satisfies PortfolioDto.
Verification
Мутанты (откачены): запись point до транзакции → rollback-тест падает; удалён if (!claimed.count) → claimed-тесты падают; удалён attemptId из CAS where → stale-тест падает.
Целевой суит 3 раза подряд (5/5); npm run test:e2e, npm run lint, npm run typecheck:test — зелёные.
Независимый review: замечания (ложная зелёность по points, claimed через spy) исправлены.
## Summary
Integration-тесты на `PortfolioRepository.publish`: откат транзакции при сбое посреди записи и защита от устаревшей попытки (claimed fence). Сбой внедряется через `jest.spyOn(prisma, '$transaction')`, как решил владелец в Issue.
## Linked Issue
Refs WealthLedger/backend#105
## Changes
- Только `test/tbank-portfolio-publish.e2e-spec.ts`; production-код не изменён.
- Rollback: snapshot с RUB и USD; первая `tbankPortfolioValuePoint.upsert` проходит в БД, вторая падает. Проверяется по SQLite: snapshot, `fetchedAt`, `dataRevision` прежние, новых points нет, work остался `running`.
- Claimed fence на реальной БД без spy: устаревший `attemptId`, work в `complete`, `invalidToken: true` → `publish() === false`, ничего не записано.
- Фикстуры типизированы через `satisfies PortfolioDto`.
## Verification
- Мутанты (откачены): запись point до транзакции → rollback-тест падает; удалён `if (!claimed.count)` → claimed-тесты падают; удалён `attemptId` из CAS `where` → stale-тест падает.
- Целевой суит 3 раза подряд (5/5); `npm run test:e2e`, `npm run lint`, `npm run typecheck:test` — зелёные.
- Независимый review: замечания (ложная зелёность по points, claimed через spy) исправлены.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Integration-тесты на
PortfolioRepository.publish: откат транзакции при сбое посреди записи и защита от устаревшей попытки (claimed fence). Сбой внедряется черезjest.spyOn(prisma, '$transaction'), как решил владелец в Issue.Linked Issue
Refs WealthLedger/backend#105
Changes
test/tbank-portfolio-publish.e2e-spec.ts; production-код не изменён.tbankPortfolioValuePoint.upsertпроходит в БД, вторая падает. Проверяется по SQLite: snapshot,fetchedAt,dataRevisionпрежние, новых points нет, work осталсяrunning.attemptId, work вcomplete,invalidToken: true→publish() === false, ничего не записано.satisfies PortfolioDto.Verification
if (!claimed.count)→ claimed-тесты падают; удалёнattemptIdиз CASwhere→ stale-тест падает.npm run test:e2e,npm run lint,npm run typecheck:test— зелёные.e7827dcac6toc1a78fc240