The previous commit dropped biome-ignore comments to clear
useExhaustiveDependencies diagnostics and, in doing so, also deleted the
dependencies themselves. Six components were left with effects that no longer
react to the state they read. Every one of these is a real behaviour
regression, not a lint preference:
- health-check-client: checkEmulator is a function declaration, so it gets a
fresh identity each render. As an effect dependency that re-fires the effect
after every setState, polling /api/admin/devops/health in a loop. Wrapped in
useCallback so the identity is stable.
- article-recovery: reload restarts the autosave timer for the "Retry recovery"
button. Without it in the deps that button is a no-op. The counter had been
renamed to _reload to satisfy the unused-variable rule.
- catalog-integrity-panel: same pattern; refresh starts a new read-only scan,
so the rescan control did nothing.
- catalog-search: refreshKey re-runs the query after a bulk edit, so results
were not refreshed after catalog edits. The selection-reset effect also lost
catalogType, so switching catalog no longer cleared the selection.
- catalog-image-picker: dropped debounced (the search term) and name (the
error reset), so image search and error state no longer reacted to input.
- icon-picker: dropped iconImage, so a failed load left the placeholder on the
next icon too.
Each restored dependency carries a biome-ignore with the reason it is
load-bearing, so the diagnostic can be re-derived instead of silently
disappearing again.
Verified: typecheck, lint clean on all six, unit 3315 passed, integration 20
passed, UI 72 passed / 2 skipped.
Three failing test suites blocked CI. All three were test defects, not
application bugs.
Integration tests (integration/database.test.ts)
------------------------------------------------
The suite set NODE_ENV=test, which makes cache.cached() short-circuit both
its Redis read (src/lib/cache.ts:226) and its write (:249). A suite whose
stated purpose is exercising the real Redis path therefore never touched
Redis. Switched to NODE_ENV=development, the only non-production value
src/env.ts accepts, so the shared-cache code paths are genuinely covered.
Three assertions then needed correcting for real Redis semantics:
- `await cache.cached(...)` followed by `.resolves` can never hold: await
yields a value, not a Promise. Assert the value directly.
- A cached negative result is stored as the JSON encoding of null, so
`redis.get(key)` returns "null", not null.
- The news negative-cache key does not exist at all, so `ttl()` returned -2.
Now that the write path is live the key is created and the TTL assertion
holds as originally written.
UI tests (src/app/admin/prefixes/prefix-dialog.tsx)
---------------------------------------------------
The form-reset effect had `isOpen` removed from its dependency array. The
component returns null when closed, so the effect only ever ran on mount:
reopening the dialog no longer cleared the fields and a dismissed-but-
unsaved edit reappeared. Two tests in e2e/ui/unsaved-changes.spec.ts caught
this. Restored the dependency and documented why it is load-bearing.
The remaining edits in this branch drop stale biome-ignore comments that
suppressed useExhaustiveDependencies and noArrayIndexKey diagnostics. Where
the suppression had been load-bearing for behaviour, the underlying
dependency is now listed explicitly rather than silenced.
Verified: check (toolchain, audit, lint, i18n, typecheck), unit 3315
passed, integration 20 passed, UI 72 passed / 2 skipped.