Files
cthulhu/internal/app/reading_speech_test.go

96 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package app
import (
"context"
"log/slog"
"reflect"
"testing"
"git.stormux.org/storm/cthulhu/internal/config"
"git.stormux.org/storm/cthulhu/internal/review"
)
func TestReadingSpeechText(t *testing.T) {
for _, test := range []struct {
name string
settings config.ReadingSettings
input string
want string
}{
{"unchanged", config.ReadingSettings{}, "saveFile 123", "saveFile 123"},
{"multicase", config.ReadingSettings{SpeakMultiCaseStringsAsWords: true}, "saveFile and HTTPServer", "save File and HTTPServer"},
{"digits", config.ReadingSettings{SpeakNumbersAsDigits: true}, "Room 123, A12, ٤٥", "Room 1 2 3, A12, ٤ ٥"},
{"both", config.ReadingSettings{SpeakNumbersAsDigits: true, SpeakMultiCaseStringsAsWords: true}, "orderNumber 42", "order Number 4 2"},
} {
t.Run(test.name, func(t *testing.T) {
if got := readingSpeechText(test.input, test.settings); got != test.want {
t.Fatalf("speech text = %q, want %q", got, test.want)
}
})
}
}
func TestPronunciationPreservesCharacterReadingAndSpelling(t *testing.T) {
entries := []config.PronunciationEntry{{Word: "a", Replacement: "article"}, {Word: "space", Replacement: "blank"}}
for _, test := range []struct {
name string
request speechRequest
want []string
}{
{"character", speechRequest{Text: "A", Character: true}, []string{"A"}},
{"echo", speechRequest{Text: "a", Character: true, CustomEcho: true}, []string{"a"}},
{"spelling", func() speechRequest {
request := speechRequest{Text: "Aa"}
set_review_spelling(&request, "Aa", review.FlatSpell)
return request
}(), []string{"A", "a"}},
{"word", speechRequest{Text: "a"}, []string{"article"}},
{"character name", speechRequest{Text: "space", Character: true}, []string{"blank"}},
} {
t.Run(test.name, func(t *testing.T) {
speaker := &spellingTestSpeaker{}
worker := newSpeechWorker(slog.New(slog.DiscardHandler), speaker)
worker.textTransform = func(text string) string { return pronunciationSpeechText(text, entries) }
if err := worker.deliver(context.Background(), test.request); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(speaker.parts, test.want) {
t.Fatalf("delivered %q, want %q", speaker.parts, test.want)
}
})
}
}
func TestSpeechHistoryReplayDoesNotApplyPronunciationTwice(t *testing.T) {
speaker := &spellingTestSpeaker{}
worker := newSpeechWorker(slog.New(slog.DiscardHandler), speaker)
worker.history = newSpeechHistory(10)
worker.textTransform = func(text string) string {
return pronunciationSpeechText(text, []config.PronunciationEntry{
{Word: "SQL", Replacement: "sequel"}, {Word: "sequel", Replacement: "next"},
})
}
if err := worker.deliver(context.Background(), speechRequest{Text: "SQL"}); err != nil {
t.Fatal(err)
}
recorded := worker.history.snapshot()[0]
if err := worker.deliver(context.Background(), speechRequest{Text: recorded, Role: "table cell", ExcludeFromHistory: true}); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(speaker.parts, []string{"sequel", "sequel"}) {
t.Fatalf("history replay changed recorded speech: %q", speaker.parts)
}
}
func TestPronunciationSpeechTextReplacesWholeWordsOnce(t *testing.T) {
entries := []config.PronunciationEntry{{Word: "SQL", Replacement: "sequel"}, {Word: "sequel", Replacement: "next"}, {Word: "café", Replacement: "coffee"}}
input := "SQL, sql; SQLite café!"
if got := pronunciationSpeechText(input, entries); got != "sequel, sequel; SQLite coffee!" {
t.Fatalf("pronunciation = %q", got)
}
}