Skip to content

Commit 85438a7

Browse files
committed
update tests for provider
1 parent d5ae2c9 commit 85438a7

File tree

5 files changed

+126
-14
lines changed

5 files changed

+126
-14
lines changed

devcycle_python_sdk/local_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ def variable(self, user: DevCycleUser, key: str, default_value: Any) -> Variable
135135
try:
136136
self.event_queue_manager.queue_aggregate_event(
137137
event=DevCycleEvent(
138-
type=EventType.AggVariableDefaulted, target=key, value=1, metaData={"evalReason": EvalReasons.DEFAULT}
138+
type=EventType.AggVariableDefaulted,
139+
target=key,
140+
value=1,
141+
metaData={"evalReason": EvalReasons.DEFAULT},
139142
),
140143
bucketed_config=None,
141144
)

devcycle_python_sdk/models/variable.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,19 @@ def create_default_variable(
8585
isDefaulted=True,
8686
eval=eval_reason,
8787
)
88+
89+
def get_flag_meta_data(self) -> dict:
90+
"""
91+
Returns metadata dictionary for OpenFeature flag resolution.
92+
93+
Returns:
94+
dict: Dictionary containing evalReasonDetails and evalReasonTargetId
95+
if they exist, empty dict otherwise.
96+
"""
97+
meta_data = {}
98+
if self.eval:
99+
if self.eval.details:
100+
meta_data["evalReasonDetails"] = self.eval.details
101+
if self.eval.target_id:
102+
meta_data["evalReasonTargetId"] = self.eval.target_id
103+
return meta_data

devcycle_python_sdk/open_feature_provider/provider.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,10 @@ def _resolve(
8888
else:
8989
reason = Reason.TARGETING_MATCH
9090

91-
# Build flag metadata if eval details exist
92-
flag_metadata = {}
93-
if variable.eval:
94-
if variable.eval.details:
95-
flag_metadata["evalReasonDetails"] = variable.eval.details
96-
if variable.eval.target_id:
97-
flag_metadata["evalReasonTargetId"] = (
98-
variable.eval.target_id
99-
)
100-
10191
return FlagResolutionDetails(
10292
value=variable.value,
10393
reason=reason,
104-
flag_metadata=flag_metadata if flag_metadata else None,
94+
flag_metadata=variable.get_flag_meta_data(),
10595
)
10696
except ValueError as e:
10797
# occurs if the key or default value is None

test/openfeature_test/test_provider.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
)
1313

1414
from devcycle_python_sdk.models.variable import Variable, TypeEnum
15+
from devcycle_python_sdk.models.eval_reason import (
16+
EvalReason,
17+
EvalReasons,
18+
DefaultReasonDetails,
19+
)
1520

1621
from devcycle_python_sdk.open_feature_provider.provider import (
1722
DevCycleProvider,
@@ -69,14 +74,19 @@ def test_resolve_details_client_returns_none(self):
6974

7075
def test_resolve_details_client_returns_default_variable(self):
7176
self.client.variable.return_value = Variable.create_default_variable(
72-
key="test-flag", default_value=False
77+
key="test-flag",
78+
default_value=False,
79+
default_reason_detail=DefaultReasonDetails.USER_NOT_TARGETED,
7380
)
7481
context = EvaluationContext(targeting_key="user-1234")
7582
details = self.provider._resolve("test-flag", False, context)
7683

7784
self.assertIsNotNone(details)
7885
self.assertEqual(details.value, False)
7986
self.assertEqual(details.reason, Reason.DEFAULT)
87+
self.assertEqual(
88+
details.flag_metadata["evalReasonDetails"], "User Not Targeted"
89+
)
8090

8191
def test_resolve_boolean_details(self):
8292
key = "test-flag"
@@ -90,6 +100,9 @@ def test_resolve_boolean_details(self):
90100
type=TypeEnum.BOOLEAN,
91101
isDefaulted=False,
92102
defaultValue=False,
103+
eval=EvalReason(
104+
reason="TARGETING_MATCH", details="All Users", target_id="targetId"
105+
),
93106
)
94107

95108
context = EvaluationContext(targeting_key="user-1234")
@@ -98,6 +111,9 @@ def test_resolve_boolean_details(self):
98111
self.assertIsNotNone(details)
99112
self.assertEqual(details.value, variable_value)
100113
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
114+
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
115+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
116+
self.assertEqual(details.flag_metadata["evalReasonTargetId"], "targetId")
101117

102118
def test_resolve_string_details(self):
103119
key = "test-flag"
@@ -111,6 +127,9 @@ def test_resolve_string_details(self):
111127
type=TypeEnum.STRING,
112128
isDefaulted=False,
113129
defaultValue=False,
130+
eval=EvalReason(
131+
reason="TARGETING_MATCH", details="All Users", target_id="targetId"
132+
),
114133
)
115134

116135
context = EvaluationContext(targeting_key="user-1234")
@@ -120,6 +139,8 @@ def test_resolve_string_details(self):
120139
self.assertEqual(details.value, variable_value)
121140
self.assertIsInstance(details.value, str)
122141
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
142+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
143+
self.assertEqual(details.flag_metadata["evalReasonTargetId"], "targetId")
123144

124145
def test_resolve_integer_details(self):
125146
key = "test-flag"
@@ -133,6 +154,9 @@ def test_resolve_integer_details(self):
133154
type=TypeEnum.STRING,
134155
isDefaulted=False,
135156
defaultValue=False,
157+
eval=EvalReason(
158+
reason="TARGETING_MATCH", details="All Users", target_id="targetId"
159+
),
136160
)
137161

138162
context = EvaluationContext(targeting_key="user-1234")
@@ -142,6 +166,8 @@ def test_resolve_integer_details(self):
142166
self.assertIsInstance(details.value, int)
143167
self.assertEqual(details.value, variable_value)
144168
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
169+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
170+
self.assertEqual(details.flag_metadata["evalReasonTargetId"], "targetId")
145171

146172
def test_resolve_float_details(self):
147173
key = "test-flag"
@@ -155,6 +181,7 @@ def test_resolve_float_details(self):
155181
type=TypeEnum.STRING,
156182
isDefaulted=False,
157183
defaultValue=False,
184+
eval=EvalReason(reason="SPLIT", details="Rollout", target_id="targetId"),
158185
)
159186

160187
context = EvaluationContext(targeting_key="user-1234")
@@ -163,7 +190,9 @@ def test_resolve_float_details(self):
163190
self.assertIsNotNone(details)
164191
self.assertIsInstance(details.value, float)
165192
self.assertEqual(details.value, variable_value)
166-
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
193+
self.assertEqual(details.reason, Reason.SPLIT)
194+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "Rollout")
195+
self.assertEqual(details.flag_metadata["evalReasonTargetId"], "targetId")
167196

168197
def test_resolve_object_details_verify_default_value(self):
169198
key = "test-flag"
@@ -204,6 +233,9 @@ def test_resolve_object_details(self):
204233
type=TypeEnum.STRING,
205234
isDefaulted=False,
206235
defaultValue=False,
236+
eval=EvalReason(
237+
reason="TARGETING_MATCH", details="Rollout", target_id="targetId"
238+
),
207239
)
208240

209241
context = EvaluationContext(targeting_key="user-1234")
@@ -213,6 +245,52 @@ def test_resolve_object_details(self):
213245
self.assertIsInstance(details.value, dict)
214246
self.assertDictEqual(details.value, variable_value)
215247
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
248+
self.assertIsNotNone(details.flag_metadata)
249+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "Rollout")
250+
self.assertEqual(details.flag_metadata["evalReasonTargetId"], "targetId")
251+
252+
def test_resolve_string_details_null_eval(self):
253+
key = "test-flag"
254+
variable_value = "some string"
255+
default_value = "default string"
256+
257+
self.client.variable.return_value = Variable(
258+
_id=None,
259+
value=variable_value,
260+
key=key,
261+
type=TypeEnum.STRING,
262+
isDefaulted=False,
263+
defaultValue=False,
264+
)
265+
266+
context = EvaluationContext(targeting_key="user-1234")
267+
details = self.provider.resolve_string_details(key, default_value, context)
268+
269+
self.assertIsNotNone(details)
270+
self.assertEqual(details.value, variable_value)
271+
self.assertIsInstance(details.value, str)
272+
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
273+
274+
def test_default_string_details_null_eval(self):
275+
key = "test-flag"
276+
default_value = "default string"
277+
278+
self.client.variable.return_value = Variable(
279+
_id=None,
280+
value=default_value,
281+
key=key,
282+
type=TypeEnum.STRING,
283+
isDefaulted=True,
284+
defaultValue=False,
285+
)
286+
287+
context = EvaluationContext(targeting_key="user-1234")
288+
details = self.provider.resolve_string_details(key, default_value, context)
289+
290+
self.assertIsNotNone(details)
291+
self.assertEqual(details.value, default_value)
292+
self.assertIsInstance(details.value, str)
293+
self.assertEqual(details.reason, Reason.DEFAULT)
216294

217295

218296
if __name__ == "__main__":

test/openfeature_test/test_provider_local_sdk.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ def test_resolve_boolean_details(self):
6666
self.assertIsNotNone(details)
6767
self.assertEqual(details.value, expected_value)
6868
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
69+
self.assertIsNotNone(details.flag_metadata)
70+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
71+
self.assertEqual(
72+
details.flag_metadata["evalReasonTargetId"], "63125321d31c601f992288bc"
73+
)
6974

7075
@responses.activate
7176
def test_resolve_integer_details(self):
@@ -82,6 +87,11 @@ def test_resolve_integer_details(self):
8287
self.assertIsNotNone(details)
8388
self.assertEqual(details.value, expected_value)
8489
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
90+
self.assertIsNotNone(details.flag_metadata)
91+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
92+
self.assertEqual(
93+
details.flag_metadata["evalReasonTargetId"], "63125321d31c601f992288bc"
94+
)
8595

8696
@responses.activate
8797
def test_resolve_float_details(self):
@@ -98,6 +108,11 @@ def test_resolve_float_details(self):
98108
self.assertIsNotNone(details)
99109
self.assertEqual(details.value, expected_value)
100110
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
111+
self.assertIsNotNone(details.flag_metadata)
112+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
113+
self.assertEqual(
114+
details.flag_metadata["evalReasonTargetId"], "63125321d31c601f992288bc"
115+
)
101116

102117
@responses.activate
103118
def test_resolve_string_details(self):
@@ -114,6 +129,11 @@ def test_resolve_string_details(self):
114129
self.assertIsNotNone(details)
115130
self.assertEqual(details.value, expected_value)
116131
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
132+
self.assertIsNotNone(details.flag_metadata)
133+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
134+
self.assertEqual(
135+
details.flag_metadata["evalReasonTargetId"], "63125321d31c601f992288bc"
136+
)
117137

118138
@responses.activate
119139
def test_resolve_object_details(self):
@@ -134,3 +154,8 @@ def test_resolve_object_details(self):
134154
self.assertIsNotNone(details)
135155
self.assertEqual(details.value, expected_value)
136156
self.assertEqual(details.reason, Reason.TARGETING_MATCH)
157+
self.assertIsNotNone(details.flag_metadata)
158+
self.assertEqual(details.flag_metadata["evalReasonDetails"], "All Users")
159+
self.assertEqual(
160+
details.flag_metadata["evalReasonTargetId"], "63125321d31c601f992288bc"
161+
)

0 commit comments

Comments
 (0)