Skip to content

refactor: drive real prompts in tests; extract prompt & view abstractions#8

Draft
PascalSenn wants to merge 1 commit into
mainfrom
refactor/prompt-view-abstractions
Draft

refactor: drive real prompts in tests; extract prompt & view abstractions#8
PascalSenn wants to merge 1 commit into
mainfrom
refactor/prompt-view-abstractions

Conversation

@PascalSenn

Copy link
Copy Markdown
Member

What

Replaces the IInteractionService test seam by driving the real Spectre prompt widgets over a scriptable TestConsole, and pulls console-interaction logic out of the commands into small, independently-tested abstractions. It's a console app, so it's now tested the way it runs — press keys, read rendered output.

Prompts

  • IPrompt<T> over a single Spectre widget shape, with composable decorators WithDefault<T> (return a default when the console can't show a prompt) and RequireNonEmpty<T> (re-show until at least one item is picked), exposed as chainable extensions: picker.RequireNonEmpty().WithDefault(empty).
  • WithDefault gates on both Interactive and Ansi capabilities — redirected streams and TERM=dumb terminals degrade gracefully instead of throwing from Spectre.
  • Empty-choices fail-fast guards on the multi-select prompts.

Views

  • IView : IRenderable base with a static factory per view; a view holds no console or service and is rendered with console.Write(view)not DI'd.
  • Converted BannerView (split into Logo/Banner/CuratedHelp), ErrorView, InstallationReportView, SkillListView; added InstallPlanView, UpdateNoticeView, and InstalledSkillsView.
  • A small Stacked + BlankLine primitive composes box renderables without the extra line break Rows inserts, so multi-panel output stays byte-identical.

Commands

  • Inlined AddCommandExecutor into AddCommand so it matches the other (fat) commands.
  • Selectors now expose only SelectAsync; row/order/group logic is inline. No structured renderable or raw Spectre prompt is built in a command anymore.

Misc

  • TimeProvider for InstallRecorder; monotonic Stopwatch + TimeProvider.System in FileLock instead of DateTime.UtcNow.

Tests

763 passing. Selectors and commands are exercised through the real prompts and views (keystrokes + rendered output) rather than a hand-written service double; net −1900 LOC.

🤖 Generated with Claude Code

…ions

Replace the IInteractionService test seam by driving the real Spectre prompt
widgets over a scriptable TestConsole, and pull console-interaction logic into
small, independently-tested abstractions.

Prompts
- IPrompt<T> over a single Spectre widget shape, with composable decorators
  WithDefault<T> (degrade to a default when the console can't prompt) and
  RequireNonEmpty<T> (re-show until non-empty), exposed as chainable extensions.
- WithDefault gates on BOTH Interactive and Ansi capabilities, so redirected and
  TERM=dumb runs degrade instead of throwing from Spectre.
- Empty-choices guards on the multi-select prompts.

Views
- IView : IRenderable base with a static factory per view; views hold no
  console/service and render via console.Write(view). Converted Banner (split
  into Logo/Banner/CuratedHelp), Error, InstallationReport, SkillList, and added
  InstallPlan, UpdateNotice, and InstalledSkills views. A Stacked/BlankLine
  primitive composes box renderables without Rows' extra line break.
- Views are no longer registered in DI.

Commands
- Inlined AddCommandExecutor into AddCommand to match the other commands.
- Selectors expose only SelectAsync; row/order/group logic is inline.

Misc
- TimeProvider for InstallRecorder; monotonic Stopwatch + TimeProvider.System in
  FileLock instead of DateTime.UtcNow.

Tests: 763 passing; selectors and commands are exercised through the real prompts
and views (keystrokes + rendered output) rather than a hand-written double.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant