package web import ( "os" "path/filepath" "testing" "time" ) func TestWatchLogDebouncesChanges(t *testing.T) { logPath := filepath.Join(t.TempDir(), "trace.jsonl") if err := os.WriteFile(logPath, []byte("initial\n"), 0o644); err != nil { t.Fatal(err) } done := make(chan struct{}) stopped := make(chan struct{}) rebuilt := make(chan struct{}, 2) go func() { defer close(stopped) watchLogUntil(newFileLog(logPath), 60*time.Millisecond, 5*time.Millisecond, done, func() { rebuilt <- struct{}{} }) }() time.Sleep(20 * time.Millisecond) if err := os.WriteFile(logPath, []byte("first change\n"), 0o644); err != nil { t.Fatal(err) } time.Sleep(30 * time.Millisecond) if err := os.WriteFile(logPath, []byte("second change\n"), 0o644); err != nil { t.Fatal(err) } select { case <-rebuilt: t.Fatal("rebuilt before the debounce interval elapsed") case <-time.After(40 * time.Millisecond): } select { case <-rebuilt: case <-time.After(200 * time.Millisecond): t.Fatal("did not rebuild after changes settled") } select { case <-rebuilt: t.Fatal("multiple changes produced more than one rebuild") case <-time.After(40 * time.Millisecond): } close(done) select { case <-stopped: case <-time.After(time.Second): t.Fatal("watcher did not stop") } }