Files
fenrir/internal/review/vertical_character_test.go

126 lines
4.1 KiB
Go

// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package review
import (
"testing"
"git.stormux.org/storm/fenrir/internal/command"
"git.stormux.org/storm/fenrir/internal/presentation"
"git.stormux.org/storm/fenrir/internal/screen"
)
func TestVerticalCharacterRetainsColumnAndDetachedReview(t *testing.T) {
var r Review
s := fixture("abcdÉ!", "x", "", "wxyzΩ?")
s.X = 4
r.Update(s)
for _, trial := range []struct {
action command.ID
want string
row int
cue presentation.Cue
character rune
}{
{command.ReviewUp, "start of screen", 0, presentation.Top, 0},
{command.ReviewDown, "space", 1, "", ' '},
{command.ReviewDown, "space", 2, "", ' '},
{command.ReviewDown, "Ω", 3, "", 'Ω'},
{command.ReviewDown, "end of screen", 3, presentation.Bottom, 0},
{command.ReviewUp, "space", 2, "", ' '},
{command.ReviewUp, "space", 1, "", ' '},
{command.ReviewUp, "É", 0, "", 'É'},
} {
result := r.Execute(trial.action)
if got := result.Text; got != trial.want || r.x != 4 || r.y != trial.row || result.Cue != trial.cue {
t.Fatalf("%s: %q at %d,%d cue %q; want %+v", trial.action, got, r.x, r.y, result.Cue, trial)
}
char := result.Character
if (char != nil) != (trial.character != 0) || char != nil && *char != trial.character {
t.Fatalf("character metadata: %v; want %q", char, trial.character)
}
if !r.Active() || r.screen.X != 4 || r.screen.Y != 0 {
t.Fatal("vertical review changed application ownership or position")
}
}
// Passive application cursor movement must leave detached review intact.
s.X, s.Y = 0, 3
r.Update(s)
if got := r.Execute(command.ReviewDown).Text; got != "space" || r.x != 4 || r.y != 1 {
t.Fatal("review followed application cursor", got, r.x, r.y)
}
r.Execute(command.FollowCursor)
if got := r.Execute(command.ReviewUp).Text; got != "space" || r.x != 0 || r.y != 2 {
t.Fatal("follow-cursor did not reset vertical review", got, r.x, r.y)
}
}
func TestVerticalCharacterScreenEdgesAndSessionReset(t *testing.T) {
for _, column := range []int{0, 19} {
var r Review
s := fixture("", "")
s.X = column
r.Update(s)
if got := r.Execute(command.ReviewDown).Text; got != "space" || r.x != column {
t.Fatal("empty screen or edge column", got, r.x)
}
for _, change := range []string{"generation", "terminal", "resize", "inactive"} {
next := fixture("new", "last")
switch change {
case "generation":
next.Generation++
case "terminal":
next.Terminal++
case "resize":
next = fixture("new", "last", "extra")
case "inactive":
r.Update(screen.Snapshot{})
if got := r.Execute(command.ReviewUp).Text; got != "no text console" {
t.Fatal(got)
}
}
r.Update(next)
if got := r.Execute(command.ReviewDown).Text; got != "l" || r.x != 0 || r.y != 1 {
t.Fatal("stale vertical position after", change, got, r.x, r.y)
}
}
}
}
func TestVerticalCharacterTableScopeRetainsAbsoluteColumn(t *testing.T) {
var r Review
r.Update(fixture("Name|Subject", "é|long word", "wide label|other", "only", "x|", "Name|Subject"))
r.Set_table_mode(true)
r.Execute(command.CurrentWord)
r.Set_mark()
r.Execute(command.NextWord)
for _, trial := range []struct {
action command.ID
want string
row int
}{
{command.ReviewDown, "g", 1},
{command.ReviewDown, "no table data", 2}, // column six belongs to the first cell
{command.ReviewDown, "no table data", 3}, // selected cell missing
{command.ReviewDown, "blank", 4},
{command.ReviewDown, "S", 5},
{command.ReviewUp, "blank", 4},
{command.ReviewUp, "no table data", 3},
{command.ReviewUp, "no table data", 2},
{command.ReviewUp, "g", 1},
{command.ReviewUp, "S", 0},
} {
if got := r.Execute(trial.action).Text; got != trial.want || r.x != 5 || r.y != trial.row || r.tableColumn != 1 {
t.Fatalf("%s: %q at %d,%d cell %d; want %+v", trial.action, got, r.x, r.y, r.tableColumn, trial)
}
}
if got := r.Execute(command.CurrentWord).Text; got != "Subject Subject" {
t.Fatal("vertical review lost header or selected cell", got)
}
r.Set_table_mode(false)
if got := r.Execute(command.ReviewDown).Text; got != "g" {
t.Fatal("ordinary review did not return", got)
}
}