Skip to content

test(app): cover the model-picker recordRecent wiring (follow-up #1347) - #1354

Merged
Astro-Han merged 4 commits into
devfrom
claude/1347-recent-test
Jun 18, 2026
Merged

test(app): cover the model-picker recordRecent wiring (follow-up #1347)#1354
Astro-Han merged 4 commits into
devfrom
claude/1347-recent-test

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Follow-up to the #1347 review (recent-model default). Two items:

P2 — wiring test (real coverage gap). model.set(item, { recent: true }) is the only path that calls provider.recordRecent; a refactor that drops { recent: true } at the picker call site, or deletes the client call, would leave every existing test green (the ModelState, route, and defaultModel tests all exercise the server side, not this client wiring).

The picker's single write path is extracted into a dependency-free selectModel() in model-picker-select.ts, and model-picker.tsx's ModelList.onSelect calls it. The extraction is the only way to unit-test this call site: importing the component itself pulls @kobalte/core, which throws Client-only API called on the server side under the bun server-condition test runtime, so the real picker interaction is only reachable via Playwright e2e. model-picker-select.test.ts asserts the load-bearing invariant — an explicit pick and clearing the selection both pass { recent: true }. The red/green gate was confirmed: dropping the flag turns the test red.

Scope note: the negative cases (a plain programmatic model.set(item) and model.cycle() must not record) are intentionally not asserted here. There is no light real-path seam for them — set/cycle live on the LocalProvider, and exercising them would require mounting the full context, the heavy e2e the #1347 review vetoed. An earlier attempt extracted them into a createModelActions factory; that added production surface for test-only reasons (YAGNI) and was reverted — local.tsx/local.test.ts are back at the merge base.

P3 — comment trim. model-state.ts had an upstream-TUI backstory header and a PR-description-style recordRecent doc. Trimmed to the load-bearing constraints (writes the recent list in state/model.json; ENOENT starts empty; other read failures skip to protect sibling state; atomic rename for the unlocked reader).

Verification

  • bun test src/components/prompt-input/model-picker-select.test.ts src/context/local.test.ts — 8 pass (2 new picker-select + 6 unchanged local)
  • red/green gate: removing { recent: true } from selectModel turns the test red
  • bun run typecheck — app + opencode clean (CI)
  • eslint clean on both changed source files

…ctions

Behavior-preserving: pulls the model picker's set/cycle out of the Local
context's init into an exported, dependency-injected factory (mirroring
createPromptBinding). The wiring was previously only reachable by mounting
the whole context, so the recordRecent side-effect had no unit coverage.
Guards the recent-model default against a refactor that drops the wiring:
an explicit pick (set(item, { recent: true })) records to the server's
recent-model default; a plain set() and cycle() never do. The existing
ModelState/route/defaultModel tests would all stay green without this.
…ints

The header told the upstream-TUI backstory and the recordRecent doc read
like a PR description. Keep only what a maintainer needs: writes the recent
list in state/model.json, ENOENT starts empty, other read failures skip to
protect sibling state, atomic rename for the unlocked reader.
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@Astro-Han, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 48 minutes and 20 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f151e62-a650-42e3-8349-3705b4c45e61

📥 Commits

Reviewing files that changed from the base of the PR and between ac1d1e1 and 6962ff2.

📒 Files selected for processing (4)
  • packages/app/src/components/prompt-input/model-picker-select.test.ts
  • packages/app/src/components/prompt-input/model-picker-select.ts
  • packages/app/src/components/prompt-input/model-picker.tsx
  • packages/opencode/src/provider/model-state.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/1347-recent-test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added app Application behavior and product flows ui Design system and user interface harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority labels Jun 17, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested priority: P2 (includes user-path files (packages/app/src/context/local.test.ts, packages/app/src/context/local.tsx)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@Astro-Han Astro-Han added the task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work label Jun 17, 2026
The first cut extracted createModelActions and tested set(item,{recent:true})
directly. That bypassed the real wiring: deleting { recent: true } from the
model picker's onSelect left the test green, so it never guarded the regression
the PR is named for. It also added test-only production surface (an 8-param DI
factory) the component did not need — the picker already exposes a
ModelPickerState injection seam.

Drop createModelActions; restore Local's inline set/cycle. Move the picker's one
write path into model-picker-select.ts (selectModel) — a dependency-free sibling
the test imports without loading the component (Kobalte pulls solid-js's
client-only API, which throws under the server-condition test runtime; mirrors
sidebar-item-navigation.ts). ModelList.onSelect now calls selectModel, and the
unit test asserts an explicit pick passes { recent: true }. Verified by dropping
the flag and watching the test go red.

The programmatic-set / cycle "do not record recent" assertions are dropped with
the factory: they have no light real-path seam (only a full LocalProvider mount,
the heavy e2e an earlier review vetoed). The picker call site is the high-value
guard.

Claude-Session: https://claude.ai/code/session_01PWbeoRm3mmxYxKae2Kj6Z7
@Astro-Han
Astro-Han merged commit 47941a7 into dev Jun 18, 2026
40 checks passed
@Astro-Han
Astro-Han deleted the claude/1347-recent-test branch June 18, 2026 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant