package test // Process-boundary test for the quiet-hours toast: quiet_mode = toast during // active quiet hours fires a desktop notification — here a fake notify-send // in the daemon's PATH that logs its arguments. import ( "os" "path/filepath" "runtime" "strings" "testing" "time" ) func TestQuietHoursToastShowsNotification(t *testing.T) { if runtime.GOOS != "linux" { t.Skip("the fake notify-send exists only on Linux") } root := t.TempDir() bin := filepath.Join(root, "bin") if err := os.MkdirAll(bin, 0o755); err != nil { t.Fatal(err) } seen := filepath.Join(root, "seen.txt") script := "#!/bin/sh\nprintf '%s\\n' \"$@\" > \"" + seen + "\"\n" if err := os.WriteFile(filepath.Join(bin, "notify-send"), []byte(script), 0o755); err != nil { t.Fatal(err) } fake := newFakeProvider(t, 0) d := startDaemon(t, root, fake.srv.URL, map[string]string{ "TALK_QUIET_HOURS": windowAround(), "TALK_QUIET_MODE": "toast", "PATH": bin + string(os.PathListSeparator) + os.Getenv("PATH"), }) code, m := speak(t, d, `{"text":"Build done, please review"}`) if code != 202 || m["discarded"] != "quiet_hours" || m["toast"] != true { t.Fatalf("speak during quiet hours (toast): %d %v", code, m) } deadline := time.Now().Add(3 * time.Second) for { if b, err := os.ReadFile(seen); err == nil { if !strings.Contains(string(b), "Build done, please review") || !strings.Contains(string(b), "talk") { t.Errorf("notify-send arguments = %q", b) } break } if time.Now().After(deadline) { t.Fatalf("notify-send was not called — daemon log:\n%s", d.stderr.String()) } time.Sleep(25 * time.Millisecond) } fake.assertNoHits(t, 200*time.Millisecond) }