// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package atspi import "testing" func TestDocumentCaretCharacterPreservesDelimiters(t *testing.T) { for _, value := range []string{"", " ", "\t", "\n", "\r", "\u00a0", "猫", "é", "\ufffc"} { if got := documentCaretCharacter(value); got != value { t.Errorf("character %q became %q", value, got) } } } func TestIncompleteEmbeddedTextRecoversOnlyWholeObject(t *testing.T) { for _, test := range []struct { name, label, expanded, want string start, end, count int incomplete bool }{ {"failed child", "Before Linked title after", "Before after", "Before Linked title after", 0, 14, 14, true}, {"complete expansion", "Different author label", "Before Linked title after", "Before Linked title after", 0, 14, 14, false}, {"wrapped first line", "Whole object label", "Before after", "Before after", 0, 14, 28, true}, {"wrapped last line", "Whole object label", "Before after", "Before after", 14, 28, 28, true}, {"unknown count", "Whole object label", "Before after", "Before after", 0, 14, 0, true}, {"invalid name", "Before \ufffc after", "Before after", "Before after", 0, 14, 14, true}, {"empty name", " ", "Before after", "Before after", 0, 14, 14, true}, } { t.Run(test.name, func(t *testing.T) { line := DocumentCaretText{Text: "Before \ufffc after", Start: test.start, End: test.end, CharacterCount: test.count, SelectionStart: 8, SelectionEnd: 10, TextAttributeRuns: []TextAttributeRun{{Start: 8, End: 10}}} line.applyExpandedText(test.expanded, test.label, test.incomplete) if line.Text != test.want || line.RawText != "Before \ufffc after" || !line.Expanded || line.Start != test.start || line.End != test.end || line.CharacterCount != test.count || line.SelectionStart != 8 || line.SelectionEnd != 10 || line.TextAttributeRuns[0].Start != 8 { t.Fatalf("expanded line = %+v", line) } }) } } func TestCaretLineRepairPreservesOnlyMatchingExpansion(t *testing.T) { snapshot := Snapshot{Text: "Before Linked title after", BrailleLine: "Before \ufffc after", BrailleLineStart: 10, CharacterCount: 24, TextCaretKnown: true} line := DocumentCaretText{Text: "Before \ufffc after", RawText: "Before \ufffc after", Start: 10, End: 24, CharacterCount: 24} snapshot.applyDocumentCaretLine(line, 18) if snapshot.Text != "Before Linked title after" || snapshot.BrailleLine != line.RawText || snapshot.BrailleCaret != 18 || snapshot.CharacterCount != 24 { t.Fatalf("matching expansion lost: %+v", snapshot) } // A newly available count permits whole-object recovery after the // initial snapshot could not establish whether its line was complete. snapshot.CharacterCount = 0 line.Text = "Before Recovered title after" snapshot.applyDocumentCaretLine(line, 18) if snapshot.Text != "Before Recovered title after" { t.Fatalf("newly recovered expansion ignored: %+v", snapshot) } // Equal raw strings on different lines must not reuse the old expansion. line.Start, line.End, line.Text = 0, 14, "Before New title after" snapshot.applyDocumentCaretLine(line, 0) if snapshot.Text != "Before New title after" || snapshot.BrailleLineStart != 0 || snapshot.BrailleCaret != 0 { t.Fatalf("new line inherited stale expansion: %+v", snapshot) } line.Text, line.RawText = "New plain 猫", "New plain 猫" snapshot.applyDocumentCaretLine(line, 2) if snapshot.Text != "New plain 猫" || snapshot.BrailleLine != "New plain 猫" || snapshot.BrailleCaret != 2 { t.Fatalf("plain line repair lost text or spacing: %+v", snapshot) } }