package ui import ( "testing" "github.com/gdamore/tcell/v2" ) func TestPainterDrawsText(t *testing.T) { screen, p := newTestScreen(t, 20, 3) p.Text(2, 1, "hello", tcell.StyleDefault) screen.Show() if got := screenLines(t, screen)[1]; got != " hello " { t.Errorf("row 1 = %q", got) } } func TestPainterClipsToItsRegion(t *testing.T) { screen, root := newTestScreen(t, 20, 5) // A painter for a 5-wide box: the text must be cut off at its edge rather // than spilling across the rest of the row. box := root.Sub(Rect{X: 2, Y: 1, W: 5, H: 1}) box.Text(0, 0, "abcdefghij", tcell.StyleDefault) screen.Show() if got := screenLines(t, screen)[1]; got != " abcde " { t.Errorf("row 1 = %q, want the text clipped at column 7", got) } } func TestPainterClipsNegativeCoordinates(t *testing.T) { screen, root := newTestScreen(t, 10, 3) box := root.Sub(Rect{X: 2, Y: 1, W: 4, H: 1}) box.SetCell(-5, 0, 'X', tcell.StyleDefault) box.SetCell(0, -1, 'Y', tcell.StyleDefault) screen.Show() lines := screenLines(t, screen) for _, line := range lines { for _, r := range line { if r == 'X' || r == 'Y' { t.Errorf("a character escaped the painter's region: %v", lines) } } } } func TestSubPainterInheritsItsParentsClip(t *testing.T) { screen, root := newTestScreen(t, 20, 5) outer := root.Sub(Rect{X: 0, Y: 0, W: 6, H: 5}) // The child asks for a region reaching past the parent, so its drawing // must still stop at the parent's edge. inner := outer.Sub(Rect{X: 3, Y: 2, W: 15, H: 1}) inner.Text(0, 0, "XXXXXXXXXX", tcell.StyleDefault) screen.Show() if got := screenLines(t, screen)[2]; got != " XXX " { t.Errorf("row 2 = %q, want the child clipped by its parent", got) } } func TestPainterSizeIsItsOwnRegion(t *testing.T) { _, root := newTestScreen(t, 40, 12) if got := root.Size(); got != (Rect{W: 40, H: 12}) { t.Errorf("root Size() = %+v", got) } if got := root.Sub(Rect{X: 5, Y: 5, W: 7, H: 3}).Size(); got != (Rect{W: 7, H: 3}) { t.Errorf("sub Size() = %+v, want the region's own size at the origin", got) } } func TestPainterFillAndClear(t *testing.T) { screen, root := newTestScreen(t, 8, 3) root.Clear(tcell.StyleDefault) root.Fill(Rect{X: 1, Y: 1, W: 3, H: 1}, '#', tcell.StyleDefault) screen.Show() if got := screenLines(t, screen)[1]; got != " ### " { t.Errorf("row 1 = %q", got) } } func TestPainterLines(t *testing.T) { screen, root := newTestScreen(t, 6, 4) root.HLine(1, 0, 4, '-', tcell.StyleDefault) root.VLine(0, 1, 3, '|', tcell.StyleDefault) screen.Show() lines := screenLines(t, screen) if lines[0] != " ---- " { t.Errorf("row 0 = %q", lines[0]) } for y := 1; y < 4; y++ { if lines[y][0] != '|' { t.Errorf("row %d = %q, want a vertical line at column 0", y, lines[y]) } } } func TestTextLimitedAddsAnEllipsis(t *testing.T) { screen, root := newTestScreen(t, 20, 2) root.TextLimited(0, 0, 6, "a-very-long-name.go", tcell.StyleDefault) root.TextLimited(0, 1, 10, "short.go", tcell.StyleDefault) screen.Show() lines := screenLines(t, screen) if got := string([]rune(lines[0])[:6]); got != "a-ver…" { t.Errorf("row 0 = %q, want it cut to six cells with an ellipsis", got) } if lines[1][:8] != "short.go" { t.Errorf("row 1 = %q, want it drawn whole", lines[1]) } } func TestTextLimitedWithNoRoomDrawsNothing(t *testing.T) { screen, root := newTestScreen(t, 5, 1) if got := root.TextLimited(2, 0, 0, "hello", tcell.StyleDefault); got != 2 { t.Errorf("TextLimited returned %d, want the column it was given back", got) } screen.Show() if got := screenLines(t, screen)[0]; got != " " { t.Errorf("row 0 = %q, want nothing drawn", got) } } func TestShadeKeepsTheCharactersAndChangesTheStyle(t *testing.T) { screen, root := newTestScreen(t, 6, 2) shadow := tcell.StyleDefault.Foreground(tcell.ColorGray) root.Text(0, 0, "abcdef", tcell.StyleDefault) root.Shade(Rect{X: 2, Y: 0, W: 2, H: 1}, shadow) screen.Show() if got := screenLines(t, screen)[0]; got != "abcdef" { t.Errorf("row 0 = %q, want the characters untouched", got) } if got := styleAt(t, screen, 2, 0); got != shadow { t.Error("the shaded cell kept its old style") } if got := styleAt(t, screen, 1, 0); got == shadow { t.Error("a cell outside the shaded rectangle was restyled") } } func TestCellAtOutsideTheClipIsBlank(t *testing.T) { _, root := newTestScreen(t, 10, 3) box := root.Sub(Rect{X: 1, Y: 1, W: 2, H: 1}) if r, _ := box.CellAt(9, 9); r != ' ' { t.Errorf("CellAt outside the clip returned %q, want a space", r) } } func TestShowCursorHidesItWhenItFallsOutsideTheClip(t *testing.T) { screen, root := newTestScreen(t, 10, 3) box := root.Sub(Rect{X: 1, Y: 1, W: 3, H: 1}) box.ShowCursor(1, 0) screen.Show() if x, y, visible := screen.GetCursor(); !visible || x != 2 || y != 1 { t.Errorf("cursor at (%d, %d) visible=%v, want (2, 1) visible", x, y, visible) } box.ShowCursor(9, 0) screen.Show() if _, _, visible := screen.GetCursor(); visible { t.Error("the cursor stayed visible although it left the painter's region") } }