Files
cthulhu/internal/app/speech_title_input_test.go

80 lines
3.0 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package app
import (
"context"
"log/slog"
"testing"
"git.stormux.org/storm/cthulhu/internal/input"
)
func TestAutomaticTitleSurvivesMovementRepeatsBeforeAndAfterDelivery(t *testing.T) {
speaker := &fakeSpeaker{spoken: make(chan string, 1)}
worker := newSpeechWorker(slog.New(slog.DiscardHandler), speaker)
worker.running = true
worker.Enqueue(speechRequest{Text: "Game status", Cause: "window-title", Append: true})
repeat := input.Event{Name: "Up", Pressed: true, Repeat: true, Timestamp: 100}
if worker.InterruptForInput(repeat) || len(worker.pending) != 1 {
t.Fatal("repeat discarded queued title")
}
request, ok := worker.next()
if !ok {
t.Fatal("title missing from queue")
}
if err := worker.deliver(context.Background(), request); err != nil {
t.Fatal(err)
}
if text := <-speaker.spoken; text != "Game status" {
t.Fatalf("speech = %q", text)
}
if worker.InterruptForInput(repeat) || worker.generation != 0 {
t.Fatal("repeat interrupted title after backend accepted it")
}
if !worker.InterruptForInput(input.Event{Name: "Up", Pressed: true, Timestamp: 200}) {
t.Fatal("fresh movement key did not interrupt")
}
}
func TestAutomaticTitleStillStopsForExplicitInput(t *testing.T) {
for _, event := range []input.Event{
{Name: "Left", Pressed: true},
{Name: "Control_L", Pressed: true, Repeat: true},
{Name: "Control_R", Pressed: true, Repeat: true},
{Name: "Escape", Pressed: true, Repeat: true},
} {
t.Run(event.Name, func(t *testing.T) {
worker := newSpeechWorker(slog.New(slog.DiscardHandler), nil)
worker.running = true
worker.Enqueue(speechRequest{Text: "Game status", Cause: "window-title", Append: true})
if !worker.InterruptForInput(event) || len(worker.pending) != 0 || worker.generation != 1 {
t.Fatal("explicit input did not stop title speech")
}
})
}
}
func TestTitleProtectionDoesNotChangeOrdinaryReading(t *testing.T) {
for _, cause := range []string{"focus", "flat-review", "current-time", "key-echo", "read-all"} {
t.Run(cause, func(t *testing.T) {
worker := newSpeechWorker(slog.New(slog.DiscardHandler), nil)
worker.running = true
worker.Enqueue(speechRequest{Text: "Game status", Cause: "window-title", Append: true})
worker.Enqueue(speechRequest{Text: "Reading", Cause: cause})
if !worker.InterruptForInput(input.Event{Name: "Up", Pressed: true, Repeat: true}) || len(worker.pending) != 0 {
t.Fatal("title protection leaked into ordinary reading")
}
})
}
worker := newSpeechWorker(slog.New(slog.DiscardHandler), nil)
worker.running = true
ctx := worker.BeginReadAll(context.Background(), 100)
worker.Enqueue(speechRequest{Text: "Game status", Cause: "window-title", Append: true})
if !worker.InterruptForInput(input.Event{Name: "Up", Pressed: true, Repeat: true, Timestamp: 101}) || ctx.Err() != context.Canceled {
t.Fatal("appended title prevented held key from stopping Say All")
}
}