@@ -19,6 +19,7 @@ package handlers
19
19
20
20
import (
21
21
"context"
22
+ "encoding/json"
22
23
"errors"
23
24
"fmt"
24
25
"net/http"
@@ -106,7 +107,7 @@ func (suite *NotificationTestSuite) TestFeatureTestFilter() {
106
107
suite .Equal (http .StatusOK , rec .Code )
107
108
108
109
// Unmarshal response
109
- response := string ( rec .Body .Bytes () )
110
+ response := rec .Body .String ( )
110
111
suite .Equal (expected , response )
111
112
}
112
113
@@ -170,7 +171,7 @@ func (suite *NotificationTestSuite) TestTrackAndProjectConfig() {
170
171
suite .Equal (http .StatusOK , rec .Code )
171
172
172
173
// Unmarshal response
173
- response := string ( rec .Body .Bytes () )
174
+ response := rec .Body .String ( )
174
175
suite .Equal (expected , response )
175
176
}
176
177
@@ -428,6 +429,65 @@ func TestRedisNotificationReceiver(t *testing.T) {
428
429
}
429
430
}
430
431
432
+ func (suite * NotificationTestSuite ) TestExperimentAndVariationIDsInNotification () {
433
+ req := httptest .NewRequest ("GET" , "/notifications/event-stream" , nil )
434
+ rec := httptest .NewRecorder ()
435
+
436
+ // Create a decision notification with experiment_id and variation_id fields
437
+ decisionEvent := map [string ]interface {}{
438
+ "Type" : "decision" ,
439
+ "UserContext" : map [string ]interface {}{
440
+ "ID" : "test_user_id" ,
441
+ },
442
+ "DecisionInfo" : map [string ]interface {}{
443
+ "flagKey" : "test_flag" ,
444
+ "enabled" : true ,
445
+ "variationKey" : "test_variation" ,
446
+ "ruleKey" : "test_experiment" ,
447
+ "experimentId" : "exp_id_123" ,
448
+ "variationId" : "var_id_456" ,
449
+ },
450
+ }
451
+
452
+ // Expected output in SSE format
453
+ expected := `data: ` + jsonMustMarshal (decisionEvent ) + "\n \n "
454
+
455
+ // Create a cancelable request context
456
+ ctx := req .Context ()
457
+ ctx1 , _ := context .WithTimeout (ctx , 2 * time .Second )
458
+
459
+ // Create notification event with our test data
460
+ notifications := []syncer.Event {
461
+ {Type : notification .Decision , Message : decisionEvent },
462
+ }
463
+
464
+ // Set up the notification endpoint with our test data
465
+ conf := config .NewDefaultConfig ()
466
+ suite .mux .Get ("/notifications/event-stream" , NotificationEventStreamHandler (
467
+ getMockNotificationReceiver (conf .Synchronization , false , notifications ... )))
468
+
469
+ // Send the request
470
+ suite .mux .ServeHTTP (rec , req .WithContext (ctx1 ))
471
+
472
+ // Verify response code and body
473
+ suite .Equal (http .StatusOK , rec .Code )
474
+ response := string (rec .Body .Bytes ())
475
+ suite .Equal (expected , response )
476
+
477
+ // Explicitly check for our test fields
478
+ suite .Contains (response , `"experimentId":"exp_id_123"` )
479
+ suite .Contains (response , `"variationId":"var_id_456"` )
480
+ }
481
+
482
+ // Helper to marshal JSON without error handling in the test
483
+ func jsonMustMarshal (v interface {}) string {
484
+ bytes , err := json .Marshal (v )
485
+ if err != nil {
486
+ panic (err )
487
+ }
488
+ return string (bytes )
489
+ }
490
+
431
491
func getMockNotificationReceiver (conf config.SyncConfig , returnError bool , msg ... syncer.Event ) NotificationReceiverFunc {
432
492
return func (ctx context.Context ) (<- chan syncer.Event , error ) {
433
493
if returnError {
0 commit comments