@@ -105,6 +105,110 @@ def test_basic_capture_with_feature_flags(self, patch_decide):
105105
106106 self .assertEqual (patch_decide .call_count , 1 )
107107
108+ @mock .patch ("posthog.client.decide" )
109+ def test_basic_capture_with_locally_evaluated_feature_flags (self , patch_decide ):
110+ patch_decide .return_value = {"featureFlags" : {"beta-feature" : "random-variant" }}
111+ client = Client (FAKE_TEST_API_KEY , on_error = self .set_fail , personal_api_key = FAKE_TEST_API_KEY )
112+
113+ multivariate_flag = {
114+ "id" : 1 ,
115+ "name" : "Beta Feature" ,
116+ "key" : "beta-feature-local" ,
117+ "is_simple_flag" : False ,
118+ "active" : True ,
119+ "rollout_percentage" : 100 ,
120+ "filters" : {
121+ "groups" : [
122+ {
123+ "properties" : [
124+ {
"key" :
"email" ,
"type" :
"person" ,
"value" :
"[email protected] " ,
"operator" :
"exact" }
125+ ],
126+ "rollout_percentage" : 100 ,
127+ },
128+ {
129+ "rollout_percentage" : 50 ,
130+ },
131+ ],
132+ "multivariate" : {
133+ "variants" : [
134+ {"key" : "first-variant" , "name" : "First Variant" , "rollout_percentage" : 50 },
135+ {"key" : "second-variant" , "name" : "Second Variant" , "rollout_percentage" : 25 },
136+ {"key" : "third-variant" , "name" : "Third Variant" , "rollout_percentage" : 25 },
137+ ]
138+ },
139+ "payloads" : {"first-variant" : "some-payload" , "third-variant" : {"a" : "json" }},
140+ },
141+ }
142+ basic_flag = {
143+ "id" : 1 ,
144+ "name" : "Beta Feature" ,
145+ "key" : "person-flag" ,
146+ "is_simple_flag" : True ,
147+ "active" : True ,
148+ "filters" : {
149+ "groups" : [
150+ {
151+ "properties" : [
152+ {
153+ "key" : "region" ,
154+ "operator" : "exact" ,
155+ "value" : ["USA" ],
156+ "type" : "person" ,
157+ }
158+ ],
159+ "rollout_percentage" : 100 ,
160+ }
161+ ],
162+ "payloads" : {"true" : 300 },
163+ },
164+ }
165+ false_flag = {
166+ "id" : 1 ,
167+ "name" : "Beta Feature" ,
168+ "key" : "false-flag" ,
169+ "is_simple_flag" : True ,
170+ "active" : True ,
171+ "filters" : {
172+ "groups" : [
173+ {
174+ "properties" : [],
175+ "rollout_percentage" : 0 ,
176+ }
177+ ],
178+ "payloads" : {"true" : 300 },
179+ },
180+ }
181+ client .feature_flags = [multivariate_flag , basic_flag , false_flag ]
182+
183+ success , msg = client .capture ("distinct_id" , "python test event" )
184+ client .flush ()
185+ self .assertTrue (success )
186+ self .assertFalse (self .failed )
187+
188+ self .assertEqual (msg ["event" ], "python test event" )
189+ self .assertTrue (isinstance (msg ["timestamp" ], str ))
190+ self .assertIsNone (msg .get ("uuid" ))
191+ self .assertEqual (msg ["distinct_id" ], "distinct_id" )
192+ self .assertEqual (msg ["properties" ]["$lib" ], "posthog-python" )
193+ self .assertEqual (msg ["properties" ]["$lib_version" ], VERSION )
194+ self .assertEqual (msg ["properties" ]["$feature/beta-feature-local" ], "third-variant" )
195+ self .assertEqual (msg ["properties" ]["$feature/false-flag" ], False )
196+ self .assertEqual (msg ["properties" ]["$active_feature_flags" ], ["beta-feature-local" ])
197+ assert "$feature/beta-feature" not in msg ["properties" ]
198+
199+ self .assertEqual (patch_decide .call_count , 0 )
200+
201+ # test that flags are not evaluated without local evaluation
202+ client .feature_flags = []
203+ success , msg = client .capture ("distinct_id" , "python test event" )
204+ client .flush ()
205+ self .assertTrue (success )
206+ self .assertFalse (self .failed )
207+ assert "$feature/beta-feature" not in msg ["properties" ]
208+ assert "$feature/beta-feature-local" not in msg ["properties" ]
209+ assert "$feature/false-flag" not in msg ["properties" ]
210+ assert "$active_feature_flags" not in msg ["properties" ]
211+
108212 @mock .patch ("posthog.client.decide" )
109213 def test_get_active_feature_flags (self , patch_decide ):
110214 patch_decide .return_value = {
@@ -620,7 +724,7 @@ def test_disable_geoip_default_on_decide(self, patch_decide):
620724 timeout = 10 ,
621725 distinct_id = "some_id" ,
622726 groups = {},
623- person_properties = {},
727+ person_properties = {"$current_distinct_id" : "some_id" },
624728 group_properties = {},
625729 disable_geoip = True ,
626730 )
@@ -632,7 +736,7 @@ def test_disable_geoip_default_on_decide(self, patch_decide):
632736 timeout = 10 ,
633737 distinct_id = "feature_enabled_distinct_id" ,
634738 groups = {},
635- person_properties = {},
739+ person_properties = {"$current_distinct_id" : "feature_enabled_distinct_id" },
636740 group_properties = {},
637741 disable_geoip = True ,
638742 )
@@ -644,7 +748,7 @@ def test_disable_geoip_default_on_decide(self, patch_decide):
644748 timeout = 10 ,
645749 distinct_id = "all_flags_payloads_id" ,
646750 groups = {},
647- person_properties = {},
751+ person_properties = {"$current_distinct_id" : "all_flags_payloads_id" },
648752 group_properties = {},
649753 disable_geoip = False ,
650754 )
@@ -660,3 +764,70 @@ def raise_effect():
660764 client .feature_flags = [{"key" : "example" , "is_simple_flag" : False }]
661765
662766 self .assertFalse (client .feature_enabled ("example" , "distinct_id" ))
767+
768+ @mock .patch ("posthog.client.decide" )
769+ def test_default_properties_get_added_properly (self , patch_decide ):
770+ patch_decide .return_value = {
771+ "featureFlags" : {"beta-feature" : "random-variant" , "alpha-feature" : True , "off-feature" : False }
772+ }
773+ client = Client (FAKE_TEST_API_KEY , on_error = self .set_fail , disable_geoip = False )
774+ client .get_feature_flag (
775+ "random_key" ,
776+ "some_id" ,
777+ groups = {"company" : "id:5" , "instance" : "app.posthog.com" },
778+ person_properties = {"x1" : "y1" },
779+ group_properties = {"company" : {"x" : "y" }},
780+ )
781+ patch_decide .assert_called_with (
782+ "random_key" ,
783+ None ,
784+ timeout = 10 ,
785+ distinct_id = "some_id" ,
786+ groups = {"company" : "id:5" , "instance" : "app.posthog.com" },
787+ person_properties = {"$current_distinct_id" : "some_id" , "x1" : "y1" },
788+ group_properties = {
789+ "company" : {"$group_key" : "id:5" , "x" : "y" },
790+ "instance" : {"$group_key" : "app.posthog.com" },
791+ },
792+ disable_geoip = False ,
793+ )
794+
795+ patch_decide .reset_mock ()
796+ client .get_feature_flag (
797+ "random_key" ,
798+ "some_id" ,
799+ groups = {"company" : "id:5" , "instance" : "app.posthog.com" },
800+ person_properties = {"$current_distinct_id" : "override" },
801+ group_properties = {
802+ "company" : {
803+ "$group_key" : "group_override" ,
804+ }
805+ },
806+ )
807+ patch_decide .assert_called_with (
808+ "random_key" ,
809+ None ,
810+ timeout = 10 ,
811+ distinct_id = "some_id" ,
812+ groups = {"company" : "id:5" , "instance" : "app.posthog.com" },
813+ person_properties = {"$current_distinct_id" : "override" },
814+ group_properties = {
815+ "company" : {"$group_key" : "group_override" },
816+ "instance" : {"$group_key" : "app.posthog.com" },
817+ },
818+ disable_geoip = False ,
819+ )
820+
821+ patch_decide .reset_mock ()
822+ # test nones
823+ client .get_all_flags_and_payloads ("some_id" , groups = {}, person_properties = None , group_properties = None )
824+ patch_decide .assert_called_with (
825+ "random_key" ,
826+ None ,
827+ timeout = 10 ,
828+ distinct_id = "some_id" ,
829+ groups = {},
830+ person_properties = {"$current_distinct_id" : "some_id" },
831+ group_properties = {},
832+ disable_geoip = False ,
833+ )
0 commit comments