Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,83 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||
)
|
||||
|
||||
func TestLiveRegionSpeaksInsertedChatWithoutEditableFocus(t *testing.T) {
|
||||
speech := &fakeSpeechQueue{spoken: make(chan string, 4)}
|
||||
adapter := &fakeAdapter{events: make(chan atspi.Event, 4)}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
processEvents(ctx, slog.New(slog.DiscardHandler), speech, adapter, 0)
|
||||
}()
|
||||
defer func() { cancel(); <-done }()
|
||||
|
||||
region := atspi.Snapshot{
|
||||
BusName: ":1.7", Path: "/chat/status", Role: "status",
|
||||
LiveRegion: true, LivePoliteness: "polite", LiveAtomic: true,
|
||||
Text: "Username: Test message",
|
||||
}
|
||||
placeholder := region
|
||||
placeholder.Text = "\ufffc"
|
||||
adapter.events <- atspi.NewEventWithPayload(atspi.TextInsertedEvent, placeholder, "\ufffc")
|
||||
select {
|
||||
case got := <-speech.spoken:
|
||||
t.Fatalf("placeholder spoken as %q", got)
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
adapter.events <- atspi.NewEvent(atspi.ChildrenAddedEvent, region)
|
||||
select {
|
||||
case got := <-speech.spoken:
|
||||
if got != "Username: Test message" {
|
||||
t.Fatalf("speech = %q", got)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("live region was not spoken")
|
||||
}
|
||||
adapter.events <- atspi.NewEventWithPayload(atspi.TextInsertedEvent, region, "Username: Test message")
|
||||
select {
|
||||
case got := <-speech.spoken:
|
||||
t.Fatalf("duplicate live region speech %q", got)
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
region.Text = "Username: Next message"
|
||||
adapter.events <- atspi.NewEventWithPayload(atspi.TextInsertedEvent, region, "Next message")
|
||||
select {
|
||||
case got := <-speech.spoken:
|
||||
if got != "Username: Next message" {
|
||||
// Atomic regions speak their current full content, supplied by the
|
||||
// adapter, rather than only the insertion payload.
|
||||
t.Fatalf("atomic speech = %q", got)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("atomic live region insertion was not spoken")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLiveRegionOffDoesNotSpeak(t *testing.T) {
|
||||
speech := &fakeSpeechQueue{spoken: make(chan string, 2)}
|
||||
adapter := &fakeAdapter{events: make(chan atspi.Event, 2)}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
processEvents(ctx, slog.New(slog.DiscardHandler), speech, adapter, 0)
|
||||
}()
|
||||
defer func() { cancel(); <-done }()
|
||||
|
||||
region := atspi.Snapshot{BusName: ":1.7", Path: "/chat/status", Role: "status", LiveRegion: true, LivePoliteness: "off", Text: "Silence"}
|
||||
adapter.events <- atspi.NewEvent(atspi.ChildrenAddedEvent, region)
|
||||
select {
|
||||
case got := <-speech.spoken:
|
||||
t.Fatalf("unexpected speech %q", got)
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user