summaryrefslogtreecommitdiff
path: root/internal/gui/generator_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-02 16:36:25 +0300
committerPaul Buetow <paul@buetow.org>2026-04-02 16:36:25 +0300
commit6bd23a588bacee2e8c75f477150b7e2d345002ff (patch)
tree67bfa78afe206e7560350bdd52c60e0e80ec3243 /internal/gui/generator_test.go
parent6ce9123de04ffff961cbf1da73648679216ff637 (diff)
Release v0.9.0v0.9.0
Diffstat (limited to 'internal/gui/generator_test.go')
-rw-r--r--internal/gui/generator_test.go87
1 files changed, 73 insertions, 14 deletions
diff --git a/internal/gui/generator_test.go b/internal/gui/generator_test.go
index 0c1ac41..2828337 100644
--- a/internal/gui/generator_test.go
+++ b/internal/gui/generator_test.go
@@ -61,6 +61,7 @@ type fakeAudioProvider struct {
outputFiles []string
lastText string
lastOutputFile string
+ generateFunc func(text, outputFile string) error
}
func (f *fakeAudioProvider) GenerateAudio(_ context.Context, text, outputFile string) error {
@@ -69,6 +70,9 @@ func (f *fakeAudioProvider) GenerateAudio(_ context.Context, text, outputFile st
f.outputFiles = append(f.outputFiles, outputFile)
f.lastText = text
f.lastOutputFile = outputFile
+ if f.generateFunc != nil {
+ return f.generateFunc(text, outputFile)
+ }
return nil
}
@@ -254,7 +258,7 @@ func TestGenerateAudioUsesSharedOpenAIVoices(t *testing.T) {
}
}
-func TestGenerateAudioUsesGeminiModelDefaultVoiceAndAttribution(t *testing.T) {
+func TestGenerateAudioUsesRandomGeminiVoiceAndAttribution(t *testing.T) {
originalFactory := newAudioProvider
t.Cleanup(func() {
newAudioProvider = originalFactory
@@ -284,7 +288,7 @@ func TestGenerateAudioUsesGeminiModelDefaultVoiceAndAttribution(t *testing.T) {
app := &Application{
config: &Config{
OutputDir: tempDir,
- AudioFormat: "wav",
+ AudioFormat: "mp3",
},
audioConfig: &audio.Config{
Provider: "gemini",
@@ -306,17 +310,17 @@ func TestGenerateAudioUsesGeminiModelDefaultVoiceAndAttribution(t *testing.T) {
if capturedConfig.Provider != "gemini" {
t.Fatalf("captured Provider = %q, want %q", capturedConfig.Provider, "gemini")
}
- if capturedConfig.GeminiVoice != "" {
- t.Fatalf("captured GeminiVoice = %q, want empty model-default voice", capturedConfig.GeminiVoice)
+ if capturedConfig.GeminiVoice != "sentinel-gemini-voice" {
+ t.Fatalf("captured GeminiVoice = %q, want %q", capturedConfig.GeminiVoice, "sentinel-gemini-voice")
}
- if capturedConfig.OutputFormat != "wav" {
- t.Fatalf("captured OutputFormat = %q, want %q", capturedConfig.OutputFormat, "wav")
+ if capturedConfig.OutputFormat != "mp3" {
+ t.Fatalf("captured OutputFormat = %q, want %q", capturedConfig.OutputFormat, "mp3")
}
if fakeProvider.generateCalls != 1 {
t.Fatalf("GenerateAudio() calls = %d, want %d", fakeProvider.generateCalls, 1)
}
- if !strings.HasSuffix(outputPath, "audio.wav") {
- t.Fatalf("outputPath = %q, want a WAV output file", outputPath)
+ if !strings.HasSuffix(outputPath, "audio.mp3") {
+ t.Fatalf("outputPath = %q, want an MP3 output file", outputPath)
}
attrPath := audio.AttributionPath(outputPath)
@@ -328,8 +332,8 @@ func TestGenerateAudioUsesGeminiModelDefaultVoiceAndAttribution(t *testing.T) {
if !strings.Contains(attribution, "Audio generated by Google Gemini TTS") {
t.Fatalf("gemini attribution missing header: %q", attribution)
}
- if strings.Contains(attribution, "sentinel-gemini-voice") {
- t.Fatalf("gemini attribution should not use the shared voice list when voice is unset: %q", attribution)
+ if !strings.Contains(attribution, "sentinel-gemini-voice") {
+ t.Fatalf("gemini attribution should use the selected random Gemini voice: %q", attribution)
}
if !strings.Contains(attribution, "Processed text sent to TTS: ябълка...") {
t.Fatalf("gemini attribution missing processed text: %q", attribution)
@@ -340,13 +344,13 @@ func TestGenerateAudioUsesGeminiModelDefaultVoiceAndAttribution(t *testing.T) {
t.Fatalf("expected metadata file: %v", err)
}
metadata := string(metadataData)
- if !strings.Contains(metadata, "audio_file=audio.wav") {
+ if !strings.Contains(metadata, "audio_file=audio.mp3") {
t.Fatalf("gemini metadata missing fresh audio file reference: %q", metadata)
}
- if !strings.Contains(metadata, "voice=model-default") {
- t.Fatalf("gemini metadata missing model-default voice marker: %q", metadata)
+ if !strings.Contains(metadata, "voice=sentinel-gemini-voice") {
+ t.Fatalf("gemini metadata missing selected random voice: %q", metadata)
}
- if !strings.Contains(metadata, "format=wav") {
+ if !strings.Contains(metadata, "format=mp3") {
t.Fatalf("gemini metadata missing format: %q", metadata)
}
if !strings.Contains(metadata, "cardtype=en-bg") {
@@ -354,6 +358,61 @@ func TestGenerateAudioUsesGeminiModelDefaultVoiceAndAttribution(t *testing.T) {
}
}
+func TestGenerateGeminiAudioWithFallbacksRetriesAlternateVoice(t *testing.T) {
+ originalFactory := newAudioProvider
+ t.Cleanup(func() {
+ newAudioProvider = originalFactory
+ })
+
+ originalVoices := append([]string(nil), audio.GeminiVoices...)
+ t.Cleanup(func() {
+ audio.GeminiVoices = originalVoices
+ })
+ audio.GeminiVoices = []string{"Charon", "Kore", "Leda"}
+
+ var attemptedVoices []string
+ newAudioProvider = func(config *audio.Config) (audio.Provider, error) {
+ attemptedVoices = append(attemptedVoices, config.GeminiVoice)
+ return &fakeAudioProvider{
+ generateFunc: func(_ string, _ string) error {
+ if config.GeminiVoice == "Charon" {
+ return audio.ErrGeminiNoAudioData
+ }
+ return nil
+ },
+ }, nil
+ }
+
+ tempDir := t.TempDir()
+ outputPath := filepath.Join(tempDir, "audio.wav")
+ app := &Application{
+ config: &Config{
+ OutputDir: tempDir,
+ AudioFormat: "wav",
+ },
+ audioConfig: &audio.Config{
+ Provider: "gemini",
+ OutputDir: tempDir,
+ GoogleAPIKey: "google-key",
+ GeminiTTSModel: "gemini-2.5-flash-preview-tts",
+ },
+ }
+
+ voice, err := app.generateGeminiAudioWithFallbacks("Charon", func(candidate string) error {
+ return app.generateAudioFile(context.Background(), "ябълка", outputPath, candidate, 1.0)
+ })
+ if err != nil {
+ t.Fatalf("generateGeminiAudioWithFallbacks() unexpected error: %v", err)
+ }
+
+ if voice != "Kore" {
+ t.Fatalf("final voice = %q, want %q", voice, "Kore")
+ }
+ if got, want := strings.Join(attemptedVoices, ","), "Charon,Kore"; got != want {
+ t.Fatalf("attempted voices = %q, want %q", got, want)
+ }
+}
+
func TestGenerateAudioBgBgUsesSharedOpenAIVoices(t *testing.T) {
originalFactory := newAudioProvider
t.Cleanup(func() {