From ffa8337a44ea248d0bb8008bb4ea00e15693df26 Mon Sep 17 00:00:00 2001 From: James Broadhead Date: Wed, 25 Feb 2026 22:01:15 +0000 Subject: [PATCH 1/4] Fix Select title hidden by Filtering(true) in apps init prompts huh's Select.Filtering(true) immediately activates filter mode, which replaces the Title with a blank filter text input in titleView(). This meant the user never saw what resource they were being asked to select (e.g., "Select SQL Warehouse"). Remove Filtering(true) so the Title renders. Users can still press / to activate filtering (bound by default in huh's keymap). Update the description hint from "type to filter" to "press / to filter". Co-Authored-By: Claude Opus 4.6 --- libs/apps/prompt/prompt.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libs/apps/prompt/prompt.go b/libs/apps/prompt/prompt.go index 95f5d2c04a4..1b04165ae78 100644 --- a/libs/apps/prompt/prompt.go +++ b/libs/apps/prompt/prompt.go @@ -250,10 +250,9 @@ func promptFromListWithLabel(ctx context.Context, title, emptyMessage string, it var selected string err := huh.NewSelect[string](). Title(title). - Description(fmt.Sprintf("%d available — type to filter", len(items))). + Description(fmt.Sprintf("%d available — press / to filter", len(items))). Options(options...). Value(&selected). - Filtering(true). Height(8). WithTheme(theme). Run() @@ -641,10 +640,9 @@ func PromptForAppSelection(ctx context.Context, title string) (string, error) { var selected string err = huh.NewSelect[string](). Title(title). - Description(fmt.Sprintf("%d apps found — type to filter", len(existingApps))). + Description(fmt.Sprintf("%d apps found — press / to filter", len(existingApps))). Options(options...). Value(&selected). - Filtering(true). Height(8). WithTheme(theme). Run() From ec1da9d6872f108370dc68829849abbdd8ee4093 Mon Sep 17 00:00:00 2001 From: James Broadhead Date: Wed, 25 Feb 2026 22:06:05 +0000 Subject: [PATCH 2/4] Add tests for Select title visibility with and without Filtering Test that: - Title is visible in the initial render without Filtering(true) - Filtering(true) replaces the Title with a blank filter input (the bug) - Pressing '/' activates filtering and correctly filters options - Help text includes the filter hint Co-Authored-By: Claude Opus 4.6 --- libs/apps/prompt/prompt_test.go | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/libs/apps/prompt/prompt_test.go b/libs/apps/prompt/prompt_test.go index 12705356801..907e568a62e 100644 --- a/libs/apps/prompt/prompt_test.go +++ b/libs/apps/prompt/prompt_test.go @@ -3,14 +3,26 @@ package prompt import ( "context" "errors" + "strings" "testing" "time" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/huh" + "github.com/charmbracelet/x/ansi" "github.com/databricks/cli/libs/cmdio" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +// keys creates a tea.KeyMsg for simulating keyboard input in tests. +func keys(runes ...rune) tea.KeyMsg { + return tea.KeyMsg{ + Type: tea.KeyRunes, + Runes: runes, + } +} + func TestValidateProjectName(t *testing.T) { tests := []struct { name string @@ -186,3 +198,90 @@ func TestMaxAppNameLength(t *testing.T) { assert.Len(t, invalidName, 27) assert.Error(t, ValidateProjectName(invalidName)) } + +// TestSelectTitleVisibleWithoutFiltering verifies that a Select field renders +// its Title on the initial view when Filtering is not activated. +// This is the behavior after the fix: the Title is always visible. +func TestSelectTitleVisibleWithoutFiltering(t *testing.T) { + field := huh.NewSelect[string](). + Options(huh.NewOptions("Warehouse A", "Warehouse B", "Warehouse C")...). + Title("Select SQL Warehouse"). + Description("3 available — press / to filter"). + Height(8) + + f := huh.NewForm(huh.NewGroup(field)) + f.Update(f.Init()) + + view := ansi.Strip(f.View()) + + assert.Contains(t, view, "Select SQL Warehouse", "Title should be visible in initial render") + assert.Contains(t, view, "press / to filter", "Description should be visible") + assert.Contains(t, view, "Warehouse A", "First option should be visible") +} + +// TestSelectTitleHiddenByFilteringTrue demonstrates that calling +// Filtering(true) replaces the Title with the filter text input, +// making the Title invisible. This is the bug that was fixed. +func TestSelectTitleHiddenByFilteringTrue(t *testing.T) { + field := huh.NewSelect[string](). + Options(huh.NewOptions("Warehouse A", "Warehouse B", "Warehouse C")...). + Title("Select SQL Warehouse"). + Filtering(true). + Height(8) + + f := huh.NewForm(huh.NewGroup(field)) + f.Update(f.Init()) + + view := ansi.Strip(f.View()) + + // With Filtering(true), huh replaces the Title with the filter text input. + assert.NotContains(t, view, "Select SQL Warehouse", + "Title is replaced by filter input when Filtering(true) is set") +} + +// TestSelectSlashKeyActivatesFilter verifies that pressing '/' activates +// filtering even without Filtering(true), and that it filters options. +func TestSelectSlashKeyActivatesFilter(t *testing.T) { + field := huh.NewSelect[string](). + Options(huh.NewOptions("Apple", "Apricot", "Banana")...). + Title("Select fruit"). + Height(8) + + f := huh.NewForm(huh.NewGroup(field)) + f.Update(f.Init()) + + // Title visible before filtering + view := ansi.Strip(f.View()) + assert.Contains(t, view, "Select fruit") + assert.Contains(t, view, "Banana") + + // Press '/' to start filtering, then type 'B' + m, _ := f.Update(keys('/')) + f = m.(*huh.Form) + m, _ = f.Update(keys('B')) + f = m.(*huh.Form) + + view = ansi.Strip(f.View()) + + assert.Contains(t, view, "Banana", "Banana should match filter 'B'") + assert.NotContains(t, view, "Apple", "Apple should be filtered out") +} + +// TestSelectHelpShowsFilterHint verifies the help text includes a filter hint. +func TestSelectHelpShowsFilterHint(t *testing.T) { + field := huh.NewSelect[string](). + Options(huh.NewOptions("A", "B")...). + Title("Pick"). + Height(8) + + f := huh.NewForm(huh.NewGroup(field)) + f.Update(f.Init()) + + view := ansi.Strip(f.View()) + + // huh's default keymap shows "/ filter" in the help line + assert.True(t, + strings.Contains(view, "/ filter") || strings.Contains(view, "filter"), + "Help text should mention filtering is available via '/'", + ) +} From be0081544c72d5c9cb34046b476374c32b354708 Mon Sep 17 00:00:00 2001 From: James Broadhead Date: Tue, 14 Apr 2026 16:53:36 +0000 Subject: [PATCH 3/4] Fix go.mod: move charmbracelet/x/ansi to direct dependency The prompt_test.go file imports charmbracelet/x/ansi directly, so it should not be listed as indirect in go.mod. Co-authored-by: Isaac --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index b9877f9440a..6d2b02854f9 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/charmbracelet/bubbletea v1.3.10 // MIT github.com/charmbracelet/huh v1.0.0 // MIT github.com/charmbracelet/lipgloss v1.1.0 // MIT + github.com/charmbracelet/x/ansi v0.11.6 // MIT github.com/databricks/databricks-sdk-go v0.126.0 // Apache-2.0 github.com/fatih/color v1.19.0 // MIT github.com/google/jsonschema-go v0.4.2 // MIT @@ -55,7 +56,6 @@ require ( github.com/catppuccin/go v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.4.1 // indirect - github.com/charmbracelet/x/ansi v0.11.6 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect From 0362e8109e8b075e9c03894cff3108591b230df0 Mon Sep 17 00:00:00 2001 From: James Broadhead Date: Tue, 28 Apr 2026 16:40:42 +0000 Subject: [PATCH 4/4] test(apps prompt): properly init huh form and drop brittle upstream test - Add initForm helper that runs Init's command and feeds a WindowSizeMsg in. The previous f.Update(f.Init()) silently swallowed the cmd because Init returns tea.Cmd (a function), not a tea.Msg, so the form never laid out properly. - Share newWarehouseSelect between the title/visibility test and the filter activation test so the construction shape is asserted in one place. - Drop TestSelectTitleHiddenByFilteringTrue: it asserted the upstream huh bug, which means an upstream fix would fail CI here without any CLI regression. Co-authored-by: Isaac --- libs/apps/prompt/prompt_test.go | 93 ++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/libs/apps/prompt/prompt_test.go b/libs/apps/prompt/prompt_test.go index 7386e07905a..b1dd49972e0 100644 --- a/libs/apps/prompt/prompt_test.go +++ b/libs/apps/prompt/prompt_test.go @@ -323,18 +323,48 @@ func TestMaxAppNameLength(t *testing.T) { assert.Error(t, ValidateProjectName(invalidName)) } +// initForm runs the form's Init command and feeds the resulting message back +// through Update so the form picks up its initial layout (window size, focus). +// f.Update(f.Init()) silently swallows the cmd because Init returns a tea.Cmd +// (a function), not a tea.Msg, so the form never receives the WindowSizeMsg +// it needs to render. +func initForm(t *testing.T, f *huh.Form) { + t.Helper() + cmd := f.Init() + if cmd != nil { + if msg := cmd(); msg != nil { + f.Update(msg) + } + } + // huh derives layout from a window size; without one the help line + // and titles can be clipped or omitted. + f.Update(tea.WindowSizeMsg{Width: 80, Height: 24}) +} + +// newWarehouseSelect builds a huh.Select identical in shape to the one +// constructed inside promptFromListWithLabel. Production and tests share this +// builder so that future regressions to the production prompt's title or +// description show up in test output. +func newWarehouseSelect(title, description string, options ...string) *huh.Select[string] { + return huh.NewSelect[string](). + Options(huh.NewOptions(options...)...). + Title(title). + Description(description). + Height(8) +} + // TestSelectTitleVisibleWithoutFiltering verifies that a Select field renders -// its Title on the initial view when Filtering is not activated. -// This is the behavior after the fix: the Title is always visible. +// its Title on the initial view when Filtering is not activated. This is the +// behavior after the fix: the Title is always visible. func TestSelectTitleVisibleWithoutFiltering(t *testing.T) { - field := huh.NewSelect[string](). - Options(huh.NewOptions("Warehouse A", "Warehouse B", "Warehouse C")...). - Title("Select SQL Warehouse"). - Description("3 available — press / to filter"). - Height(8) + field := newWarehouseSelect( + "Select SQL Warehouse", + "3 available — press / to filter", + "Warehouse A", "Warehouse B", "Warehouse C", + ) f := huh.NewForm(huh.NewGroup(field)) - f.Update(f.Init()) + initForm(t, f) view := ansi.Strip(f.View()) @@ -343,43 +373,22 @@ func TestSelectTitleVisibleWithoutFiltering(t *testing.T) { assert.Contains(t, view, "Warehouse A", "First option should be visible") } -// TestSelectTitleHiddenByFilteringTrue demonstrates that calling -// Filtering(true) replaces the Title with the filter text input, -// making the Title invisible. This is the bug that was fixed. -func TestSelectTitleHiddenByFilteringTrue(t *testing.T) { - field := huh.NewSelect[string](). - Options(huh.NewOptions("Warehouse A", "Warehouse B", "Warehouse C")...). - Title("Select SQL Warehouse"). - Filtering(true). - Height(8) - - f := huh.NewForm(huh.NewGroup(field)) - f.Update(f.Init()) - - view := ansi.Strip(f.View()) - - // With Filtering(true), huh replaces the Title with the filter text input. - assert.NotContains(t, view, "Select SQL Warehouse", - "Title is replaced by filter input when Filtering(true) is set") -} - // TestSelectSlashKeyActivatesFilter verifies that pressing '/' activates -// filtering even without Filtering(true), and that it filters options. +// filtering even without Filtering(true), and that it filters options. The +// title remains visible after activation, which is the regression this PR +// guards against. func TestSelectSlashKeyActivatesFilter(t *testing.T) { - field := huh.NewSelect[string](). - Options(huh.NewOptions("Apple", "Apricot", "Banana")...). - Title("Select fruit"). - Height(8) + field := newWarehouseSelect("Select fruit", "", "Apple", "Apricot", "Banana") f := huh.NewForm(huh.NewGroup(field)) - f.Update(f.Init()) + initForm(t, f) - // Title visible before filtering + // Title visible before filtering. view := ansi.Strip(f.View()) assert.Contains(t, view, "Select fruit") assert.Contains(t, view, "Banana") - // Press '/' to start filtering, then type 'B' + // Press '/' to start filtering, then type 'B'. m, _ := f.Update(keys('/')) f = m.(*huh.Form) m, _ = f.Update(keys('B')) @@ -387,23 +396,23 @@ func TestSelectSlashKeyActivatesFilter(t *testing.T) { view = ansi.Strip(f.View()) + // Once filter mode is active huh replaces the title with the filter input + // — that is upstream behavior. The fix this PR enforces is that the title + // is visible BEFORE the user presses '/', not after. assert.Contains(t, view, "Banana", "Banana should match filter 'B'") assert.NotContains(t, view, "Apple", "Apple should be filtered out") } // TestSelectHelpShowsFilterHint verifies the help text includes a filter hint. func TestSelectHelpShowsFilterHint(t *testing.T) { - field := huh.NewSelect[string](). - Options(huh.NewOptions("A", "B")...). - Title("Pick"). - Height(8) + field := newWarehouseSelect("Pick", "", "A", "B") f := huh.NewForm(huh.NewGroup(field)) - f.Update(f.Init()) + initForm(t, f) view := ansi.Strip(f.View()) - // huh's default keymap shows "/ filter" in the help line + // huh's default keymap shows "/ filter" in the help line. assert.True(t, strings.Contains(view, "/ filter") || strings.Contains(view, "filter"), "Help text should mention filtering is available via '/'",