1
- import pytest
2
1
from unittest .mock import Mock , create_autospec
2
+
3
+ import pytest
4
+
5
+ from openfeature .contrib .provider .flagd .config import Config
3
6
from openfeature .contrib .provider .flagd .resolvers .in_process import InProcessResolver
4
- from openfeature .evaluation_context import EvaluationContext
5
- from openfeature .exception import FlagNotFoundError
6
7
from openfeature .contrib .provider .flagd .resolvers .process .flags import Flag , FlagStore
7
- from openfeature .contrib . provider . flagd . config import Config
8
+ from openfeature .evaluation_context import EvaluationContext
8
9
from openfeature .exception import FlagNotFoundError , ParseError
9
10
11
+
10
12
@pytest .fixture
11
13
def config ():
12
14
return create_autospec (Config )
13
15
16
+
14
17
@pytest .fixture
15
18
def flag_store ():
16
19
return create_autospec (FlagStore )
17
20
21
+
18
22
@pytest .fixture
19
23
def targeting ():
20
24
return {
@@ -24,33 +28,37 @@ def targeting():
24
28
None ,
25
29
]
26
30
}
27
-
31
+
32
+
28
33
@pytest .fixture
29
34
def flag (targeting ):
30
35
return Flag (
31
36
key = "flag" ,
32
37
state = "ENABLED" ,
33
38
variants = {"default_variant" : False , "target_variant" : True },
34
39
default_variant = "default_variant" ,
35
- targeting = targeting
40
+ targeting = targeting ,
36
41
)
37
42
43
+
38
44
@pytest .fixture
39
45
def context ():
40
46
return EvaluationContext (targeting_key = "target_variant" )
41
47
48
+
42
49
@pytest .fixture
43
50
def resolver (config ):
44
- config .offline_flag_source_path = ' flag.json'
51
+ config .offline_flag_source_path = " flag.json"
45
52
config .deadline_ms = 100
46
53
return InProcessResolver (
47
54
config = config ,
48
55
emit_provider_ready = Mock (),
49
56
emit_provider_error = Mock (),
50
57
emit_provider_stale = Mock (),
51
- emit_provider_configuration_changed = Mock ()
58
+ emit_provider_configuration_changed = Mock (),
52
59
)
53
60
61
+
54
62
@pytest .fixture
55
63
def flag ():
56
64
return Flag (
@@ -61,6 +69,7 @@ def flag():
61
69
targeting = None ,
62
70
)
63
71
72
+
64
73
def targeting ():
65
74
return {
66
75
"if" : [
@@ -70,14 +79,17 @@ def targeting():
70
79
]
71
80
}
72
81
82
+
73
83
def context (targeting_key ):
74
84
return EvaluationContext (targeting_key = targeting_key )
75
85
86
+
76
87
def test_resolve_boolean_details_flag_not_found (resolver ):
77
88
resolver .flag_store .get_flag = Mock (return_value = None )
78
89
with pytest .raises (FlagNotFoundError ):
79
90
resolver .resolve_boolean_details ("nonexistent_flag" , False )
80
91
92
+
81
93
def test_resolve_boolean_details_disabled_flag (flag , resolver ):
82
94
flag .state = "DISABLED"
83
95
resolver .flag_store .get_flag = Mock (return_value = flag )
@@ -88,65 +100,100 @@ def test_resolve_boolean_details_disabled_flag(flag, resolver):
88
100
assert result .variant == None
89
101
assert result .value == False
90
102
103
+
91
104
def test_resolve_boolean_details_invalid_variant (resolver , flag ):
92
- flag .targeting = {
93
- "var" : ["targetingKey" , "invalid_variant" ]
94
- }
105
+ flag .targeting = {"var" : ["targetingKey" , "invalid_variant" ]}
95
106
96
107
resolver .flag_store .get_flag = Mock (return_value = flag )
97
108
98
109
with pytest .raises (ParseError ):
99
110
resolver .resolve_boolean_details ("flag" , False )
100
111
112
+
101
113
@pytest .mark .parametrize (
102
- "variants, targeting,"
103
- "context, method, default_value,"
104
- "expected_reason, expected_variant, expected_value," ,
114
+ "variants, targeting,"
115
+ "context, method, default_value,"
116
+ "expected_reason, expected_variant, expected_value," ,
105
117
[
106
118
(
107
- {"default_variant" : False , "target_variant" : True }, None ,
108
- None , "resolve_boolean_details" , False ,
109
- "STATIC" , "default_variant" , False ,
110
- ) ,
111
- (
112
- { "default_variant" : False , "target_variant" : True }, targeting () ,
113
- context ( "no_target_variant" ), "resolve_boolean_details" , False ,
114
- "DEFAULT" , "default_variant" , False ,
119
+ {"default_variant" : False , "target_variant" : True },
120
+ None ,
121
+ None ,
122
+ "resolve_boolean_details" ,
123
+ False ,
124
+ "STATIC" ,
125
+ "default_variant" ,
126
+ False ,
115
127
),
116
128
(
117
- {"default_variant" : False , "target_variant" : True }, targeting (),
118
- context ("target_variant" ), "resolve_boolean_details" , False ,
119
- "TARGETING_MATCH" , "target_variant" , True ,
129
+ {"default_variant" : False , "target_variant" : True },
130
+ targeting (),
131
+ context ("no_target_variant" ),
132
+ "resolve_boolean_details" ,
133
+ False ,
134
+ "DEFAULT" ,
135
+ "default_variant" ,
136
+ False ,
120
137
),
121
138
(
122
- {"default_variant" : "default" , "target_variant" : "target" }, targeting (),
123
- context ("target_variant" ), "resolve_string_details" , "placeholder" ,
124
- "TARGETING_MATCH" , "target_variant" , "target" ,
139
+ {"default_variant" : False , "target_variant" : True },
140
+ targeting (),
141
+ context ("target_variant" ),
142
+ "resolve_boolean_details" ,
143
+ False ,
144
+ "TARGETING_MATCH" ,
145
+ "target_variant" ,
146
+ True ,
125
147
),
126
148
(
127
- {"default_variant" : 1.0 , "target_variant" : 2.0 }, targeting (),
128
- context ("target_variant" ), "resolve_float_details" , 0.0 ,
129
- "TARGETING_MATCH" , "target_variant" , 2.0 ,
149
+ {"default_variant" : "default" , "target_variant" : "target" },
150
+ targeting (),
151
+ context ("target_variant" ),
152
+ "resolve_string_details" ,
153
+ "placeholder" ,
154
+ "TARGETING_MATCH" ,
155
+ "target_variant" ,
156
+ "target" ,
130
157
),
131
158
(
132
- {"default_variant" : True , "target_variant" : False }, targeting (),
133
- context ("target_variant" ), "resolve_boolean_details" , True ,
134
- "TARGETING_MATCH" , "target_variant" , False ,
159
+ {"default_variant" : 1.0 , "target_variant" : 2.0 },
160
+ targeting (),
161
+ context ("target_variant" ),
162
+ "resolve_float_details" ,
163
+ 0.0 ,
164
+ "TARGETING_MATCH" ,
165
+ "target_variant" ,
166
+ 2.0 ,
135
167
),
136
168
(
137
- {"default_variant" : 10 , "target_variant" : 0 }, targeting (),
138
- context ("target_variant" ), "resolve_integer_details" , 1 ,
139
- "TARGETING_MATCH" , "target_variant" , 0 ,
169
+ {"default_variant" : True , "target_variant" : False },
170
+ targeting (),
171
+ context ("target_variant" ),
172
+ "resolve_boolean_details" ,
173
+ True ,
174
+ "TARGETING_MATCH" ,
175
+ "target_variant" ,
176
+ False ,
140
177
),
141
178
(
142
- {"default_variant" : {}, "target_variant" : {}}, targeting (),
143
- context ("target_variant" ), "resolve_object_details" , {},
144
- "TARGETING_MATCH" , "target_variant" , {},
179
+ {"default_variant" : 10 , "target_variant" : 0 },
180
+ targeting (),
181
+ context ("target_variant" ),
182
+ "resolve_integer_details" ,
183
+ 1 ,
184
+ "TARGETING_MATCH" ,
185
+ "target_variant" ,
186
+ 0 ,
145
187
),
146
188
(
147
- {"default_variant" : None , "target_variant" : None }, targeting (),
148
- context ("target_variant" ), "resolve_object_details" , {},
149
- "TARGETING_MATCH" , "target_variant" , None ,
189
+ {"default_variant" : {}, "target_variant" : {}},
190
+ targeting (),
191
+ context ("target_variant" ),
192
+ "resolve_object_details" ,
193
+ {},
194
+ "TARGETING_MATCH" ,
195
+ "target_variant" ,
196
+ {},
150
197
),
151
198
],
152
199
ids = [
@@ -158,15 +205,20 @@ def test_resolve_boolean_details_invalid_variant(resolver, flag):
158
205
"boolean_falsy_target" ,
159
206
"integer_falsy_target" ,
160
207
"object_falsy_target" ,
161
- "none_target_value" ,
162
208
],
163
209
)
164
210
def test_resolver_details (
165
- resolver , flag ,
166
- variants , targeting ,
167
- context , method , default_value ,
168
- expected_reason , expected_variant , expected_value
169
- ):
211
+ resolver ,
212
+ flag ,
213
+ variants ,
214
+ targeting ,
215
+ context ,
216
+ method ,
217
+ default_value ,
218
+ expected_reason ,
219
+ expected_variant ,
220
+ expected_value ,
221
+ ):
170
222
flag .variants = variants
171
223
flag .targeting = targeting
172
224
resolver .flag_store .get_flag = Mock (return_value = flag )
0 commit comments