@@ -10,7 +10,6 @@ import (
1010 "sync"
1111 "testing"
1212 "time"
13-
1413 flagsmith "github.com/Flagsmith/flagsmith-go-client/v4"
1514 "github.com/Flagsmith/flagsmith-go-client/v4/fixtures"
1615 "github.com/stretchr/testify/assert"
@@ -200,6 +199,7 @@ func TestGetFlags(t *testing.T) {
200199 assert .Equal (t , fixtures .Feature1Name , allFlags [0 ].FeatureName )
201200 assert .Equal (t , fixtures .Feature1ID , allFlags [0 ].FeatureID )
202201 assert .Equal (t , fixtures .Feature1Value , allFlags [0 ].Value )
202+
203203}
204204
205205func TestGetFlagsTransientIdentity (t * testing.T ) {
@@ -861,3 +861,101 @@ func TestPollErrorHandlerIsUsedWhenPollFails(t *testing.T) {
861861 assert .Equal (t , statusCode , 500 )
862862 assert .Equal (t , status , "500 Internal Server Error" )
863863}
864+
865+ func TestRealtime (t * testing.T ) {
866+ // Given
867+ mux := http .NewServeMux ()
868+ requestCount := struct {
869+ mu sync.Mutex
870+ count int
871+ }{}
872+
873+ mux .HandleFunc ("/api/v1/environment-document/" , func (rw http.ResponseWriter , req * http.Request ) {
874+ assert .Equal (t , "GET" , req .Method )
875+ assert .Equal (t , fixtures .EnvironmentAPIKey , req .Header .Get ("X-Environment-Key" ))
876+ requestCount .mu .Lock ()
877+ requestCount .count ++
878+ requestCount .mu .Unlock ()
879+
880+ rw .Header ().Set ("Content-Type" , "application/json" )
881+ rw .WriteHeader (http .StatusOK )
882+ _ , err := io .WriteString (rw , fixtures .EnvironmentJson )
883+ if err != nil {
884+ panic (err )
885+ }
886+ assert .NoError (t , err )
887+ })
888+ mux .HandleFunc (fmt .Sprintf ("/sse/environments/%s/stream" , fixtures .ClientAPIKey ), func (rw http.ResponseWriter , req * http.Request ) {
889+ assert .Equal (t , "GET" , req .Method )
890+
891+ // Set the necessary headers for SSE
892+ rw .Header ().Set ("Content-Type" , "text/event-stream" )
893+ rw .Header ().Set ("Cache-Control" , "no-cache" )
894+ rw .Header ().Set ("Connection" , "keep-alive" )
895+
896+ // Flush headers to the client
897+ flusher , _ := rw .(http.Flusher )
898+ flusher .Flush ()
899+
900+ // Use an `updated_at` value that is older than the `updated_at` set on the environment document
901+ // to ensure an older timestamp does not trigger an update.
902+ sendUpdatedAtSSEEvent (rw , flusher , 1640995200.079725 )
903+ time .Sleep (10 * time .Millisecond )
904+
905+ // Update the `updated_at`(to trigger the environment update)
906+ sendUpdatedAtSSEEvent (rw , flusher , 1733480514.079725 )
907+ time .Sleep (10 * time .Millisecond )
908+ })
909+
910+ ctx := context .Background ()
911+
912+ server := httptest .NewServer (mux )
913+ defer server .Close ()
914+
915+ // When
916+ client := flagsmith .NewClient (fixtures .EnvironmentAPIKey ,
917+ flagsmith .WithBaseURL (server .URL + "/api/v1/" ),
918+ flagsmith .WithLocalEvaluation (ctx ),
919+ flagsmith .WithRealtime (),
920+ flagsmith .WithRealtimeBaseURL (server .URL + "/" ),
921+ )
922+ // Sleep to ensure that the server has time to update the environment
923+ time .Sleep (10 * time .Millisecond )
924+
925+ flags , err := client .GetFlags (ctx , nil )
926+
927+ // Then
928+ assert .NoError (t , err )
929+
930+ allFlags := flags .AllFlags ()
931+
932+ assert .Equal (t , 1 , len (allFlags ))
933+
934+ assert .Equal (t , fixtures .Feature1Name , allFlags [0 ].FeatureName )
935+ assert .Equal (t , fixtures .Feature1ID , allFlags [0 ].FeatureID )
936+ assert .Equal (t , fixtures .Feature1Value , allFlags [0 ].Value )
937+
938+ // Sleep to ensure that the server has time to update the environment
939+ // (After the second sse event)
940+ time .Sleep (10 * time .Millisecond )
941+
942+ requestCount .mu .Lock ()
943+ assert .Equal (t , 2 , requestCount .count )
944+ }
945+ func sendUpdatedAtSSEEvent (rw http.ResponseWriter , flusher http.Flusher , updatedAt float64 ) {
946+ // Format the SSE event with the provided updatedAt value
947+ sseEvent := fmt .Sprintf (`event: environment_updated
948+ data: {"updated_at": %f}
949+
950+ ` , updatedAt )
951+
952+ // Write the SSE event to the response
953+ _ , err := io .WriteString (rw , sseEvent )
954+ if err != nil {
955+ http .Error (rw , "Failed to send SSE event" , http .StatusInternalServerError )
956+ return
957+ }
958+
959+ // Flush the event to the client
960+ flusher .Flush ()
961+ }
0 commit comments