@@ -61,6 +61,53 @@ describe("QueueMetricsProcessor", () => {
6161 expect ( ( ) => processor . addSample ( 0 ) ) . not . toThrow ( ) ;
6262 expect ( processor . getCurrentSampleCount ( ) ) . toBe ( 1 ) ;
6363 } ) ;
64+
65+ it ( "should handle empty queue with all zero samples" , ( ) => {
66+ processor . addSample ( 0 ) ;
67+ processor . addSample ( 0 ) ;
68+ processor . addSample ( 0 ) ;
69+
70+ const result = processor . processBatch ( ) ;
71+ expect ( result ) . not . toBeNull ( ) ;
72+ expect ( result ! . median ) . toBe ( 0 ) ;
73+ expect ( result ! . smoothedValue ) . toBe ( 0 ) ;
74+ expect ( processor . getSmoothedValue ( ) ) . toBe ( 0 ) ;
75+ } ) ;
76+
77+ it ( "should properly transition from zero to non-zero queue" , ( ) => {
78+ // Start with empty queue
79+ processor . addSample ( 0 ) ;
80+ processor . addSample ( 0 ) ;
81+ let result = processor . processBatch ( ) ;
82+ expect ( result ! . median ) . toBe ( 0 ) ;
83+ expect ( result ! . smoothedValue ) . toBe ( 0 ) ;
84+
85+ // Queue starts filling
86+ processor . addSample ( 10 ) ;
87+ processor . addSample ( 15 ) ;
88+ result = processor . processBatch ( ) ;
89+ expect ( result ! . median ) . toBeGreaterThan ( 0 ) ;
90+ // EWMA: 0.3 * median + 0.7 * 0
91+ expect ( result ! . smoothedValue ) . toBeGreaterThan ( 0 ) ;
92+ } ) ;
93+
94+ it ( "should properly transition from non-zero to zero queue" , ( ) => {
95+ // Start with non-empty queue
96+ processor . addSample ( 10 ) ;
97+ processor . addSample ( 15 ) ;
98+ let result = processor . processBatch ( ) ;
99+ const initialSmoothed = result ! . smoothedValue ;
100+ expect ( initialSmoothed ) . toBeGreaterThan ( 0 ) ;
101+
102+ // Queue becomes empty
103+ processor . addSample ( 0 ) ;
104+ processor . addSample ( 0 ) ;
105+ processor . addSample ( 0 ) ;
106+ result = processor . processBatch ( ) ;
107+ expect ( result ! . median ) . toBe ( 0 ) ;
108+ // EWMA should gradually decrease: 0.3 * 0 + 0.7 * initialSmoothed
109+ expect ( result ! . smoothedValue ) . toBe ( 0.7 * initialSmoothed ) ;
110+ } ) ;
64111 } ) ;
65112
66113 describe ( "Batch processing timing" , ( ) => {
@@ -146,6 +193,15 @@ describe("QueueMetricsProcessor", () => {
146193 processor = new QueueMetricsProcessor ( { ewmaAlpha : 0.3 , batchWindowMs : 1000 } ) ;
147194 } ) ;
148195
196+ it ( "should calculate median of single sample" , ( ) => {
197+ processor . addSample ( 42 ) ;
198+
199+ const result = processor . processBatch ( ) ;
200+ expect ( result ! . median ) . toBe ( 42 ) ;
201+ expect ( result ! . sampleCount ) . toBe ( 1 ) ;
202+ expect ( result ! . smoothedValue ) . toBe ( 42 ) ; // First batch initializes to median
203+ } ) ;
204+
149205 it ( "should calculate median of odd number of samples" , ( ) => {
150206 processor . addSample ( 1 ) ;
151207 processor . addSample ( 10 ) ;
@@ -162,9 +218,9 @@ describe("QueueMetricsProcessor", () => {
162218 processor . addSample ( 8 ) ;
163219
164220 const result = processor . processBatch ( ) ;
165- // With even count, we take the lower middle value (index 1)
166- // Sorted: [1, 5, 8, 10], median index = floor(4/2) = 2, so median = 8
167- expect ( result ! . median ) . toBe ( 8 ) ;
221+ // With even count, we average the two middle values
222+ // Sorted: [1, 5, 8, 10], median = (5 + 8) / 2 = 6.5
223+ expect ( result ! . median ) . toBe ( 6.5 ) ;
168224 } ) ;
169225
170226 it ( "should filter outliers using median" , ( ) => {
0 commit comments