115 lines
3.7 KiB
Go
115 lines
3.7 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"
|
|
)
|
|
|
|
func TestSpellingUsesSourceAtDetachedReviewPosition(t *testing.T) {
|
|
var review Review
|
|
snapshot := fixture("A book!?É界", "other")
|
|
snapshot.X = 3
|
|
review.Update(snapshot)
|
|
for _, trial := range []struct {
|
|
id command.ID
|
|
text string
|
|
phonetic bool
|
|
}{
|
|
{command.SpellWord, "book!?É界", false},
|
|
{command.PhoneticWord, "book!?É界", true},
|
|
{command.SpellLine, "A book!?É界", false},
|
|
{command.PhoneticLine, "A book!?É界", true},
|
|
{command.PhoneticChar, "o", true},
|
|
} {
|
|
result := review.Execute(trial.id)
|
|
if got := result.Text; got != trial.text {
|
|
t.Fatal(trial.id, got)
|
|
}
|
|
spelling := result.Spelling
|
|
if spelling == nil || spelling.Text != trial.text || spelling.Phonetic != trial.phonetic {
|
|
t.Fatal(trial.id, spelling)
|
|
}
|
|
if result.Character != nil || result.Cue != "" {
|
|
t.Fatal("source was converted to character feedback or a cue")
|
|
}
|
|
// Application motion and passive updates must not move detached review.
|
|
snapshot.X, snapshot.Y = 0, 1
|
|
review.Update(snapshot)
|
|
if review.x != 3 || review.y != 0 || !review.Active() {
|
|
t.Fatal("spelling moved or lost review")
|
|
}
|
|
}
|
|
result := review.Execute(command.CurrentWord)
|
|
if result.Spelling != nil {
|
|
t.Fatal("spelling leaked into ordinary review")
|
|
}
|
|
snapshot.Active = false
|
|
review.Update(snapshot)
|
|
result = review.Execute(command.SpellWord)
|
|
if result.Spelling != nil || result.Cue != presentation.Error {
|
|
t.Fatal("unavailable screen was spelled")
|
|
}
|
|
}
|
|
|
|
func TestSpellingBlanksAndLiteralAnnouncements(t *testing.T) {
|
|
for _, text := range []string{"", " ", "blank", "space"} {
|
|
for _, id := range []command.ID{command.SpellWord, command.PhoneticWord, command.SpellLine, command.PhoneticLine, command.PhoneticChar} {
|
|
var review Review
|
|
review.Update(fixture(text))
|
|
result := review.Execute(id)
|
|
if text == "" || text == " " {
|
|
if result.Spelling != nil || result.Cue != presentation.Blank {
|
|
t.Fatal(text, id, result.Spelling, result.Cue)
|
|
}
|
|
} else if result.Spelling == nil || result.Cue != "" {
|
|
t.Fatal("literal announcement was not spelled", text, id)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTableSpellingKeepsCellScopeAndExcludesHeaders(t *testing.T) {
|
|
var review Review
|
|
snapshot := fixture("Name|Subject|Empty", "Same|A book!||Tail")
|
|
review.Update(snapshot)
|
|
review.Set_table_mode(true)
|
|
review.Execute(command.CurrentWord)
|
|
review.Set_mark()
|
|
review.Execute(command.NextLine)
|
|
review.Execute(command.NextWord)
|
|
if got := review.Execute(command.CurrentWord).Text; got != "A book! Subject" {
|
|
t.Fatal(got)
|
|
}
|
|
for _, id := range []command.ID{command.SpellWord, command.PhoneticWord} {
|
|
result := review.Execute(id)
|
|
if got := result.Text; got != "A book!" || result.Spelling == nil {
|
|
t.Fatal(id, got, result.Spelling)
|
|
}
|
|
}
|
|
if got := review.Execute(command.PhoneticChar).Text; got != "A" {
|
|
t.Fatal(got)
|
|
}
|
|
if got := review.Execute(command.PhoneticLine).Text; got != "Same|A book!||Tail" {
|
|
t.Fatal("line scope was restricted to a cell", got)
|
|
}
|
|
review.Execute(command.NextWord)
|
|
result := review.Execute(command.PhoneticWord)
|
|
if result.Spelling != nil || result.Cue != presentation.Blank {
|
|
t.Fatal("empty cell was spelled as a header", result.Spelling)
|
|
}
|
|
result = review.Execute(command.PhoneticChar)
|
|
if result.Spelling != nil || result.Cue != presentation.Blank {
|
|
t.Fatal("empty cell character escaped its cell")
|
|
}
|
|
review.Update(fixture(""))
|
|
result = review.Execute(command.PhoneticWord)
|
|
if got := result.Text; got != "no table data" || result.Spelling != nil {
|
|
t.Fatal("table error was spelled", got)
|
|
}
|
|
}
|