1package services
2
3import (
4 "testing"
5 "time"
6
7 "github.com/bnema/archup/internal/application/dto"
8)
9
10func TestProgressTracker_Subscribe(t *testing.T) {
11 tracker := NewProgressTracker()
12 defer tracker.Close()
13
14 ch := tracker.Subscribe()
15 if ch == nil {
16 t.Fatal("expected non-nil channel")
17 }
18}
19
20func TestProgressTracker_Emit(t *testing.T) {
21 tracker := NewProgressTracker()
22 defer tracker.Close()
23
24 ch := tracker.Subscribe()
25
26 update := &dto.ProgressUpdate{
27 Phase: "Test Phase",
28 PhaseNumber: 1,
29 TotalPhases: 8,
30 ProgressPercent: 10,
31 Message: "Test message",
32 IsError: false,
33 }
34
35 go tracker.Emit(update)
36
37 select {
38 case received := <-ch:
39 if received.Phase != "Test Phase" {
40 t.Errorf("expected phase 'Test Phase', got %s", received.Phase)
41 }
42 if received.Message != "Test message" {
43 t.Errorf("expected message 'Test message', got %s", received.Message)
44 }
45 case <-time.After(1 * time.Second):
46 t.Fatal("timeout waiting for progress update")
47 }
48}
49
50func TestProgressTracker_MultipleSubscribers(t *testing.T) {
51 tracker := NewProgressTracker()
52 defer tracker.Close()
53
54 ch1 := tracker.Subscribe()
55 ch2 := tracker.Subscribe()
56
57 update := &dto.ProgressUpdate{
58 Phase: "Test",
59 Message: "Test message",
60 }
61
62 go tracker.Emit(update)
63
64 // Both channels should receive the update
65 select {
66 case <-ch1:
67 case <-time.After(1 * time.Second):
68 t.Fatal("timeout on ch1")
69 }
70
71 select {
72 case <-ch2:
73 case <-time.After(1 * time.Second):
74 t.Fatal("timeout on ch2")
75 }
76}
77
78func TestProgressTracker_EmitPhaseStarted(t *testing.T) {
79 tracker := NewProgressTracker()
80 defer tracker.Close()
81
82 ch := tracker.Subscribe()
83
84 go tracker.EmitPhaseStarted("Preflight", 1, 8)
85
86 select {
87 case update := <-ch:
88 if update.Phase != "Preflight" {
89 t.Errorf("expected phase 'Preflight', got %s", update.Phase)
90 }
91 if update.Message != "Starting Preflight" {
92 t.Errorf("expected message 'Starting Preflight', got %s", update.Message)
93 }
94 if update.ProgressPercent != 0 {
95 t.Errorf("expected progress 0%%, got %d%%", update.ProgressPercent)
96 }
97 case <-time.After(1 * time.Second):
98 t.Fatal("timeout waiting for phase started event")
99 }
100}
101
102func TestProgressTracker_EmitPhaseCompleted(t *testing.T) {
103 tracker := NewProgressTracker()
104 defer tracker.Close()
105
106 ch := tracker.Subscribe()
107
108 go tracker.EmitPhaseCompleted("Preflight", 1, 8)
109
110 select {
111 case update := <-ch:
112 if update.Phase != "Preflight" {
113 t.Errorf("expected phase 'Preflight', got %s", update.Phase)
114 }
115 if update.Message != "Preflight completed" {
116 t.Errorf("expected message 'Preflight completed', got %s", update.Message)
117 }
118 if update.ProgressPercent != 12 { // 1 * 100 / 8 = 12%
119 t.Errorf("expected progress 12%%, got %d%%", update.ProgressPercent)
120 }
121 case <-time.After(1 * time.Second):
122 t.Fatal("timeout waiting for phase completed event")
123 }
124}
125
126func TestProgressTracker_EmitPhaseError(t *testing.T) {
127 tracker := NewProgressTracker()
128 defer tracker.Close()
129
130 ch := tracker.Subscribe()
131
132 go tracker.EmitPhaseError("Preflight", 1, 8, "Something went wrong")
133
134 select {
135 case update := <-ch:
136 if update.Phase != "Preflight" {
137 t.Errorf("expected phase 'Preflight', got %s", update.Phase)
138 }
139 if update.Message != "Something went wrong" {
140 t.Errorf("expected error message, got %s", update.Message)
141 }
142 if !update.IsError {
143 t.Error("expected IsError to be true")
144 }
145 case <-time.After(1 * time.Second):
146 t.Fatal("timeout waiting for phase error event")
147 }
148}
149
150// Note: Unsubscribe test is not practical since Subscribe returns a read-only channel
151// and the internal channel is not directly accessible to the caller.
152
153func TestProgressTracker_TimestampSet(t *testing.T) {
154 tracker := NewProgressTracker()
155 defer tracker.Close()
156
157 ch := tracker.Subscribe()
158
159 update := &dto.ProgressUpdate{
160 Phase: "Test",
161 Message: "Test message",
162 // Timestamp is zero
163 }
164
165 go tracker.Emit(update)
166
167 select {
168 case received := <-ch:
169 if received.Timestamp.IsZero() {
170 t.Error("expected timestamp to be set")
171 }
172 case <-time.After(1 * time.Second):
173 t.Fatal("timeout waiting for progress update")
174 }
175}