mirror of
https://github.com/charmbracelet/bubbles.git
synced 2026-07-21 02:59:28 -06:00
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>
152 lines
4.2 KiB
Go
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
|
|
}
|