// Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later package reader import ( "os" "path/filepath" "reflect" "testing" "git.stormux.org/storm/fenrir/internal/command" "git.stormux.org/storm/fenrir/internal/i18n" "git.stormux.org/storm/fenrir/internal/presentation" "git.stormux.org/storm/fenrir/internal/screen" ) func TestFallbackMessagesTranslateWithoutChangingScreenContentOrMetadata(t *testing.T) { if got := presentation.Character('\x7f'); got != "character 127" { t.Fatal("English control-character fallback changed", got) } root := t.TempDir() directory := filepath.Join(root, "xx", "LC_MESSAGES") if err := os.MkdirAll(directory, 0700); err != nil { t.Fatal(err) } data := "msgid \"character {0}\"\nmsgstr \"translated-character {0}\"\n\nmsgid \"no text console\"\nmsgstr \"translated-unavailable\"\n" if err := os.WriteFile(filepath.Join(directory, "fenrir.po"), []byte(data), 0600); err != nil { t.Fatal(err) } previous := i18n.Use(i18n.New(root, "xx")) t.Cleanup(func() { i18n.Use(previous) }) r := New() r.Update(fixture("\x7f")) character := r.Command(command.CurrentChar) if character.Text != "translated-character 127" || character.Character == nil || *character.Character != '\x7f' { t.Fatalf("control-character translation lost its value or metadata: %+v", character) } r.Update(fixture("no text console")) if result := r.Command(command.CurrentLine); result.Text != "no text console" { t.Fatal("translated application content", result) } r.Update(screen.Snapshot{}) for _, id := range []command.ID{command.CurrentChar, command.SetLiveRegion} { result := r.Command(id) if result.Text != "translated-unavailable" || result.Cue != presentation.Error || result.Character != nil || result.Spelling != nil { t.Fatalf("%s: unavailable feedback changed: %+v", id, result) } } } func TestCommandResultsRetainFeedbackAcrossCommandsAndUpdates(t *testing.T) { r := New() r.Configure_attributes("both", "fenrirBold") r.Configure_indentation("speech") s := fixture("root", " child") s.Attributes = make([]screen.Attribute, len(s.Cells)) for index := range s.Attributes { s.Attributes[index] = screen.Attribute{Foreground: screen.ColorDefault, Background: screen.ColorDefault} if index >= s.Cols { s.Attributes[index].Style = screen.Bold } } r.Update(s) line := r.Command(command.NextLine) character := r.Command(command.LastText) spelling := r.Command(command.SpellWord) boundary := r.Command(command.NextLine) if line.Text != " child" || line.Attributes == nil || line.Attributes.Text != "bold" || line.Indentation == nil || line.Indentation.Text != "indented 4 " { t.Fatalf("incomplete line result: %+v", line) } if character.Character == nil || *character.Character != 'd' || character.After.Text != "last character in line" { t.Fatalf("incomplete character result: %+v", character) } if spelling.Spelling == nil || spelling.Spelling.Text != "child" || boundary.Cue != presentation.Bottom { t.Fatalf("spelling=%+v boundary=%+v", spelling, boundary) } for _, id := range []command.ID{command.AutoRead, command.ToggleAttributes, command.ToggleTracking, command.Unbound} { result := r.Command(id) want := presentation.CommandResult{Text: result.Text} if id == command.Unbound { want.Cue = presentation.Error } if !reflect.DeepEqual(result, want) { t.Fatalf("%s retained prior feedback: %+v", id, result) } } r.Update(screen.Snapshot{}) inactive := r.Command(command.CurrentChar) if inactive.Text != "no text console" || inactive.Cue != presentation.Error || inactive.Character != nil || inactive.Spelling != nil { t.Fatalf("incomplete inactive result: %+v", inactive) } // Retained pointer metadata belongs to its result, not the next dispatch. if *character.Character != 'd' || character.After.Text != "last character in line" || spelling.Spelling.Text != "child" || line.Attributes.Text != "bold" || line.Indentation.Text != "indented 4 " { t.Fatal("later dispatch or screen update modified a saved result") } }