Files

141 lines
4.4 KiB
Go

// Cthulhu screen reader.
// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
package app
import "testing"
type remoteSpeechQueue struct {
requests []speechRequest
interrupts int
}
type remoteBrailleQueue struct {
running bool
text []string
}
func (queue *remoteBrailleQueue) EnqueueMessage(text string) bool {
if !queue.running {
return false
}
queue.text = append(queue.text, text)
return true
}
func TestRemoteBrailleMessage(t *testing.T) {
queue := &remoteBrailleQueue{}
presenter := remoteSpeech{braille: queue}
if presenter.BrailleMessage("Unavailable") || len(queue.text) != 0 {
t.Fatal("message accepted while braille is stopped")
}
queue.running = true
if !presenter.BrailleMessage("Braille") || len(queue.text) != 1 || queue.text[0] != "Braille" {
t.Fatalf("braille message was not queued: %v", queue.text)
}
if presenter.BrailleMessage("") {
t.Fatal("empty message accepted")
}
}
func TestRemotePresentMessageUsesSpeechAndBraille(t *testing.T) {
speech := &remoteSpeechQueue{}
braille := &remoteBrailleQueue{running: true}
presenter := remoteSpeech{speech: speech, braille: braille}
if !presenter.PresentMessage("Status") || len(speech.requests) != 1 ||
len(braille.text) != 1 || braille.text[0] != "Status" {
t.Fatalf("present message: speech=%v braille=%v", speech.requests, braille.text)
}
if !(remoteSpeech{braille: braille}).PresentMessage("Braille only") {
t.Fatal("braille-only presentation rejected")
}
}
func TestWineMessageKeepsSourcePrivateInSpeechRequest(t *testing.T) {
speech := &remoteSpeechQueue{}
presenter := remoteSpeech{speech: speech}
if !presenter.presentMessage("Game control", "wine-accessible-event") {
t.Fatal("Wine presentation rejected")
}
if len(speech.requests) != 1 || speech.requests[0].Cause != "wine-accessible-event" {
t.Fatalf("speech requests = %+v", speech.requests)
}
}
func (queue *remoteSpeechQueue) Enqueue(request speechRequest) {
queue.requests = append(queue.requests, request)
}
func (queue *remoteSpeechQueue) Interrupt() {
queue.interrupts++
}
func TestRemoteSpeechQueuesWithoutInterruptingByDefault(t *testing.T) {
queue := &remoteSpeechQueue{}
presenter := remoteSpeech{speech: queue}
if !presenter.PresentMessage("Status") {
t.Fatal("PresentMessage rejected available speech")
}
if !presenter.SpeakText("Queued", false) {
t.Fatal("SpeakText rejected available speech")
}
if queue.interrupts != 0 {
t.Fatalf("interrupts = %d, want 0", queue.interrupts)
}
if len(queue.requests) != 2 {
t.Fatalf("requests = %d, want 2", len(queue.requests))
}
for index, request := range queue.requests {
if !request.Append {
t.Fatalf("request %d was not queued as append speech", index)
}
}
}
func TestRemoteSpeechInterruptsBeforeRequestedSpeech(t *testing.T) {
queue := &remoteSpeechQueue{}
presenter := remoteSpeech{speech: queue}
if !presenter.SpeakText("Now", true) {
t.Fatal("SpeakText rejected available speech")
}
if queue.interrupts != 1 {
t.Fatalf("interrupts = %d, want 1", queue.interrupts)
}
if len(queue.requests) != 1 || queue.requests[0].Text != "Now" || !queue.requests[0].Append {
t.Fatalf("request = %+v, want queued Now speech", queue.requests)
}
}
func TestRemoteSpeechCancellationAndUnavailableBraille(t *testing.T) {
queue := &remoteSpeechQueue{}
presenter := remoteSpeech{speech: queue}
if !presenter.CancelSpeech() {
t.Fatal("CancelSpeech rejected available speech")
}
if queue.interrupts != 1 {
t.Fatalf("interrupts = %d, want 1", queue.interrupts)
}
if presenter.BrailleMessage("Braille") {
t.Fatal("BrailleMessage succeeded without a braille backend")
}
unavailable := remoteSpeech{}
if unavailable.PresentMessage("Status") || unavailable.SpeakText("Text", false) || unavailable.CancelSpeech() {
t.Fatal("remote speech succeeded without a speech worker")
}
}