diff --git a/internal/queue/queue_test.go b/internal/queue/queue_test.go index 14794b3..808a39c 100644 --- a/internal/queue/queue_test.go +++ b/internal/queue/queue_test.go @@ -497,15 +497,26 @@ func TestLawState(t *testing.T) { } q.Close() - fenster := mustQuiet(t, "18:00-08:00") + // Das Ruhezeit-Fenster muss JETZT inaktiv sein, sonst würde die Ansage + // unten getoastet statt gesprochen — ein festes Fenster wäre eine + // Zeitbombe (rot zu bestimmten Tageszeiten). Deshalb dynamisch: eine + // Stunde, die zwei Stunden in der Zukunft beginnt. + window := inactiveQuietWindow(time.Now()) + fenster := mustQuiet(t, window) + if fenster.Active(time.Now()) { + t.Fatalf("Testfenster %s ist aktiv — darf nicht sein", window) + } q2 := New(Laws{RateLimit: time.Hour, AllowHighBurst: true, Quiet: fenster, QuietMode: QuietModeToast}, g.speak, nil) defer q2.Close() st2 := q2.LawState() if st2.RateLimit != time.Hour || !st2.AllowHighBurst { t.Errorf("LawState = %+v, want 1h-Fenster mit Burst-Recht", st2) } - if st2.Quiet.String() != "18:00-08:00" || st2.QuietMode != QuietModeToast { - t.Errorf("Ruhezeit in LawState = %q/%q", st2.Quiet, st2.QuietMode) + if st2.Quiet.String() != window || st2.QuietMode != QuietModeToast { + t.Errorf("Ruhezeit in LawState = %q/%q, want %q/toast", st2.Quiet, st2.QuietMode, window) + } + if st2.QuietActive || !st2.QuietUntil.IsZero() { + t.Errorf("Ruhezeit inaktiv erwartet, LawState meldet active=%v until=%v", st2.QuietActive, st2.QuietUntil) } q2.Enqueue(Item{Text: "erste"}) @@ -515,3 +526,29 @@ func TestLawState(t *testing.T) { } g.step <- struct{}{} } + +// inactiveQuietWindow liefert ein "HH:MM-HH:MM"-Fenster von einer Stunde, +// das zwei Stunden nach now beginnt — es enthält now garantiert nicht, egal +// zu welcher Tageszeit der Test läuft (auch über Mitternacht hinweg). +func inactiveQuietWindow(now time.Time) string { + start := now.Add(2 * time.Hour) + end := now.Add(3 * time.Hour) + return start.Format("15:04") + "-" + end.Format("15:04") +} + +// TestInactiveQuietWindow: Das Test-Hilfsfenster darf zu KEINER Tageszeit +// aktiv sein — sonst wäre TestLawState wieder eine Zeitbombe. +func TestInactiveQuietWindow(t *testing.T) { + base := time.Date(2026, 10, 24, 0, 0, 0, 0, time.Local) + for m := 0; m < 24*60; m += 7 { + now := base.Add(time.Duration(m) * time.Minute) + w := inactiveQuietWindow(now) + q, err := ParseQuietHours(w) + if err != nil { + t.Fatalf("%s: %v", now.Format("15:04"), err) + } + if q.Active(now) { + t.Errorf("um %s ist Fenster %s aktiv", now.Format("15:04"), w) + } + } +}