@@ -42,6 +42,39 @@ def identifier_is(value: str) -> Condition:
4242 )
4343
4444
45+ def plan_is (value : str ) -> Condition :
46+ return Condition (
47+ id = uid (),
48+ attribute = "traits" ,
49+ operator = "=" ,
50+ trait = "/plan" ,
51+ target_type = "text" ,
52+ target_values = [value ],
53+ )
54+
55+
56+ def config_requiring (* conditions : Condition ) -> Config :
57+ return Config (
58+ id = CONFIG_ID ,
59+ key = "config-with-a-two-condition-rule" ,
60+ type = "string" ,
61+ variations = [],
62+ target = TargetingRules (
63+ default_value = "this-is-the-default" ,
64+ rules = [
65+ ConditionalRule (
66+ id = uid (),
67+ order = 0 ,
68+ target = "value" ,
69+ value = "Rule A Value" ,
70+ percentages = [],
71+ conditions = list (conditions ),
72+ )
73+ ],
74+ ),
75+ )
76+
77+
4578def test_evaluates_to_the_default_value_when_there_are_no_targeting_rules () -> None :
4679 config = Config (
4780 id = CONFIG_ID ,
@@ -251,7 +284,7 @@ def test_cycles_through_multiple_rules(self) -> None:
251284 assert evaluator .evaluate (config , ctx (id = "15" )).value == "Rule B Value"
252285 assert evaluator .evaluate (config , ctx (id = "20" )).value == "this-is-the-default"
253286
254- def test_falls_back_to_the_default_when_conditions_array_is_empty (self ) -> None :
287+ def test_a_rule_with_no_conditions_applies_to_every_context (self ) -> None :
255288 config = Config (
256289 id = CONFIG_ID ,
257290 key = "config-without-rules" ,
@@ -272,32 +305,38 @@ def test_falls_back_to_the_default_when_conditions_array_is_empty(self) -> None:
272305 ),
273306 )
274307
275- assert evaluator .evaluate (config , ctx (id = "10" )).value == "this-is-the-default"
308+ assert evaluator .evaluate (config , ctx (id = "10" )).value == "Rule A Value"
309+ assert evaluator .evaluate (config ).value == "Rule A Value"
276310
277- def test_matches_on_the_first_true_condition (self ) -> None :
278- config = Config (
279- id = CONFIG_ID ,
280- key = "config-without-rules" ,
281- type = "string" ,
282- variations = [],
283- target = TargetingRules (
284- default_value = "this-is-the-default" ,
285- rules = [
286- ConditionalRule (
287- id = uid (),
288- order = 0 ,
289- target = "value" ,
290- value = "Rule A Value" ,
291- percentages = [],
292- conditions = [identifier_is ("10" ), identifier_is ("20" )],
293- )
294- ],
295- ),
311+ def test_a_rule_with_several_conditions_matches_when_every_condition_matches (self ) -> None :
312+ config = config_requiring (identifier_is ("10" ), plan_is ("pro" ))
313+
314+ assert evaluator .evaluate (config , ctx (id = "10" , traits = {"plan" : "pro" })).value == "Rule A Value"
315+
316+ def test_a_rule_with_several_conditions_does_not_match_when_only_the_first_matches (self ) -> None :
317+ config = config_requiring (identifier_is ("10" ), plan_is ("pro" ))
318+
319+ assert (
320+ evaluator .evaluate (config , ctx (id = "10" , traits = {"plan" : "free" })).value == "this-is-the-default"
296321 )
297322
298- assert evaluator .evaluate (config , ctx (id = "10" )).value == "Rule A Value"
299- assert evaluator .evaluate (config , ctx (id = "20" )).value == "Rule A Value"
300- assert evaluator .evaluate (config , ctx (id = "30" )).value == "this-is-the-default"
323+ def test_a_rule_with_several_conditions_does_not_match_when_only_the_second_matches (self ) -> None :
324+ config = config_requiring (identifier_is ("10" ), plan_is ("pro" ))
325+
326+ assert evaluator .evaluate (config , ctx (id = "20" , traits = {"plan" : "pro" })).value == "this-is-the-default"
327+
328+ def test_a_rule_with_several_conditions_does_not_match_when_no_condition_matches (self ) -> None :
329+ config = config_requiring (identifier_is ("10" ), plan_is ("pro" ))
330+
331+ assert (
332+ evaluator .evaluate (config , ctx (id = "20" , traits = {"plan" : "free" })).value == "this-is-the-default"
333+ )
334+
335+ def test_a_rule_whose_conditions_cannot_all_hold_never_matches (self ) -> None :
336+ config = config_requiring (identifier_is ("10" ), identifier_is ("20" ))
337+
338+ assert evaluator .evaluate (config , ctx (id = "10" )).value == "this-is-the-default"
339+ assert evaluator .evaluate (config , ctx (id = "20" )).value == "this-is-the-default"
301340
302341 def test_falls_back_to_the_default_when_the_condition_matches_but_the_value_is_none (
303342 self ,
0 commit comments