120 lines
3.6 KiB
Go
120 lines
3.6 KiB
Go
package atspi
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
func TestBrailleCaptureKeepsTruncatedUnicodeOrigin(t *testing.T) {
|
|
raw := strings.Repeat("猫", 2000) + " é"
|
|
var snapshot Snapshot
|
|
captureBrailleLine(&snapshot, raw, raw[:len(raw)-len("é")], 19)
|
|
removed := utf8.RuneCountInString(raw) - utf8.RuneCountInString(snapshot.BrailleLine)
|
|
if snapshot.BrailleLineStart != 19+removed || snapshot.BrailleCaret != 2021 || !strings.HasSuffix(snapshot.BrailleLine, " é") {
|
|
t.Fatalf("origin=%d caret=%d", snapshot.BrailleLineStart, snapshot.BrailleCaret)
|
|
}
|
|
}
|
|
|
|
func TestBrailleRouteRejectsChangedLineAndFocus(t *testing.T) {
|
|
s := NewSnapshot("/entry", "Message", "entry", "", "é猫")
|
|
s.BusName, s.TextCaretKnown = ":1.42", true
|
|
s.StatesKnown, s.Focused = true, true
|
|
captureBrailleLine(&s, "é猫", "é", 12)
|
|
route := BrailleRoute{Focus: s.ID(), Line: "é猫", Start: 12, Offset: 14}
|
|
if !validBrailleRoute(s, route) {
|
|
t.Fatal("valid EOL route rejected")
|
|
}
|
|
for _, change := range []func(*Snapshot){
|
|
func(s *Snapshot) { s.BusName = ":1.43" },
|
|
func(s *Snapshot) { s.Path = "/other" },
|
|
func(s *Snapshot) { s.BrailleLine = "ab" },
|
|
func(s *Snapshot) { s.BrailleLineStart++ },
|
|
func(s *Snapshot) { s.Defunct = true },
|
|
func(s *Snapshot) { s.Focused = false },
|
|
func(s *Snapshot) { s.StatesKnown = false },
|
|
func(s *Snapshot) { s.Role = "password text" },
|
|
func(s *Snapshot) { s.TextCaretKnown = false },
|
|
} {
|
|
changed := s
|
|
change(&changed)
|
|
if validBrailleRoute(changed, route) {
|
|
t.Fatalf("accepted stale/protected route %+v", changed)
|
|
}
|
|
}
|
|
for _, offset := range []int{-1, 11, 15} {
|
|
route.Offset = offset
|
|
if validBrailleRoute(s, route) {
|
|
t.Fatalf("accepted offset %d", offset)
|
|
}
|
|
}
|
|
}
|
|
|
|
func assertNativeBrailleRouting(t *testing.T, ctx context.Context, adapter *Adapter) {
|
|
t.Helper()
|
|
wait := func(name string, offset int) Snapshot {
|
|
t.Helper()
|
|
for {
|
|
select {
|
|
case e := <-adapter.Events():
|
|
if e.Source.Name != name {
|
|
continue
|
|
}
|
|
if offset < 0 && (e.Type == FocusEvent || e.Type == FocusedStateEvent && e.Detail1 == 1) {
|
|
return e.Source
|
|
}
|
|
if offset >= 0 && e.Type == CaretEvent && e.Source.BrailleCaret == offset {
|
|
return e.Source
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatalf("missing native braille event for %s offset %d", name, offset)
|
|
}
|
|
}
|
|
}
|
|
pressTreeProbeKey(t, "F6")
|
|
s := wait("Caret review probe", -1)
|
|
if !s.TextCaretKnown || s.BrailleLine != "Caret 猫 text" {
|
|
t.Fatalf("native braille snapshot %+v", s)
|
|
}
|
|
route := BrailleRoute{Focus: s.ID(), Line: s.BrailleLine, Start: s.BrailleLineStart}
|
|
for _, offset := range []int{1, 6, 7, 12, 6} {
|
|
route.Offset = offset
|
|
if err := adapter.RouteBraille(ctx, route); err != nil {
|
|
t.Fatalf("route offset %d: %v", offset, err)
|
|
}
|
|
wait("Caret review probe", offset)
|
|
}
|
|
waitLine := func(line string) {
|
|
t.Helper()
|
|
for {
|
|
select {
|
|
case event := <-adapter.Events():
|
|
if event.Source.ID() == s.ID() && event.Source.BrailleLine == line {
|
|
return
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatal("edited braille line was not captured")
|
|
}
|
|
}
|
|
}
|
|
pressTreeProbeKey(t, "z")
|
|
waitLine("Caret z猫 text")
|
|
if err := adapter.RouteBraille(ctx, route); !errors.Is(err, ErrStaleObject) {
|
|
t.Fatalf("stale text route: %v", err)
|
|
}
|
|
pressTreeProbeKey(t, "BackSpace")
|
|
waitLine("Caret 猫 text")
|
|
pressTreeProbeKey(t, "F7")
|
|
secret := wait("Protected text probe", -1)
|
|
if secret.TextCaretKnown || secret.BrailleLine != "" {
|
|
t.Fatal("captured protected braille text")
|
|
}
|
|
if err := adapter.RouteBraille(ctx, route); !errors.Is(err, ErrStaleObject) {
|
|
t.Fatalf("old focus route: %v", err)
|
|
}
|
|
pressTreeProbeKey(t, "F8")
|
|
wait("Numeric value probe", -1)
|
|
}
|