Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion internal/iostreams/forms.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@ func inputForm(io *IOStreams, _ context.Context, message string, cfg InputPrompt

// buildConfirmForm constructs an interactive form for yes/no confirmation prompts.
func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form {
field := huh.NewConfirm().
field := huh.NewSelect[bool]().
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

order is unchanged and the defaultValue the cursor lands on depends on the command 🫡

No
Image

Yes
Image

Title(message).
Options(
huh.NewOption("Yes", true),
huh.NewOption("No", false),
).
Value(choice)
return newForm(io, field)
}
Expand Down
30 changes: 20 additions & 10 deletions internal/iostreams/forms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,26 +105,36 @@ func TestConfirmForm(t *testing.T) {
assert.Contains(t, view, "No")
})

t.Run("default value is respected", func(t *testing.T) {
t.Run("default true starts on Yes", func(t *testing.T) {
choice := true
f := buildConfirmForm(nil, "Continue?", &choice)
f.Update(f.Init())

assert.True(t, choice)
view := ansi.Strip(f.View())
assert.Contains(t, view, style.Chevron()+" Yes")
})

t.Run("toggle changes value", func(t *testing.T) {
t.Run("default false starts on No", func(t *testing.T) {
choice := false
f := buildConfirmForm(nil, "Continue?", &choice)
f.Update(f.Init())

// Toggle to Yes
f.Update(tea.KeyPressMsg{Code: tea.KeyLeft})
assert.True(t, choice)
view := ansi.Strip(f.View())
assert.Contains(t, view, style.Chevron()+" No")
})

t.Run("arrow keys change selection", func(t *testing.T) {
choice := true
f := buildConfirmForm(nil, "Continue?", &choice)
f.Update(f.Init())

// Toggle back to No
f.Update(tea.KeyPressMsg{Code: tea.KeyRight})
// Move down to No
f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
assert.False(t, choice)

// Move back up to Yes
f.Update(tea.KeyPressMsg{Code: tea.KeyUp})
assert.True(t, choice)
})
}

Expand Down Expand Up @@ -450,12 +460,12 @@ func TestFormsAccessible(t *testing.T) {
assert.Contains(t, out.String(), "Pick one (press Enter for 1)")
})

t.Run("confirm form accepts yes/no input", func(t *testing.T) {
t.Run("confirm form accepts numbered input", func(t *testing.T) {
var choice bool
f := buildConfirmForm(io, "Continue?", &choice)

var out strings.Builder
err := f.WithOutput(&out).WithInput(strings.NewReader("y\n")).Run()
err := f.WithOutput(&out).WithInput(strings.NewReader("1\n")).Run()

assert.NoError(t, err)
assert.True(t, choice)
Expand Down
Loading