100 lines
3.3 KiB
Go
100 lines
3.3 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package presentation
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/atspi"
|
|
)
|
|
|
|
func TestTypingEchoModeCombinations(t *testing.T) {
|
|
for mask := 0; mask < 8; mask++ {
|
|
for _, enabled := range []bool{false, true} {
|
|
t.Run(fmt.Sprintf("modes=%03b/enabled=%v", mask, enabled), func(t *testing.T) {
|
|
options := DefaultOptions()
|
|
options.EnableKeyEcho = enabled
|
|
options.EnableEchoByCharacter = mask&1 != 0
|
|
options.EnableEchoByWord = mask&2 != 0
|
|
options.EnableEchoBySentence = mask&4 != 0
|
|
// With printable key categories disabled, each mode must still
|
|
// work independently. Sentence completion takes precedence.
|
|
options.EnableAlphabeticKeys = false
|
|
options.EnableNumericKeys = false
|
|
options.EnablePunctuationKeys = false
|
|
options.EnableSpace = false
|
|
for _, tc := range []struct {
|
|
payload, context, word, sentence string
|
|
}{
|
|
{"é", "Café", "", ""},
|
|
{"7", "7", "", ""},
|
|
{"😀", "😀", "", ""},
|
|
{" ", "Café ", "Café", ""},
|
|
{",", "Café,", "Café", ""},
|
|
{" ", "First. Second. ", "", "Second."},
|
|
{"\n", "First. Last line\n", "line", "Last line"},
|
|
{" ", "Café ", "", ""},
|
|
} {
|
|
want, wantKind := "", "key"
|
|
if options.EnableEchoByCharacter {
|
|
wantKind = "character"
|
|
if tc.payload != "\n" {
|
|
want = tc.payload
|
|
if want == " " {
|
|
want = "space"
|
|
}
|
|
}
|
|
}
|
|
if options.EnableEchoByWord && tc.word != "" {
|
|
want, wantKind = tc.word, "word"
|
|
}
|
|
if options.EnableEchoBySentence && tc.sentence != "" {
|
|
want, wantKind = tc.sentence, "sentence"
|
|
}
|
|
if !enabled {
|
|
want = ""
|
|
}
|
|
event := atspi.Event{Type: atspi.TextInsertedEvent, Payload: tc.payload,
|
|
Source: atspi.Snapshot{Role: "entry", Editable: true, TextBeforeCaret: tc.context}}
|
|
text, kind := TypingEcho(event, "", options)
|
|
if text != want || text != "" && kind != wantKind {
|
|
t.Errorf("payload=%q context=%q: (%q, %q), want (%q, %q)", tc.payload, tc.context, text, kind, want, wantKind)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTypingEchoLineBreakBeforeExistingText(t *testing.T) {
|
|
for _, mode := range []string{"word", "sentence"} {
|
|
for _, tc := range []struct {
|
|
name, payload, previous, following, want string
|
|
}{
|
|
{"split line", "\n", "Hello", "following text", "Hello"},
|
|
{"split line with tab", "\t", "Hello", "\tfollowing text", "Hello"},
|
|
{"start of line", "\n", "", "following text", ""},
|
|
{"blank line", "\n", "", "", ""},
|
|
{"unicode", "\n", "Café", "following text", "Café"},
|
|
} {
|
|
t.Run(mode+"/"+tc.name, func(t *testing.T) {
|
|
options := DefaultOptions()
|
|
options.EnableEchoByWord = mode == "word"
|
|
options.EnableEchoBySentence = mode == "sentence"
|
|
event := atspi.Event{Type: atspi.TextInsertedEvent, Payload: tc.payload,
|
|
Source: atspi.Snapshot{Role: "entry", Editable: true, TextCaretKnown: true, Text: tc.following}}
|
|
want := tc.want
|
|
if mode == "sentence" && tc.payload == "\t" {
|
|
want = "" // A tab only completes a sentence after punctuation.
|
|
}
|
|
if got := TypingEchoText(event, tc.previous, options); got != want {
|
|
t.Fatalf("echo = %q, want %q", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|