test(web): add coverage for isPRRateLimited, computeStats, getAlerts, and Dashboard#128
test(web): add coverage for isPRRateLimited, computeStats, getAlerts, and Dashboard#128AgentWrapper wants to merge 1 commit intomainfrom
Conversation
… and Dashboard
Fixes a missed isPRRateLimited guard ("Data not loaded" blocker was not
treated as stale, causing enrichment-timeout sessions to be misclassified
as needing attention), then adds the unit tests that would have caught it.
## Test additions
- `types.test.ts`: 7 tests for isPRRateLimited (empty, unrelated blockers,
rate-limit sentinel, Data-not-loaded enrichment timeout, multiple blockers)
plus 2 getAttentionLevel integration tests verifying stale PRs stay "working"
- `serialize.test.ts`: 6 tests for computeStats (zero sessions, total count,
active-only working count, open-state PR count, pending review count)
- `components.test.tsx`: 7 getAlerts edge-case tests (reviewDecision=none,
draft bypass, merge conflict alert + action, rate-limited no-alerts,
closed/merged no-alerts) and 11 Dashboard smoke tests (empty state, session
counts, attention-zone grouping, orchestrator link, rate-limit banner
show/hide/dismiss, PR table presence)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
|
|
||
| // ── computeStats ────────────────────────────────────────────────────── | ||
|
|
||
| import { computeStats } from "../serialize"; |
There was a problem hiding this comment.
Duplicate import of computeStats in same file
Low Severity
computeStats is imported from "../serialize" twice in the same file — once at line 23 (added to the existing import block) and again at line 983 (a standalone import alongside the new makeSession/makePR import). The second computeStats import is redundant; only the makeSession/makePR import on line 984 is actually needed there.
Additional Locations (1)
| return ( | ||
| pr.mergeability.blockers.includes("API rate limited or unavailable") || | ||
| pr.mergeability.blockers.includes("Data not loaded") | ||
| ); |
There was a problem hiding this comment.
Misleading "rate limited" banner for enrichment timeouts
Low Severity
Expanding isPRRateLimited to also match "Data not loaded" (enrichment timeout) causes the Dashboard's rate-limit banner to display "GitHub API rate limited" for sessions that merely timed out during server-side enrichment. The banner text is factually incorrect for the timeout case — the GitHub API may not be rate-limited at all. Users could investigate rate limits when the actual problem is network latency or slow enrichment. The function's broadened semantics no longer match its name or the hardcoded banner copy that depends on it.


Summary
isPRRateLimitednow also returnstruefor the"Data not loaded"blocker, which is set when server-side PR enrichment times out (4sPromise.race). Without this, sessions with timed-out enrichment had their defaultciStatus=none/reviewDecision=nonetreated as real data, causinggetAttentionLevelto misclassify them as"pending"or"review"instead of"working".Test additions
types.test.tsisPRRateLimitedunit tests +getAttentionLevelintegrationserialize.test.tscomputeStats(zero, total count, working count, open PRs, needsReview)components.test.tsxgetAlertsedge cases (reviewDecision=none, draft bypass, merge conflict, rate-limited, closed/merged)components.test.tsxDashboardcomponent (empty state, session counts, attention zones, orchestrator link, rate-limit banner, PR table)Test plan
pnpm test— all 367 tests passpnpm typecheck— no type errorspnpm lint— no lint errors🤖 Generated with Claude Code