99 lines
3.7 KiB
Go
99 lines
3.7 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package app
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/config"
|
|
"git.stormux.org/storm/cthulhu/internal/remote"
|
|
)
|
|
|
|
func TestWineEditFieldsOnlyTypingAndVoices(t *testing.T) {
|
|
settings := config.DefaultSettings()
|
|
settings.KeyEchoInEditFieldsOnly = true
|
|
settings.UseCustomEchoVoice = true
|
|
settings.UseCustomEchoForKey = true
|
|
settings.UseCustomEchoForCharacter = false
|
|
live := &liveSettings{}
|
|
live.Store(settings)
|
|
speech := &remoteSpeechQueue{}
|
|
braille := &remoteBrailleQueue{running: true}
|
|
presenter := remoteSpeech{speech: speech, braille: braille, live: live}
|
|
owner := newWineEventPresenter(func(string) bool { return true })
|
|
defer owner.Close()
|
|
presenter.wine = owner
|
|
for _, tc := range []struct {
|
|
role, states, description string
|
|
want bool
|
|
}{
|
|
{"edit", "", "", true}, {"read only edit", "", "", false}, {"edit", "read only", "", false},
|
|
{"button", "", "", false}, {"text", "", "", false}, {"edit", "", "password", false},
|
|
} {
|
|
presenter.PresentAccessibleEvent(remote.AccessibleEvent{SourceID: "control", EventType: "focus", Role: tc.role, States: tc.states, Description: tc.description})
|
|
owner.flush()
|
|
before := len(speech.requests)
|
|
accepted := presenter.PresentAccessibleEvent(remote.AccessibleEvent{SourceID: "control", EventType: "text", Name: "A", States: "kind=8"})
|
|
if accepted != tc.want || (len(speech.requests) > before) != tc.want {
|
|
t.Fatalf("role=%s states=%s protected=%s accepted=%v", tc.role, tc.states, tc.description, accepted)
|
|
}
|
|
if tc.want && (!speech.requests[before].CustomEcho || !speech.requests[before].Character || braille.text[len(braille.text)-1] != "A") {
|
|
t.Fatal("Wine key voice or braille lost")
|
|
}
|
|
}
|
|
presenter.PresentAccessibleEvent(remote.AccessibleEvent{SourceID: "edit", EventType: "focus", Role: "edit"})
|
|
owner.flush()
|
|
settings.EnableEchoByCharacter = true
|
|
live.Store(settings)
|
|
presenter.PresentAccessibleEvent(remote.AccessibleEvent{SourceID: "edit", EventType: "text", Name: "a", States: "kind=8"})
|
|
if speech.requests[len(speech.requests)-1].CustomEcho {
|
|
t.Fatal("character routing used key-only custom voice")
|
|
}
|
|
// Moving focus to a menu invalidates the preceding editor's text actions.
|
|
presenter.PresentAccessibleEvent(remote.AccessibleEvent{SourceID: "menu", EventType: "focus", Role: "menu item"})
|
|
owner.flush()
|
|
if presenter.PresentAccessibleEvent(remote.AccessibleEvent{SourceID: "edit", EventType: "text", Name: "a", States: "kind=8"}) {
|
|
t.Fatal("old editor still echoes")
|
|
}
|
|
}
|
|
|
|
func TestWineKeyEchoRequiresCurrentDesktopFocus(t *testing.T) {
|
|
_, _, monitor, _ := reviewFocusSetup(t)
|
|
owner := newWineEventPresenter(func(string) bool { return true })
|
|
defer owner.Close()
|
|
owner.foreground, owner.titles = monitor, monitor
|
|
focus := remote.AccessibleEvent{SourceID: "edit", EventType: "focus", Role: "edit", WindowTitle: monitor.title.Title.Title}
|
|
owner.Present(focus)
|
|
owner.flush()
|
|
if !owner.EditFieldFocused() {
|
|
t.Fatal("current Wine editor rejected")
|
|
}
|
|
monitor.state.Epoch++
|
|
if owner.EditFieldFocused() {
|
|
t.Fatal("stale Wine editor survived foreground switch")
|
|
}
|
|
monitor.title.Epoch = monitor.state.Epoch
|
|
owner.Present(focus)
|
|
owner.flush()
|
|
if !owner.EditFieldFocused() {
|
|
t.Fatal("new focus did not restore editor")
|
|
}
|
|
monitor.title.Title.Wine = false
|
|
if owner.EditFieldFocused() {
|
|
t.Fatal("native window reused Wine focus")
|
|
}
|
|
monitor.title.Title.Wine = true
|
|
focus.Role = "menu item"
|
|
owner.Present(focus)
|
|
owner.flush()
|
|
if owner.EditFieldFocused() {
|
|
t.Fatal("menu retained editor echo")
|
|
}
|
|
owner.Close()
|
|
if owner.EditFieldFocused() {
|
|
t.Fatal("closed helper retained focus")
|
|
}
|
|
}
|