@@ -752,6 +752,96 @@ def test_basic_capture_with_feature_flags_switched_off_doesnt_send_them(
752752
753753 self .assertEqual (patch_flags .call_count , 0 )
754754
755+ @mock .patch ("posthog.client.flags" )
756+ def test_capture_with_send_feature_flags_true_and_local_evaluation_uses_local_flags (
757+ self , patch_flags
758+ ):
759+ """Test that send_feature_flags=True with local evaluation enabled uses local flags without API call"""
760+ patch_flags .return_value = {"featureFlags" : {"remote-flag" : "remote-variant" }}
761+
762+ multivariate_flag = {
763+ "id" : 1 ,
764+ "name" : "Beta Feature" ,
765+ "key" : "beta-feature-local" ,
766+ "active" : True ,
767+ "rollout_percentage" : 100 ,
768+ "filters" : {
769+ "groups" : [
770+ {
771+ "rollout_percentage" : 100 ,
772+ },
773+ ],
774+ "multivariate" : {
775+ "variants" : [
776+ {
777+ "key" : "first-variant" ,
778+ "name" : "First Variant" ,
779+ "rollout_percentage" : 50 ,
780+ },
781+ {
782+ "key" : "second-variant" ,
783+ "name" : "Second Variant" ,
784+ "rollout_percentage" : 50 ,
785+ },
786+ ]
787+ },
788+ },
789+ }
790+ simple_flag = {
791+ "id" : 2 ,
792+ "name" : "Simple Flag" ,
793+ "key" : "simple-flag" ,
794+ "active" : True ,
795+ "filters" : {
796+ "groups" : [
797+ {
798+ "rollout_percentage" : 100 ,
799+ }
800+ ],
801+ },
802+ }
803+
804+ with mock .patch ("posthog.client.batch_post" ) as mock_post :
805+ client = Client (
806+ FAKE_TEST_API_KEY ,
807+ on_error = self .set_fail ,
808+ personal_api_key = FAKE_TEST_API_KEY ,
809+ sync_mode = True ,
810+ )
811+ client .feature_flags = [multivariate_flag , simple_flag ]
812+
813+ msg_uuid = client .capture (
814+ "python test event" ,
815+ distinct_id = "distinct_id" ,
816+ send_feature_flags = True ,
817+ )
818+ self .assertIsNotNone (msg_uuid )
819+ self .assertFalse (self .failed )
820+
821+ # Get the enqueued message from the mock
822+ mock_post .assert_called_once ()
823+ batch_data = mock_post .call_args [1 ]["batch" ]
824+ msg = batch_data [0 ]
825+
826+ self .assertEqual (msg ["event" ], "python test event" )
827+ self .assertEqual (msg ["distinct_id" ], "distinct_id" )
828+
829+ # Verify local flags are included in the event
830+ self .assertIn ("$feature/beta-feature-local" , msg ["properties" ])
831+ self .assertIn ("$feature/simple-flag" , msg ["properties" ])
832+ self .assertEqual (msg ["properties" ]["$feature/simple-flag" ], True )
833+
834+ # Verify active feature flags are set correctly
835+ active_flags = msg ["properties" ]["$active_feature_flags" ]
836+ self .assertIn ("beta-feature-local" , active_flags )
837+ self .assertIn ("simple-flag" , active_flags )
838+
839+ # The remote flag should NOT be included since we used local evaluation
840+ self .assertNotIn ("$feature/remote-flag" , msg ["properties" ])
841+
842+ # CRITICAL: Verify the /flags API was NOT called
843+ self .assertEqual (patch_flags .call_count , 0 )
844+
755845 @mock .patch ("posthog.client.flags" )
756846 def test_capture_with_send_feature_flags_options_only_evaluate_locally_true (
757847 self , patch_flags
0 commit comments