@@ -882,6 +882,56 @@ class FeatureFlagManagerTests: XCTestCase {
882882 let missingFieldResult = parseResponse ( missingFieldJSON)
883883 XCTAssertNotNil ( missingFieldResult, " Parser should handle missing flags field " )
884884 XCTAssertNil ( missingFieldResult? . flags, " Flags should be nil when field is missing " )
885+
886+ let optionalExperimentPropertiesJSON = """
887+ {
888+ " flags " : {
889+ " active_experiment_flag " : {
890+ " variant_key " : " A " ,
891+ " variant_value " : " A " ,
892+ " experiment_id " : " 447db52b-ec4a-4186-8d89-f9ba7bc7d7dd " ,
893+ " is_experiment_active " : true,
894+ " is_qa_tester " : false
895+ },
896+ " experiment_flag_for_qa_user " : {
897+ " variant_key " : " B " ,
898+ " variant_value " : " B " ,
899+ " experiment_id " : " 447db52b-ec4a-4186-8d89-f9ba7bc7d7dd " ,
900+ " is_experiment_active " : false,
901+ " is_qa_tester " : true
902+ },
903+ " flag_with_no_optionals " : {
904+ " variant_key " : " C " ,
905+ " variant_value " : " C "
906+ }
907+ }
908+ }
909+ """ . data ( using: . utf8) !
910+
911+ let experimentResult = parseResponse ( optionalExperimentPropertiesJSON)
912+ XCTAssertNotNil ( experimentResult)
913+ XCTAssertEqual ( experimentResult? . flags? . count, 3 )
914+
915+ let activeFlag = experimentResult? . flags ? [ " active_experiment_flag " ]
916+ XCTAssertEqual ( activeFlag? . key, " A " )
917+ XCTAssertEqual ( activeFlag? . value as? String , " A " )
918+ XCTAssertEqual ( activeFlag? . experimentID, " 447db52b-ec4a-4186-8d89-f9ba7bc7d7dd " )
919+ XCTAssertEqual ( activeFlag? . isExperimentActive, true )
920+ XCTAssertEqual ( activeFlag? . isQATester, false )
921+
922+ let qaFlag = experimentResult? . flags ? [ " experiment_flag_for_qa_user " ]
923+ XCTAssertEqual ( qaFlag? . key, " B " )
924+ XCTAssertEqual ( qaFlag? . value as? String , " B " )
925+ XCTAssertEqual ( qaFlag? . experimentID, " 447db52b-ec4a-4186-8d89-f9ba7bc7d7dd " )
926+ XCTAssertEqual ( qaFlag? . isExperimentActive, false )
927+ XCTAssertEqual ( qaFlag? . isQATester, true )
928+
929+ let minimalFlag = experimentResult? . flags ? [ " flag_with_no_optionals " ]
930+ XCTAssertEqual ( minimalFlag? . key, " C " )
931+ XCTAssertEqual ( minimalFlag? . value as? String , " C " )
932+ XCTAssertNil ( minimalFlag? . experimentID)
933+ XCTAssertNil ( minimalFlag? . isExperimentActive)
934+ XCTAssertNil ( minimalFlag? . isQATester)
885935 }
886936
887937 // --- Delegate Error Handling Tests ---
@@ -1258,6 +1308,23 @@ class FeatureFlagManagerTests: XCTestCase {
12581308 }
12591309 }
12601310
1311+ func testTrackingIncludesOptionalProperties( ) {
1312+ // Set up flags with experiment properties
1313+ let flagsWithExperiment : [ String : MixpanelFlagVariant ] = [
1314+ " experiment_flag " : MixpanelFlagVariant ( key: " variant_a " , value: true , isExperimentActive: true , isQATester: false , experimentID: " exp_123 " )
1315+ ]
1316+ simulateFetchSuccess ( flags: flagsWithExperiment)
1317+
1318+ mockDelegate. trackExpectation = XCTestExpectation ( description: " Track with experiment properties " )
1319+ _ = manager. getVariantSync ( " experiment_flag " , fallback: defaultFallback)
1320+ wait ( for: [ mockDelegate. trackExpectation!] , timeout: 1.0 )
1321+
1322+ let props = mockDelegate. trackedEvents [ 0 ] . properties!
1323+ XCTAssertEqual ( props [ " $experiment_id " ] as? String , " exp_123 " )
1324+ XCTAssertEqual ( props [ " $is_experiment_active " ] as? Bool , true )
1325+ XCTAssertEqual ( props [ " $is_qa_tester " ] as? Bool , false )
1326+ }
1327+
12611328 // MARK: - Timing Properties Sanity Tests
12621329
12631330 func testTimingPropertiesSanity( ) {
0 commit comments