from numbers import Number import pytest from openfeature.exception import ErrorCode from openfeature.flag_evaluation import FlagResolutionDetails, Reason from openfeature.provider.in_memory_provider import InMemoryFlag, InMemoryProvider def test_should_return_in_memory_provider_metadata(): # Given provider = InMemoryProvider({}) # When metadata = provider.get_metadata() # Then assert metadata is not None assert metadata.name == "In-Memory Provider" @pytest.mark.asyncio async def test_should_handle_unknown_flags_correctly(): # Given provider = InMemoryProvider({}) # When flag_sync = provider.resolve_boolean_details(flag_key="Key", default_value=True) flag_async = await provider.resolve_boolean_details_async( flag_key="Key", default_value=True ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value is True assert flag.reason == Reason.ERROR assert flag.error_code == ErrorCode.FLAG_NOT_FOUND assert flag.error_message == "Flag 'Key' not found" @pytest.mark.asyncio async def test_calls_context_evaluator_if_present(): # Given def context_evaluator(flag: InMemoryFlag, evaluation_context: dict): return FlagResolutionDetails( value=False, reason=Reason.TARGETING_MATCH, ) provider = InMemoryProvider( { "Key": InMemoryFlag( "true", {"true": True, "false": False}, context_evaluator=context_evaluator, ) } ) # When flag_sync = provider.resolve_boolean_details(flag_key="Key", default_value=False) flag_async = await provider.resolve_boolean_details_async( flag_key="Key", default_value=False ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value is False assert isinstance(flag.value, bool) assert flag.reason == Reason.TARGETING_MATCH @pytest.mark.asyncio async def test_should_resolve_boolean_flag_from_in_memory(): # Given provider = InMemoryProvider( {"Key": InMemoryFlag("true", {"true": True, "false": False})} ) # When flag_sync = provider.resolve_boolean_details(flag_key="Key", default_value=False) flag_async = await provider.resolve_boolean_details_async( flag_key="Key", default_value=False ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value is True assert isinstance(flag.value, bool) assert flag.variant == "true" @pytest.mark.asyncio async def test_should_resolve_integer_flag_from_in_memory(): # Given provider = InMemoryProvider( {"Key": InMemoryFlag("hundred", {"zero": 0, "hundred": 100})} ) # When flag_sync = provider.resolve_integer_details(flag_key="Key", default_value=0) flag_async = await provider.resolve_integer_details_async( flag_key="Key", default_value=0 ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value == 100 assert isinstance(flag.value, Number) assert flag.variant == "hundred" @pytest.mark.asyncio async def test_should_resolve_float_flag_from_in_memory(): # Given provider = InMemoryProvider( {"Key": InMemoryFlag("ten", {"zero": 0.0, "ten": 10.23})} ) # When flag_sync = provider.resolve_float_details(flag_key="Key", default_value=0.0) flag_async = await provider.resolve_float_details_async( flag_key="Key", default_value=0.0 ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value == 10.23 assert isinstance(flag.value, Number) assert flag.variant == "ten" @pytest.mark.asyncio async def test_should_resolve_string_flag_from_in_memory(): # Given provider = InMemoryProvider( { "Key": InMemoryFlag( "stringVariant", {"defaultVariant": "Default", "stringVariant": "String"}, ) } ) # When flag_sync = provider.resolve_string_details(flag_key="Key", default_value="Default") flag_async = await provider.resolve_string_details_async( flag_key="Key", default_value="Default" ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value == "String" assert isinstance(flag.value, str) assert flag.variant == "stringVariant" @pytest.mark.asyncio async def test_should_resolve_list_flag_from_in_memory(): # Given provider = InMemoryProvider( {"Key": InMemoryFlag("twoItems", {"empty": [], "twoItems": ["item1", "item2"]})} ) # When flag_sync = provider.resolve_object_details(flag_key="Key", default_value=[]) flag_async = await provider.resolve_object_details_async( flag_key="Key", default_value=[] ) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value == ["item1", "item2"] assert isinstance(flag.value, list) assert flag.variant == "twoItems" @pytest.mark.asyncio async def test_should_resolve_object_flag_from_in_memory(): # Given return_value = { "String": "string", "Number": 2, "Boolean": True, } provider = InMemoryProvider( {"Key": InMemoryFlag("obj", {"obj": return_value, "empty": {}})} ) # When flag_sync = provider.resolve_object_details(flag_key="Key", default_value={}) flag_async = provider.resolve_object_details(flag_key="Key", default_value={}) # Then assert flag_sync == flag_async for flag in [flag_sync, flag_async]: assert flag is not None assert flag.value == return_value assert isinstance(flag.value, dict) assert flag.variant == "obj"