@@ -319,6 +319,112 @@ def test_identity_flags_are_used_if_targeting_key_provided(
319319 )
320320
321321
322+ def test_identity_flags_are_used_with_flat_attributes (
323+ mock_flagsmith_client : MagicMock ,
324+ ) -> None :
325+ # Given
326+ key = "key"
327+ targeting_key = "targeting_key"
328+ traits = {"foo" : "bar" , "age" : 25 }
329+ value = "foo"
330+ default_value = "default"
331+
332+ provider = FlagsmithProvider (mock_flagsmith_client )
333+
334+ mock_flagsmith_client .get_environment_flags .side_effect = NotImplementedError ()
335+ mock_flagsmith_client .get_identity_flags .return_value = Flags (
336+ {key : Flag (feature_id = 1 , feature_name = key , enabled = True , value = value )}
337+ )
338+
339+ # When
340+ result = provider .resolve_string_details (
341+ flag_key = key ,
342+ default_value = default_value ,
343+ evaluation_context = EvaluationContext (
344+ targeting_key = targeting_key , attributes = traits
345+ ),
346+ )
347+
348+ # Then
349+ assert result .value == value
350+ assert result .error_code is None
351+ assert result .reason is None
352+
353+ mock_flagsmith_client .get_identity_flags .assert_called_once_with (
354+ identifier = targeting_key , traits = traits
355+ )
356+
357+
358+ def test_identity_flags_flat_attributes_and_nested_traits_are_merged (
359+ mock_flagsmith_client : MagicMock ,
360+ ) -> None :
361+ # Given
362+ key = "key"
363+ targeting_key = "targeting_key"
364+ value = "foo"
365+ default_value = "default"
366+
367+ provider = FlagsmithProvider (mock_flagsmith_client )
368+
369+ mock_flagsmith_client .get_environment_flags .side_effect = NotImplementedError ()
370+ mock_flagsmith_client .get_identity_flags .return_value = Flags (
371+ {key : Flag (feature_id = 1 , feature_name = key , enabled = True , value = value )}
372+ )
373+
374+ # When
375+ result = provider .resolve_string_details (
376+ flag_key = key ,
377+ default_value = default_value ,
378+ evaluation_context = EvaluationContext (
379+ targeting_key = targeting_key ,
380+ attributes = {"flat_trait" : "flat_value" , "traits" : {"nested_trait" : "nested_value" }},
381+ ),
382+ )
383+
384+ # Then
385+ assert result .value == value
386+ assert result .error_code is None
387+ assert result .reason is None
388+
389+ mock_flagsmith_client .get_identity_flags .assert_called_once_with (
390+ identifier = targeting_key ,
391+ traits = {"flat_trait" : "flat_value" , "nested_trait" : "nested_value" },
392+ )
393+
394+
395+ def test_identity_flags_nested_traits_take_precedence_over_flat_attributes (
396+ mock_flagsmith_client : MagicMock ,
397+ ) -> None :
398+ # Given
399+ key = "key"
400+ targeting_key = "targeting_key"
401+ value = "foo"
402+ default_value = "default"
403+
404+ provider = FlagsmithProvider (mock_flagsmith_client )
405+
406+ mock_flagsmith_client .get_environment_flags .side_effect = NotImplementedError ()
407+ mock_flagsmith_client .get_identity_flags .return_value = Flags (
408+ {key : Flag (feature_id = 1 , feature_name = key , enabled = True , value = value )}
409+ )
410+
411+ # When
412+ provider .resolve_string_details (
413+ flag_key = key ,
414+ default_value = default_value ,
415+ evaluation_context = EvaluationContext (
416+ targeting_key = targeting_key ,
417+ attributes = {"shared_key" : "flat_value" , "traits" : {"shared_key" : "nested_value" }},
418+ ),
419+ )
420+
421+ # Then
422+ mock_flagsmith_client .get_identity_flags .assert_called_once_with (
423+ identifier = targeting_key ,
424+ traits = {"shared_key" : "nested_value" },
425+ )
426+
427+
322428def test_resolve_boolean_details_uses_enabled_when_use_boolean_config_value_is_false (
323429 mock_flagsmith_client : MagicMock ,
324430) -> None :
0 commit comments