Skip to content

Commit ae05496

Browse files
JAORMXclaude
andcommitted
Fix flaky SpinnerObserver tests with WaitGroup sync
Add sync.WaitGroup to SpinnerObserver so stopSpinner() blocks until the animate() goroutine finishes its cleanup write, eliminating the race that caused TestSpinnerObserver_MultiplePhases flakiness. Remove all time.Sleep calls from tests since synchronization is now deterministic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e035912 commit ae05496

2 files changed

Lines changed: 4 additions & 5 deletions

File tree

internal/infra/progress/spinner.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type SpinnerObserver struct {
2626
out io.Writer
2727
mu sync.Mutex
2828
stop chan struct{} // nil when no spinner is active
29+
wg sync.WaitGroup
2930

3031
successStyle lipgloss.Style
3132
warnStyle lipgloss.Style
@@ -53,6 +54,7 @@ func (s *SpinnerObserver) Start(_ progress.Phase, msg string) {
5354
s.stop = stop
5455
s.mu.Unlock()
5556

57+
s.wg.Add(1)
5658
go s.animate(msg, stop)
5759
}
5860

@@ -81,9 +83,11 @@ func (s *SpinnerObserver) stopSpinner() {
8183
s.stop = nil
8284
}
8385
s.mu.Unlock()
86+
s.wg.Wait()
8487
}
8588

8689
func (s *SpinnerObserver) animate(msg string, stop <-chan struct{}) {
90+
defer s.wg.Done()
8791
ticker := time.NewTicker(80 * time.Millisecond)
8892
defer ticker.Stop()
8993

internal/infra/progress/spinner_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"bytes"
88
"strings"
99
"testing"
10-
"time"
1110

1211
"github.com/stretchr/testify/assert"
1312

@@ -57,8 +56,6 @@ func TestSpinnerObserver_StartThenComplete(t *testing.T) {
5756
obs := NewSpinnerObserver(&buf)
5857

5958
obs.Start(progress.PhaseStartingVM, "Starting VM...")
60-
// Give the goroutine a moment to emit at least one frame.
61-
time.Sleep(150 * time.Millisecond)
6259
obs.Complete("VM started")
6360

6461
output := buf.String()
@@ -73,11 +70,9 @@ func TestSpinnerObserver_MultiplePhases(t *testing.T) {
7370
obs := NewSpinnerObserver(&buf)
7471

7572
obs.Start(progress.PhaseResolvingAgent, "Resolving...")
76-
time.Sleep(100 * time.Millisecond)
7773
obs.Complete("Resolved")
7874

7975
obs.Start(progress.PhaseStartingVM, "Starting...")
80-
time.Sleep(100 * time.Millisecond)
8176
obs.Complete("Started")
8277

8378
output := buf.String()

0 commit comments

Comments
 (0)