Replace the OptionsFunc-based MultiSelectWithSearch with a custom huh
Field implementation. huh's OptionsFunc runs in a goroutine, causing
data races with selection state and stale cache issues that made
selections disappear on toggle or search changes.
The custom field (multiSelectSearchField) combines a text input and
multi-select list in a single field with full control over the update
loop. Search runs asynchronously via tea.Cmd when the user presses
Enter, with a themed spinner during loading. Selections are stored in
a simple map — no goroutine races, no Eval cache, no syncAccessor.
Also adds defensive validation for mismatched Keys/Labels slices from
searchFunc.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add 'Type to search, Ctrl+U to clear' placeholder to the
MultiSelectWithSearch search input. Set WithWidth(80) in the test
harness to prevent textinput placeholder rendering panics when
there is no terminal.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace Value() pointer bindings with syncAccessor in
MultiSelectWithSearch. huh's OptionsFunc runs in a goroutine while
the main event loop writes field values, causing a data race on
shared variables. syncAccessor implements huh's Accessor interface
with a shared mutex, ensuring all reads and writes are synchronized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace manual model updates with an io.Pipe-based test harness that
drives forms through bubbletea's real event loop. Interaction helpers
(tab(), toggle(), typeKeys(), enter(), etc.) send raw terminal bytes
through io.Pipe to form.Run() in a goroutine.
Add tests for AuthToken, ConfirmDeletion, and InputHostname including
validation rejection paths. Add MultiSelectWithSearch coverage for
persistent options and empty search results.
30 tests, ~1s, all build*Form methods at 94-100% coverage.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract build*Form() methods from each huhPrompter method, separating
form construction from form.Run(). This enables testing the real form
construction code by driving it with direct model updates, adapted
from huh's own test patterns.
Tests cover Input, Select, MultiSelect, Confirm, Password,
MarkdownEditor, and MultiSelectWithSearch including a persistence
test that verifies selections survive across search query changes.
Also fixes a search cache initialization bug where the first
buildOptions("") call would skip the searchFunc due to
cachedSearchQuery defaulting to "".
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>