detached c0af074

test(vt): strengthen snapshot review coverage

commit
c0af07455840ec4a313bd9923ee51efc8beb8e01
author
brice · · 2026-07-29 05:22 UTC
parent
9db9bf9
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +38 -2
M pkg/vt/screen_snapshot_test.go +38 -2
@@ -195,7 +195,7 @@ func TestScreenSnapshotFidelity(t *testing.T) {
195195 }
196196 copy(screen.Frame.Row(0), cells)
197197 screen.buffer.boundaries[0] = LineBound{End: 3, Soft: true}
198- return screen, cells, []LineBound{LineBound{End: 3, Soft: true}, LineBound{}}
198+ return screen, cells, []LineBound{{End: 3, Soft: true}, {}}
199199 },
200200 },
201201 {
@@ -225,6 +225,20 @@ func TestScreenSnapshotFidelity(t *testing.T) {
225225 }
226226 }
227227
228+func TestScreenSnapshotPreservesLogicalRowsAfterScroll(t *testing.T) {
229+ screen := NewScreen(3, 2)
230+ screen.Write([]byte("ABC"))
231+ screen.Write([]byte("DEF"))
232+ screen.Write([]byte("G"))
233+
234+ snapshot := screen.Snapshot()
235+ for y, want := range []string{"DEF", "G "} {
236+ require.Equal(t, want, rowText(snapshot.Row(y)))
237+ require.Equal(t, screen.Frame.Row(y), snapshot.Row(y))
238+ require.Equal(t, screen.LineBounds()[y], snapshot.Bound(y))
239+ }
240+}
241+
228242 func TestScreenSnapshotOwnership(t *testing.T) {
229243 tests := []struct {
230244 name string
@@ -330,9 +344,18 @@ func TestScreenSnapshotDoesNotMutateHistoryOrDamage(t *testing.T) {
330344 screen := test.make()
331345 beforeDamage := screen.CaptureDamage()
332346 var beforeHistory HistorySnapshotView
347+ var beforeRows [][]renderer.Cell
348+ var beforeBounds []LineBound
333349 beforeCap, beforeCellCap := 0, 0
334350 if screen.History() != nil {
335351 beforeHistory = screen.History().SnapshotView()
352+ beforeView := screen.History().View()
353+ beforeRows = make([][]renderer.Cell, beforeView.Len())
354+ beforeBounds = make([]LineBound, beforeView.Len())
355+ for i := range beforeRows {
356+ beforeRows[i] = beforeView.Row(i)
357+ beforeBounds[i] = beforeView.Bound(i)
358+ }
336359 beforeCap = screen.History().Cap()
337360 beforeCellCap = screen.History().CellCap()
338361 }
@@ -342,7 +365,20 @@ func TestScreenSnapshotDoesNotMutateHistoryOrDamage(t *testing.T) {
342365 afterDamage := screen.CaptureDamage()
343366 require.Equal(t, beforeDamage, afterDamage)
344367 if screen.History() != nil {
345- require.Equal(t, beforeHistory, screen.History().SnapshotView())
368+ afterHistory := screen.History().SnapshotView()
369+ afterView := screen.History().View()
370+ afterRows := make([][]renderer.Cell, afterView.Len())
371+ afterBounds := make([]LineBound, afterView.Len())
372+ for i := range afterRows {
373+ afterRows[i] = afterView.Row(i)
374+ afterBounds[i] = afterView.Bound(i)
375+ }
376+ require.Equal(t, beforeHistory.ChunkCount(), afterHistory.ChunkCount())
377+ require.Equal(t, beforeHistory.Len(), afterHistory.Len())
378+ require.Equal(t, beforeHistory.Cells(), afterHistory.Cells())
379+ require.Equal(t, beforeHistory.Tail().Len(), afterHistory.Tail().Len())
380+ require.Equal(t, beforeRows, afterRows)
381+ require.Equal(t, beforeBounds, afterBounds)
346382 require.Equal(t, beforeCap, screen.History().Cap())
347383 require.Equal(t, beforeCellCap, screen.History().CellCap())
348384 }
@@ -195,7 +195,7 @@ func TestScreenSnapshotFidelity(t *testing.T) {
195 }195 }
196 copy(screen.Frame.Row(0), cells)196 copy(screen.Frame.Row(0), cells)
197 screen.buffer.boundaries[0] = LineBound{End: 3, Soft: true}197 screen.buffer.boundaries[0] = LineBound{End: 3, Soft: true}
198- return screen, cells, []LineBound{LineBound{End: 3, Soft: true}, LineBound{}}198+ return screen, cells, []LineBound{{End: 3, Soft: true}, {}}
199 },199 },
200 },200 },
201 {201 {
@@ -225,6 +225,20 @@ func TestScreenSnapshotFidelity(t *testing.T) {
225 }225 }
226 }226 }
227 227
228+func TestScreenSnapshotPreservesLogicalRowsAfterScroll(t *testing.T) {
229+ screen := NewScreen(3, 2)
230+ screen.Write([]byte("ABC"))
231+ screen.Write([]byte("DEF"))
232+ screen.Write([]byte("G"))
233+
234+ snapshot := screen.Snapshot()
235+ for y, want := range []string{"DEF", "G "} {
236+ require.Equal(t, want, rowText(snapshot.Row(y)))
237+ require.Equal(t, screen.Frame.Row(y), snapshot.Row(y))
238+ require.Equal(t, screen.LineBounds()[y], snapshot.Bound(y))
239+ }
240+}
241+
228 func TestScreenSnapshotOwnership(t *testing.T) {242 func TestScreenSnapshotOwnership(t *testing.T) {
229 tests := []struct {243 tests := []struct {
230 name string244 name string
@@ -330,9 +344,18 @@ func TestScreenSnapshotDoesNotMutateHistoryOrDamage(t *testing.T) {
330 screen := test.make()344 screen := test.make()
331 beforeDamage := screen.CaptureDamage()345 beforeDamage := screen.CaptureDamage()
332 var beforeHistory HistorySnapshotView346 var beforeHistory HistorySnapshotView
347+ var beforeRows [][]renderer.Cell
348+ var beforeBounds []LineBound
333 beforeCap, beforeCellCap := 0, 0349 beforeCap, beforeCellCap := 0, 0
334 if screen.History() != nil {350 if screen.History() != nil {
335 beforeHistory = screen.History().SnapshotView()351 beforeHistory = screen.History().SnapshotView()
352+ beforeView := screen.History().View()
353+ beforeRows = make([][]renderer.Cell, beforeView.Len())
354+ beforeBounds = make([]LineBound, beforeView.Len())
355+ for i := range beforeRows {
356+ beforeRows[i] = beforeView.Row(i)
357+ beforeBounds[i] = beforeView.Bound(i)
358+ }
336 beforeCap = screen.History().Cap()359 beforeCap = screen.History().Cap()
337 beforeCellCap = screen.History().CellCap()360 beforeCellCap = screen.History().CellCap()
338 }361 }
@@ -342,7 +365,20 @@ func TestScreenSnapshotDoesNotMutateHistoryOrDamage(t *testing.T) {
342 afterDamage := screen.CaptureDamage()365 afterDamage := screen.CaptureDamage()
343 require.Equal(t, beforeDamage, afterDamage)366 require.Equal(t, beforeDamage, afterDamage)
344 if screen.History() != nil {367 if screen.History() != nil {
345- require.Equal(t, beforeHistory, screen.History().SnapshotView())368+ afterHistory := screen.History().SnapshotView()
369+ afterView := screen.History().View()
370+ afterRows := make([][]renderer.Cell, afterView.Len())
371+ afterBounds := make([]LineBound, afterView.Len())
372+ for i := range afterRows {
373+ afterRows[i] = afterView.Row(i)
374+ afterBounds[i] = afterView.Bound(i)
375+ }
376+ require.Equal(t, beforeHistory.ChunkCount(), afterHistory.ChunkCount())
377+ require.Equal(t, beforeHistory.Len(), afterHistory.Len())
378+ require.Equal(t, beforeHistory.Cells(), afterHistory.Cells())
379+ require.Equal(t, beforeHistory.Tail().Len(), afterHistory.Tail().Len())
380+ require.Equal(t, beforeRows, afterRows)
381+ require.Equal(t, beforeBounds, afterBounds)
346 require.Equal(t, beforeCap, screen.History().Cap())382 require.Equal(t, beforeCap, screen.History().Cap())
347 require.Equal(t, beforeCellCap, screen.History().CellCap())383 require.Equal(t, beforeCellCap, screen.History().CellCap())
348 }384 }

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