""" Gap tests for settings_utils: _get_typed_value edge cases, get_bool_setting, get_settings_snapshot, extract_setting_value corner cases, and extract_bool_setting with non-bool inputs. These complement the existing test_settings_utils_typed_value.py and test_settings_utils_behavior.py by covering paths that those files miss. """ import pytest from local_deep_research.api.settings_utils import ( InMemorySettingsManager, extract_bool_setting, extract_setting_value, ) # --------------------------------------------------------------------------- # Fixture # --------------------------------------------------------------------------- @pytest.fixture def manager(): """Create an InMemorySettingsManager with defaults loaded.""" return InMemorySettingsManager() # --------------------------------------------------------------------------- # _get_typed_value — additional edge cases # --------------------------------------------------------------------------- class TestGetTypedValueTextarea: """textarea ui_element — should behave like text (str conversion).""" def test_string_passthrough(self, manager): result = manager._get_typed_value( {"ui_element": "textarea"}, "hello\nworld" ) assert result == "hello\nworld" def test_int_converted_to_string(self, manager): result = manager._get_typed_value({"ui_element": "textarea"}, 99) assert result == "99" assert isinstance(result, str) class TestGetTypedValueConversionEdgeCases: """Conversion failure and boundary cases not covered elsewhere.""" def test_none_returns_none_regardless_of_ui_element(self, manager): """None short-circuits before any type dispatch.""" for ui in ("text", "checkbox", "number", "select", "json", "textarea"): assert manager._get_typed_value({"ui_element": ui}, None) is None def test_number_with_empty_string(self, manager): """Empty string cannot be parsed as number; returns original value.""" result = manager._get_typed_value({"ui_element": "number"}, "") assert result == "" def test_range_with_negative_float(self, manager): result = manager._get_typed_value({"ui_element": "range"}, "-2.5") assert result == -2.5 def test_checkbox_with_none_value(self, manager): """None should be returned directly (short-circuit), not converted.""" result = manager._get_typed_value({"ui_element": "checkbox"}, None) assert result is None def test_json_with_string_json_object(self, manager): """A JSON string should be parsed into a dict.""" result = manager._get_typed_value({"ui_element": "json"}, '{"a": 1}') assert result == {"a": 1} def test_json_with_empty_string(self, manager): """Empty string for json ui_element — should pass through as-is.""" result = manager._get_typed_value({"ui_element": "json"}, "") # _parse_json_value returns empty strings as-is assert result == "" def test_multiselect_with_empty_list(self, manager): result = manager._get_typed_value({"ui_element": "multiselect"}, []) assert result == [] def test_multiselect_with_single_item_string(self, manager): """A plain string without commas should still be parsed.""" result = manager._get_typed_value({"ui_element": "multiselect"}, "solo") # _parse_multiselect with a non-bracketed, non-comma string # returns a single-element list assert isinstance(result, list) assert "solo" in result class TestGetTypedValueMissingUiElement: """When setting_data has no ui_element key at all.""" def test_defaults_to_text_converts_to_str(self, manager): """Missing ui_element defaults to 'text', so str() is applied.""" result = manager._get_typed_value({}, 42) assert result == "42" assert isinstance(result, str) # --------------------------------------------------------------------------- # get_bool_setting — InMemorySettingsManager method # --------------------------------------------------------------------------- class TestGetBoolSetting: """InMemorySettingsManager.get_bool_setting wraps get_setting + to_bool.""" def test_true_bool_value(self, manager): manager.create_or_update_setting( {"key": "test.gbool", "value": True, "ui_element": "checkbox"} ) assert manager.get_bool_setting("test.gbool") is True def test_false_bool_value(self, manager): manager.create_or_update_setting( {"key": "test.gbool", "value": False, "ui_element": "checkbox"} ) assert manager.get_bool_setting("test.gbool") is False def test_string_true(self, manager): manager.create_or_update_setting( {"key": "test.gbool", "value": "true", "ui_element": "checkbox"} ) assert manager.get_bool_setting("test.gbool") is True def test_string_on(self, manager): manager.create_or_update_setting( {"key": "test.gbool", "value": "on", "ui_element": "checkbox"} ) assert manager.get_bool_setting("test.gbool") is True def test_missing_key_returns_default_true(self, manager): assert manager.get_bool_setting("nonexistent.key", default=True) is True def test_missing_key_returns_default_false(self, manager): assert ( manager.get_bool_setting("nonexistent.key", default=False) is False ) def test_integer_1_is_true(self, manager): manager.create_or_update_setting( {"key": "test.gbool", "value": 1, "ui_element": "checkbox"} ) # parse_boolean treats any truthy value (including 1) as True assert manager.get_bool_setting("test.gbool") is True def test_integer_0_is_false(self, manager): manager.create_or_update_setting( {"key": "test.gbool", "value": 0, "ui_element": "checkbox"} ) assert manager.get_bool_setting("test.gbool") is False # --------------------------------------------------------------------------- # get_settings_snapshot — simplified key→value dict # --------------------------------------------------------------------------- class TestGetSettingsSnapshot: """InMemorySettingsManager.get_settings_snapshot returns flat key→value.""" def test_returns_dict(self, manager): snapshot = manager.get_settings_snapshot() assert isinstance(snapshot, dict) def test_values_are_extracted_from_setting_dicts(self, manager): """Each setting's 'value' field should be the snapshot value.""" manager.create_or_update_setting( {"key": "snap.test", "value": "hello", "ui_element": "text"} ) snapshot = manager.get_settings_snapshot() assert snapshot["snap.test"] == "hello" def test_non_dict_settings_passed_through(self, manager): """If a setting is not a dict (unlikely but possible), pass through.""" # Force a raw value into _settings manager._settings["raw.val"] = "plain_string" snapshot = manager.get_settings_snapshot() assert snapshot["raw.val"] == "plain_string" def test_snapshot_is_independent_copy(self, manager): """Modifying snapshot should not affect manager state.""" snapshot = manager.get_settings_snapshot() snapshot["injected"] = "bad" snapshot2 = manager.get_settings_snapshot() assert "injected" not in snapshot2 # --------------------------------------------------------------------------- # create_or_update_setting — edge cases # --------------------------------------------------------------------------- class TestCreateOrUpdateSettingEdgeCases: def test_non_dict_returns_none(self, manager): """Passing a non-dict returns None.""" assert manager.create_or_update_setting("not_a_dict") is None def test_dict_without_key_returns_none(self, manager): assert manager.create_or_update_setting({"value": 42}) is None def test_does_not_mutate_input_dict(self, manager): """The original dict should not be modified when value is typed.""" original = { "key": "test.nomut", "value": "42", "ui_element": "number", } original_value = original["value"] manager.create_or_update_setting(original) # Original dict's value should remain unchanged assert original["value"] == original_value def test_setting_without_value_key(self, manager): """A dict with 'key' but no 'value' should still be stored.""" result = manager.create_or_update_setting( {"key": "test.noval", "ui_element": "text"} ) assert result is not None assert "test.noval" in manager.get_all_settings() # --------------------------------------------------------------------------- # import_settings — type conversion path # --------------------------------------------------------------------------- class TestImportSettingsTypedValues: """import_settings applies _get_typed_value when value dicts are imported.""" def test_number_value_converted_on_import(self, manager): manager.import_settings( {"imp.num": {"value": "7", "ui_element": "number"}}, delete_extra=True, ) # The stored value should be int 7 (whole-number float → int) all_settings = manager.get_all_settings() assert all_settings["imp.num"]["value"] == 7 def test_checkbox_value_converted_on_import(self, manager): manager.import_settings( {"imp.bool": {"value": "true", "ui_element": "checkbox"}}, delete_extra=True, ) all_settings = manager.get_all_settings() assert all_settings["imp.bool"]["value"] is True def test_plain_value_stored_as_is(self, manager): """Non-dict values are stored without type conversion.""" manager.import_settings( {"imp.raw": "just_a_string"}, delete_extra=True, ) all_settings = manager.get_all_settings() assert all_settings["imp.raw"] == "just_a_string" # --------------------------------------------------------------------------- # extract_setting_value — additional corner cases # --------------------------------------------------------------------------- class TestExtractSettingValueEdgeCases: def test_dict_without_value_key_returns_whole_dict(self): """A dict that lacks 'value' is returned as-is (it's not a setting dict).""" settings = {"key": {"other_field": "data"}} result = extract_setting_value(settings, "key") assert result == {"other_field": "data"} def test_value_is_none_explicitly(self): """When value is explicitly None, it should be returned (not default).""" settings = {"key": {"value": None}} result = extract_setting_value(settings, "key", default="fallback") assert result is None def test_value_is_zero(self): """Falsy value 0 should be returned, not the default.""" settings = {"key": {"value": 0}} result = extract_setting_value(settings, "key", default=99) assert result == 0 def test_value_is_empty_string(self): """Falsy value '' should be returned, not the default.""" settings = {"key": {"value": ""}} result = extract_setting_value(settings, "key", default="fallback") assert result == "" def test_value_is_false(self): """Falsy value False should be returned, not the default.""" settings = {"key": {"value": False}} result = extract_setting_value(settings, "key", default=True) assert result is False def test_empty_snapshot(self): result = extract_setting_value({}, "any", default="d") assert result == "d" # --------------------------------------------------------------------------- # extract_bool_setting — additional edge cases # --------------------------------------------------------------------------- class TestExtractBoolSettingEdgeCases: def test_integer_1_is_true(self): settings = {"flag": {"value": 1}} assert extract_bool_setting(settings, "flag") is True def test_integer_0_is_false(self): settings = {"flag": {"value": 0}} assert extract_bool_setting(settings, "flag") is False def test_none_value_uses_default_true(self): settings = {"flag": {"value": None}} assert extract_bool_setting(settings, "flag", default=True) is True def test_none_value_uses_default_false(self): settings = {"flag": {"value": None}} assert extract_bool_setting(settings, "flag", default=False) is False def test_empty_string_is_false(self): """Empty string is not in the truthy set, so it's False.""" settings = {"flag": {"value": ""}} assert extract_bool_setting(settings, "flag") is False def test_whitespace_string_true(self): """to_bool strips whitespace before comparison.""" settings = {"flag": {"value": " true "}} assert extract_bool_setting(settings, "flag") is True def test_case_insensitive_TRUE(self): settings = {"flag": {"value": "TRUE"}} assert extract_bool_setting(settings, "flag") is True def test_plain_value_not_dict(self): """When value is stored directly (not in a dict with 'value' key).""" settings = {"flag": "yes"} assert extract_bool_setting(settings, "flag") is True def test_none_snapshot_returns_default(self): assert extract_bool_setting(None, "flag", default=True) is True def test_string_enabled_is_true(self): settings = {"flag": {"value": "enabled"}} assert extract_bool_setting(settings, "flag") is True def test_string_on_is_true(self): settings = {"flag": {"value": "on"}} assert extract_bool_setting(settings, "flag") is True def test_arbitrary_string_is_false(self): """An unrecognized string should be False.""" settings = {"flag": {"value": "maybe"}} assert extract_bool_setting(settings, "flag") is False