@@ -319,6 +319,118 @@ 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 = {
381+ "flat_trait" : "flat_value" ,
382+ "traits" : {"nested_trait" : "nested_value" },
383+ },
384+ ),
385+ )
386+
387+ # Then
388+ assert result .value == value
389+ assert result .error_code is None
390+ assert result .reason is None
391+
392+ mock_flagsmith_client .get_identity_flags .assert_called_once_with (
393+ identifier = targeting_key ,
394+ traits = {"flat_trait" : "flat_value" , "nested_trait" : "nested_value" },
395+ )
396+
397+
398+ def test_identity_flags_nested_traits_take_precedence_over_flat_attributes (
399+ mock_flagsmith_client : MagicMock ,
400+ ) -> None :
401+ # Given
402+ key = "key"
403+ targeting_key = "targeting_key"
404+ value = "foo"
405+ default_value = "default"
406+
407+ provider = FlagsmithProvider (mock_flagsmith_client )
408+
409+ mock_flagsmith_client .get_environment_flags .side_effect = NotImplementedError ()
410+ mock_flagsmith_client .get_identity_flags .return_value = Flags (
411+ {key : Flag (feature_id = 1 , feature_name = key , enabled = True , value = value )}
412+ )
413+
414+ # When
415+ provider .resolve_string_details (
416+ flag_key = key ,
417+ default_value = default_value ,
418+ evaluation_context = EvaluationContext (
419+ targeting_key = targeting_key ,
420+ attributes = {
421+ "shared_key" : "flat_value" ,
422+ "traits" : {"shared_key" : "nested_value" },
423+ },
424+ ),
425+ )
426+
427+ # Then
428+ mock_flagsmith_client .get_identity_flags .assert_called_once_with (
429+ identifier = targeting_key ,
430+ traits = {"shared_key" : "nested_value" },
431+ )
432+
433+
322434def test_resolve_boolean_details_uses_enabled_when_use_boolean_config_value_is_false (
323435 mock_flagsmith_client : MagicMock ,
324436) -> None :
0 commit comments