bubbles/textinput/textinput_test.go
Charlie Tonneslan 60b0b13dfa fix(textinput): stop applying Text/Placeholder style to padding
When Width is set, View pads the input out to that width with spaces.
Both the text path and the placeholder path were running those padding
spaces through the active style, so setting a background color on either
Text or Placeholder caused the bg to extend well past the actual content,
which doesn't match how a placeholder usually reads in CSS terms (you
expect the style to scope to the text itself).

Drop the styling on the padding in both code paths so the two views
behave the same way: style covers the text, the rest is empty space.
Closes #245.

Signed-off-by: Charlie Tonneslan <cst0520@gmail.com>
2026-05-15 10:18:25 -04:00

152 lines
4.2 KiB
Go

package textinput
import (
"fmt"
"strconv"
"strings"
"testing"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
)
func Test_CurrentSuggestion(t *testing.T) {
textinput := New()
textinput.ShowSuggestions = true
suggestion := textinput.CurrentSuggestion()
expected := ""
if suggestion != expected {
t.Fatalf("Error: expected no current suggestion but was %s", suggestion)
}
textinput.SetSuggestions([]string{"test1", "test2", "test3"})
suggestion = textinput.CurrentSuggestion()
expected = ""
if suggestion != expected {
t.Fatalf("Error: expected no current suggestion but was %s", suggestion)
}
textinput.SetValue("test")
textinput.updateSuggestions()
textinput.nextSuggestion()
suggestion = textinput.CurrentSuggestion()
expected = "test2"
if suggestion != expected {
t.Fatalf("Error: expected first suggestion but was %s", suggestion)
}
textinput.Blur()
if strings.HasSuffix(textinput.View(), "test2") {
t.Fatalf("Error: suggestions should not be rendered when input isn't focused. expected \"> test\" but got \"%s\"", textinput.View())
}
}
func Test_SlicingOutsideCap(t *testing.T) {
textinput := New()
textinput.Placeholder = "作業ディレクトリを指定してください"
textinput.SetWidth(32)
textinput.View()
}
func TestChinesePlaceholder(t *testing.T) {
t.Skip("Skipping flaky test, the returned view seems incorrect. TODO: Needs investigation.")
textinput := New()
textinput.Placeholder = "输入消息..."
textinput.SetWidth(20)
got := textinput.View()
expected := "> 输入消息... "
if got != expected {
t.Fatalf("expected %q but got %q", expected, got)
}
}
func TestPlaceholderTruncate(t *testing.T) {
t.Skip("Skipping flaky test, the returned view seems incorrect. TODO: Needs investigation.")
textinput := New()
textinput.Placeholder = "A very long placeholder, or maybe not so much"
textinput.SetWidth(10)
got := textinput.View()
expected := "> A very …"
if got != expected {
t.Fatalf("expected %q but got %q", expected, got)
}
}
func ExampleValidateFunc() {
creditCardNumber := New()
creditCardNumber.Placeholder = "4505 **** **** 1234"
creditCardNumber.Focus()
creditCardNumber.CharLimit = 20
creditCardNumber.SetWidth(30)
creditCardNumber.Prompt = ""
// This anonymous function is a valid function for ValidateFunc.
creditCardNumber.Validate = func(s string) error {
// Credit Card Number should a string less than 20 digits
// It should include 16 integers and 3 spaces
if len(s) > 16+3 {
return fmt.Errorf("CCN is too long")
}
if len(s) == 0 || len(s)%5 != 0 && (s[len(s)-1] < '0' || s[len(s)-1] > '9') {
return fmt.Errorf("CCN is invalid")
}
// The last digit should be a number unless it is a multiple of 4 in which
// case it should be a space
if len(s)%5 == 0 && s[len(s)-1] != ' ' {
return fmt.Errorf("CCN must separate groups with spaces")
}
// The remaining digits should be integers
c := strings.ReplaceAll(s, " ", "")
_, err := strconv.ParseInt(c, 10, 64)
return err
}
}
func TestTextStyleAndPlaceholderStyleScopeMatch(t *testing.T) {
// Regression test for #245. The padding spaces that fill the input out to
// its full width must not pick up the Text or Placeholder style, otherwise
// the user sees a styled background extending past the actual text. Both
// the text and placeholder code paths should agree.
bg := lipgloss.NewStyle().Background(lipgloss.Color("#AFAFAF"))
m := New()
m.SetWidth(20)
m.Placeholder = "Pies"
styles := m.Styles()
styles.Focused.Text = bg
styles.Focused.Placeholder = bg
styles.Blurred.Text = bg
styles.Blurred.Placeholder = bg
m.SetStyles(styles)
m.Blur()
placeholderView := m.View()
if !strings.HasSuffix(placeholderView, strings.Repeat(" ", 17)) {
t.Errorf("placeholder view should end with unstyled padding spaces, got %q", placeholderView)
}
m.SetValue("foo")
textView := m.View()
if !strings.HasSuffix(textView, strings.Repeat(" ", 17)) {
t.Errorf("text view should end with unstyled padding spaces, got %q", textView)
}
}
func keyPress(key rune) tea.Msg {
return tea.KeyPressMsg{Code: key, Text: string(key)}
}
func sendString(m Model, str string) Model {
for _, k := range str {
m, _ = m.Update(keyPress(k))
}
return m
}