@@ -1154,3 +1154,145 @@ def test_inactivity_timeout_triggers_reconnect(self, mock_server: MockSSEServer)
11541154
11551155 # Should have the new value after reconnect
11561156 assert client .get ("feature" ) == "after-reconnect"
1157+
1158+
1159+ class TestReplaneClientId :
1160+ """Test auto-generated replaneClientId context field."""
1161+
1162+ def test_auto_generates_replane_client_id (self , mock_server : MockSSEServer ):
1163+ """Client auto-generates replaneClientId and uses it for segmentation."""
1164+ mock_server .send_init (
1165+ [
1166+ create_config (
1167+ "feature" ,
1168+ "default" ,
1169+ overrides = [
1170+ create_override (
1171+ "segmented-override" ,
1172+ "segmented-value" ,
1173+ [
1174+ {
1175+ "operator" : "segmentation" ,
1176+ "property" : "replaneClientId" ,
1177+ "fromPercentage" : 0 ,
1178+ "toPercentage" : 100 ,
1179+ "seed" : "test-seed" ,
1180+ }
1181+ ],
1182+ ),
1183+ ],
1184+ ),
1185+ ]
1186+ )
1187+
1188+ # Create client without providing replaneClientId
1189+ with Replane (
1190+ base_url = mock_server .url ,
1191+ sdk_key = "rp_test_key" ,
1192+ ) as client :
1193+ # Should match segmentation because replaneClientId is auto-generated
1194+ assert client .get ("feature" ) == "segmented-value"
1195+
1196+ def test_user_provided_replane_client_id_takes_precedence (
1197+ self , mock_server : MockSSEServer
1198+ ):
1199+ """User-provided replaneClientId takes precedence over auto-generated one."""
1200+ user_provided_id = "user-provided-client-id"
1201+ mock_server .send_init (
1202+ [
1203+ create_config (
1204+ "feature" ,
1205+ "default" ,
1206+ overrides = [
1207+ create_override (
1208+ "user-override" ,
1209+ "user-override-value" ,
1210+ [create_condition ("equals" , "replaneClientId" , user_provided_id )],
1211+ ),
1212+ ],
1213+ ),
1214+ ]
1215+ )
1216+
1217+ # Provide replaneClientId in context - should take precedence
1218+ with Replane (
1219+ base_url = mock_server .url ,
1220+ sdk_key = "rp_test_key" ,
1221+ context = {"replaneClientId" : user_provided_id },
1222+ ) as client :
1223+ assert client .get ("feature" ) == "user-override-value"
1224+
1225+ def test_per_request_context_overrides_replane_client_id (
1226+ self , mock_server : MockSSEServer
1227+ ):
1228+ """Per-request context can override replaneClientId."""
1229+ per_request_id = "per-request-client-id"
1230+ mock_server .send_init (
1231+ [
1232+ create_config (
1233+ "feature" ,
1234+ "default" ,
1235+ overrides = [
1236+ create_override (
1237+ "per-request-override" ,
1238+ "per-request-value" ,
1239+ [create_condition ("equals" , "replaneClientId" , per_request_id )],
1240+ ),
1241+ ],
1242+ ),
1243+ ]
1244+ )
1245+
1246+ with Replane (
1247+ base_url = mock_server .url ,
1248+ sdk_key = "rp_test_key" ,
1249+ ) as client :
1250+ # Default should be based on auto-generated ID (won't match)
1251+ assert client .get ("feature" ) == "default"
1252+
1253+ # Per-request context should override the auto-generated ID
1254+ assert (
1255+ client .get ("feature" , context = {"replaneClientId" : per_request_id })
1256+ == "per-request-value"
1257+ )
1258+
1259+ def test_unique_replane_client_id_per_client_instance (
1260+ self , mock_server : MockSSEServer
1261+ ):
1262+ """Each client instance gets a unique replaneClientId."""
1263+ mock_server .send_init (
1264+ [
1265+ create_config (
1266+ "feature" ,
1267+ "default" ,
1268+ overrides = [
1269+ create_override (
1270+ "50-percent-rollout" ,
1271+ "rollout-value" ,
1272+ [
1273+ {
1274+ "operator" : "segmentation" ,
1275+ "property" : "replaneClientId" ,
1276+ "fromPercentage" : 0 ,
1277+ "toPercentage" : 50 ,
1278+ "seed" : "test-seed" ,
1279+ }
1280+ ],
1281+ ),
1282+ ],
1283+ ),
1284+ ]
1285+ )
1286+
1287+ # Create multiple clients and check they get different segmentation results
1288+ results = []
1289+ for _ in range (10 ):
1290+ with Replane (
1291+ base_url = mock_server .url ,
1292+ sdk_key = "rp_test_key" ,
1293+ ) as client :
1294+ results .append (client .get ("feature" ))
1295+
1296+ # With 10 clients and 50% rollout, we should statistically see both values
1297+ # This test mainly verifies that segmentation is working
1298+ assert "rollout-value" in results or "default" in results
0 commit comments