Skip to content

test(health): isolate lag-only degradation for checks.indexer.status - #1388

Open
Ajibose wants to merge 1 commit into
LabsCrypt:mainfrom
Ajibose:test/health-lag-degradation-status
Open

test(health): isolate lag-only degradation for checks.indexer.status#1388
Ajibose wants to merge 1 commit into
LabsCrypt:mainfrom
Ajibose:test/health-lag-degradation-status

Conversation

@Ajibose

@Ajibose Ajibose commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Closes #1294

Summary

Audit issue #1294 asked for a test that isolates lag-only indexer
degradation and asserts the granular checks.indexer.status field
reflects it (matching the top-level status), per the mismatch
described in UX Refinement #34.

Honest status of the underlying bug: it was already fixed by prior
work — PR #1375 / commit 99a79c4 (fix: report indexer lag in checks.indexer.status breakdown, closing #1236) changed
checks.indexer.status in backend/src/routes/health.routes.ts from:

status: !indexerEnabled ? 'disabled' : indexerFailureDegraded ? 'degraded' : 'ok',

to:

status: !indexerEnabled ? 'disabled' : indexerFailureDegraded || indexerLagDegraded ? 'degraded' : 'ok',

That same PR also added a test ('returns 503 when DB is up, indexer enabled, and lag exceeds 60 s') that sets lag = 120s and asserts
checks.indexer.status === 'degraded'. So functionally the coverage
gap the audit flagged is mostly closed already — but that test relies
implicitly on beforeEach's default event counters (degraded: false,
eventsFailed: 0) rather than explicitly asserting them in the test
body, so it doesn't visibly prove failure-rate degradation was not a
contributing factor. This PR closes that remaining ambiguity with a
new, explicitly-isolated test rather than a near-duplicate.

I verified this by:

  1. Running the current test suite (npm run test:unit) — all 40 files
    / 316 tests pass, including the existing lag test.
  2. Temporarily reverting the checks.indexer.status line to the
    pre-fix: report indexer lag in checks.indexer.status breakdown (#1236) #1375 buggy version and re-running tests/health.test.ts — both
    the existing lag test and the new test correctly failed
    (expected 'ok' to be 'degraded'), confirming the new test would
    have caught this regression had it not already been fixed.
  3. Restoring the fix and re-running the full suite — all tests pass
    again.

Changes

  • backend/tests/health.test.ts: added one new test,
    'returns checks.indexer.status "degraded" for lag-only degradation, with failure-rate signals asserted healthy (#1294)', placed after
    the existing lag-exceeds-threshold test. It:
    • Sets STREAM_CONTRACT_ID (indexer enabled) and indexer state lag
      to 120s (makeState(120), > the 60s threshold).
    • Explicitly mocks sorobanEventWorker.getEventCounters() to return
      healthy failure-rate signals (eventsFailed: 0, degraded: false,
      non-zero eventsProcessed) instead of relying on beforeEach
      defaults implicitly.
    • Asserts res.status === 503 and res.body.status === 'degraded'.
    • Asserts res.body.eventsFailed === 0 and
      res.body.indexerDegraded === false — proving failure-rate
      degradation was NOT a contributing factor.
    • Asserts res.body.checks.indexer.status === 'degraded',
      checks.indexer.enabled === true,
      checks.indexer.lagSeconds > 60, and
      checks.database.status === 'ok' — proving lag alone drove the
      granular breakdown to "degraded".

No changes were needed in backend/src/routes/health.routes.ts — the
checks.indexer.status computation already correctly ORs
indexerFailureDegraded and indexerLagDegraded.

How to test

cd backend
npm install
npx prisma generate
npm run test:unit

All 40 test files / 316 tests pass. tests/health.test.ts now has 8
tests (was 7).

To see the new test actually catch a regression, revert line 166 of
backend/src/routes/health.routes.ts to
status: !indexerEnabled ? 'disabled' : indexerFailureDegraded ? 'degraded' : 'ok',
and re-run npx vitest run tests/health.test.ts — both the existing
lag test and the new test fail.

Add an explicitly-isolated test that induces indexerLagDegraded alone
(lag > 60s, failure-rate counters healthy) and asserts
checks.indexer.status reflects it as "degraded", while also asserting
eventsFailed/indexerDegraded stay healthy so the test can't pass on a
failure-rate coincidence. The prior lag test relied on beforeEach
defaults implicitly rather than asserting isolation explicitly.

Closes LabsCrypt#1294
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Audit] No test asserts checks.indexer.status reflects lag-based degradation

1 participant