detached a6ee214

test(vt): table-drive the live line-bounds test

commit
a6ee2149c92861e04e8a39be67a0332b83e22439
author
brice · · 2026-07-25 11:05 UTC
parent
24c95ef
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +38 -19
M pkg/vt/screen_write_test.go +38 -19
@@ -4,6 +4,7 @@ import (
44 "testing"
55
66 "github.com/bnema/vev/pkg/renderer"
7+ "github.com/stretchr/testify/require"
78 )
89
910 func TestWritePrintableAndUTF8(t *testing.T) {
@@ -924,26 +925,44 @@ func TestC1Controls(t *testing.T) {
924925 }
925926
926927 func TestScreenLineBoundsDescribesTheLiveGrid(t *testing.T) {
927- s := NewScreen(4, 3)
928- s.Write([]byte("abcdef")) // wraps after column 4
929-
930- bounds := s.LineBounds()
931- if len(bounds) != 3 {
932- t.Fatalf("len(LineBounds()) = %d, want 3", len(bounds))
933- }
934- if !bounds[0].Soft {
935- t.Errorf("bounds[0].Soft = false, want true (row wrapped)")
936- }
937- if bounds[1].Soft {
938- t.Errorf("bounds[1].Soft = true, want false (row did not wrap)")
939- }
940- if bounds[1].End != 2 {
941- t.Errorf("bounds[1].End = %d, want 2", bounds[1].End)
928+ tests := []struct {
929+ name string
930+ width int
931+ height int
932+ write string
933+ want []LineBound
934+ // checkOwned exercises the caller-owned-copy guarantee: it only makes
935+ // sense to check once per LineBounds() call, so it lives on the case
936+ // whose write actually produces a soft-wrapped row 0 to corrupt.
937+ checkOwned bool
938+ }{
939+ {
940+ name: "wraps after column width",
941+ width: 4,
942+ height: 3,
943+ write: "abcdef", // wraps after column 4
944+ want: []LineBound{
945+ {End: 4, Soft: true}, // row 0: filled the row and wrapped
946+ {End: 2, Soft: false}, // row 1: "ef", no wrap
947+ {End: 0, Soft: false}, // row 2: untouched
948+ },
949+ checkOwned: true,
950+ },
942951 }
943952
944- // The result is owned by the caller.
945- bounds[0] = LineBound{}
946- if !s.LineBounds()[0].Soft {
947- t.Error("mutating the result changed the screen's own boundaries")
953+ for _, tt := range tests {
954+ t.Run(tt.name, func(t *testing.T) {
955+ s := NewScreen(tt.width, tt.height)
956+ s.Write([]byte(tt.write))
957+
958+ bounds := s.LineBounds()
959+ require.Equal(t, tt.want, bounds)
960+
961+ if tt.checkOwned {
962+ // The result is owned by the caller.
963+ bounds[0] = LineBound{}
964+ require.True(t, s.LineBounds()[0].Soft, "mutating the result changed the screen's own boundaries")
965+ }
966+ })
948967 }
949968 }
@@ -4,6 +4,7 @@ import (
4 "testing"4 "testing"
5 5
6 "github.com/bnema/vev/pkg/renderer"6 "github.com/bnema/vev/pkg/renderer"
7+ "github.com/stretchr/testify/require"
7 )8 )
8 9
9 func TestWritePrintableAndUTF8(t *testing.T) {10 func TestWritePrintableAndUTF8(t *testing.T) {
@@ -924,26 +925,44 @@ func TestC1Controls(t *testing.T) {
924 }925 }
925 926
926 func TestScreenLineBoundsDescribesTheLiveGrid(t *testing.T) {927 func TestScreenLineBoundsDescribesTheLiveGrid(t *testing.T) {
927- s := NewScreen(4, 3)928+ tests := []struct {
928- s.Write([]byte("abcdef")) // wraps after column 4929+ name string
929-930+ width int
930- bounds := s.LineBounds()931+ height int
931- if len(bounds) != 3 {932+ write string
932- t.Fatalf("len(LineBounds()) = %d, want 3", len(bounds))933+ want []LineBound
933- }934+ // checkOwned exercises the caller-owned-copy guarantee: it only makes
934- if !bounds[0].Soft {935+ // sense to check once per LineBounds() call, so it lives on the case
935- t.Errorf("bounds[0].Soft = false, want true (row wrapped)")936+ // whose write actually produces a soft-wrapped row 0 to corrupt.
936- }937+ checkOwned bool
937- if bounds[1].Soft {938+ }{
938- t.Errorf("bounds[1].Soft = true, want false (row did not wrap)")939+ {
939- }940+ name: "wraps after column width",
940- if bounds[1].End != 2 {941+ width: 4,
941- t.Errorf("bounds[1].End = %d, want 2", bounds[1].End)942+ height: 3,
943+ write: "abcdef", // wraps after column 4
944+ want: []LineBound{
945+ {End: 4, Soft: true}, // row 0: filled the row and wrapped
946+ {End: 2, Soft: false}, // row 1: "ef", no wrap
947+ {End: 0, Soft: false}, // row 2: untouched
948+ },
949+ checkOwned: true,
950+ },
942 }951 }
943 952
944- // The result is owned by the caller.953+ for _, tt := range tests {
945- bounds[0] = LineBound{}954+ t.Run(tt.name, func(t *testing.T) {
946- if !s.LineBounds()[0].Soft {955+ s := NewScreen(tt.width, tt.height)
947- t.Error("mutating the result changed the screen's own boundaries")956+ s.Write([]byte(tt.write))
957+
958+ bounds := s.LineBounds()
959+ require.Equal(t, tt.want, bounds)
960+
961+ if tt.checkOwned {
962+ // The result is owned by the caller.
963+ bounds[0] = LineBound{}
964+ require.True(t, s.LineBounds()[0].Soft, "mutating the result changed the screen's own boundaries")
965+ }
966+ })
948 }967 }
949 }968 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close