// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "errors" "log/slog" "testing" "time" "git.stormux.org/storm/cthulhu/internal/config" "git.stormux.org/storm/cthulhu/internal/speech" ) func TestPreferencesEnableAndDisableSpeechDuringSession(t *testing.T) { settings := config.DefaultSettings() settings.EnableSpeech = false speaker := &fakeSpeaker{spoken: make(chan string, 1)} speechWorker := newSpeechWorker(slog.New(slog.DiscardHandler), speaker) speechWorker.SetEnabled(false) if err := speechWorker.Start(context.Background()); err != nil { t.Fatal(err) } defer speechWorker.Stop(context.Background()) updates := 0 worker := newPreferencesWorker(slog.New(slog.DiscardHandler), settings, settingsUpdateFunc(func(context.Context, speech.Settings) error { updates++; return nil })) worker.speechWorker = speechWorker enabled := settings enabled.EnableSpeech = true if err := worker.applyRuntime(context.Background(), enabled); err != nil { t.Fatal(err) } if updates != 1 { t.Fatalf("enabling speech made %d backend updates, want 1", updates) } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() if err := speechWorker.EnqueueAndWait(ctx, speechRequest{Text: "enabled"}); err != nil { t.Fatal(err) } if got := <-speaker.spoken; got != "enabled" { t.Fatalf("spoken text = %q", got) } if err := worker.applyRuntime(context.Background(), settings); err != nil { t.Fatal(err) } if updates != 1 { t.Fatal("disabling speech reconnected the backend") } if err := speechWorker.EnqueueAndWait(ctx, speechRequest{Text: "disabled"}); !errors.Is(err, context.Canceled) { t.Fatalf("disabled speech returned %v, want canceled", err) } select { case got := <-speaker.spoken: t.Fatalf("speech escaped disabled mode: %q", got) default: } }