diff options
| author | historia <[not public]> | 2026-09-15 16:26:23 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-15 16:26:23 -0400 |
| commit | d89504c3df74706b387b8fa829dd291e31ca01c7 (patch) | |
| tree | 8924164ed1b061cca04aaa79f283d1ab0995486e /internal/ui/table_test.go | |
| parent | 0b0b25222b3131ada79ff78c28eb8bf07d977deb (diff) | |
| download | thehouseoficarus-d89504c3df74706b387b8fa829dd291e31ca01c7.tar.gz | |
fix: help topics (newplayer, title/body files), help aliases, and table width rebalancing
Diffstat (limited to 'internal/ui/table_test.go')
| -rw-r--r-- | internal/ui/table_test.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go new file mode 100644 index 0000000..68b6d32 --- /dev/null +++ b/internal/ui/table_test.go @@ -0,0 +1,91 @@ +package ui + +import ( + "strings" + "testing" + + "thehouseoficarus/internal/color" +) + +func renderWidths(t *testing.T, tt *Table, unicode bool, maxWidth int) []string { + t.Helper() + lines := tt.Render(unicode, maxWidth) + for _, l := range lines { + if vl := color.VisibleLen(l); maxWidth > 0 && vl > maxWidth+1 { + t.Errorf("line exceeds maxWidth %d: %d (%q)", maxWidth, vl, l) + } + } + // All border/content lines must be the same visible width so the box + // lines up. + widths := map[int]bool{} + for _, l := range lines { + widths[color.VisibleLen(l)] = true + } + if len(widths) > 1 { + var ws []string + for w := range widths { + ws = append(ws, string(rune('0'+w))) + } + t.Errorf("inconsistent line widths: %v", strings.Join(ws, ",")) + } + return lines +} + +func TestTableFitsWithinWidth(t *testing.T) { + tt := &Table{ + Title: "Commands", + Columns: []string{"Command", "Type", "Description"}, + Rows: [][]string{ + {"north / south / east / west / ne / nw / se / sw / up / down", "Active", "Move in a direction"}, + {"bet", "Active", "Place a casino wager (e.g. bet 100 on banker)"}, + {"attack / kill", "Active", "Attack a mob"}, + }, + } + for _, w := range []int{0, 40, 80, 100} { + lines := renderWidths(t, tt, true, w) + // Description column must never be crushed: with three columns the + // description always keeps at least a fair share of the budget. + if w == 80 { + // lines: border, title, sep, header, sep, rows... + if !strings.Contains(lines[5], "Move i") { + t.Errorf("description column crushed at width 80: %q", lines[5]) + } + } + } +} + +func TestTableNoMutation(t *testing.T) { + tt := &Table{ + Title: "T", + Columns: []string{"A", "B"}, + Rows: [][]string{{"very long cell content here", "x"}}, + } + before := tt.Columns[0] + _ = tt.Render(true, 20) + if tt.Columns[0] != before { + t.Errorf("Render mutated table columns: %q", tt.Columns[0]) + } +} + +func TestTableASCIIFallback(t *testing.T) { + tt := &Table{Title: "T", Columns: []string{"A", "B"}, Rows: [][]string{{"1", "2"}}} + lines := renderWidths(t, tt, false, 0) + if !strings.Contains(lines[0], "+") { + t.Errorf("expected ASCII border, got %q", lines[0]) + } +} + +func TestTableColoredCellWidth(t *testing.T) { + // ANSI-colored cells must be measured and padded by visible length. + red := "\x1b[31m" + reset := "\x1b[0m" + tt := &Table{Columns: []string{"A", "B"}, Rows: [][]string{{red + "hi" + reset, "x"}}} + lines := renderWidths(t, tt, true, 0) + // lines: top border, header, sep, data row, bottom border + if len(lines) < 5 { + t.Fatalf("expected 5 lines, got %d: %q", len(lines), lines) + } + if !strings.Contains(lines[3], "hi") || !strings.Contains(lines[3], "x") { + t.Errorf("unexpected row: %q", lines[3]) + } +} |
