""" Extended tests for settings/manager.py Tests cover additional functionality not in the main test file: - Type conversion edge cases (get_bool_setting, various ui_elements) - Environment variable edge cases - Import/export settings - Version checking - Default settings loading - create_setting helper - WebSocket event emission - Nested settings paths - Password/sensitive field handling """ import os import json from unittest.mock import Mock, MagicMock, patch class MockSetting: """Mock Setting model for testing.""" def __init__( self, key, value, ui_element="text", editable=True, type=None, name=None, description=None, category=None, options=None, min_value=None, max_value=None, step=None, visible=True, ): self.key = key self.value = value self.ui_element = ui_element self.editable = editable self.type = type or Mock(name="APP") self.name = name or key self.description = description or "" self.category = category self.options = options self.min_value = min_value self.max_value = max_value self.step = step self.visible = visible self.updated_at = None class TestGetBoolSetting: """Tests for get_bool_setting method.""" def test_get_bool_setting_true_string(self): """get_bool_setting converts 'true' string to True.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value="true", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.debug", check_env=False) assert result is True def test_get_bool_setting_false_string(self): """get_bool_setting converts 'false' string to False.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value="false", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.debug", check_env=False) assert result is False def test_get_bool_setting_1_string(self): """get_bool_setting converts '1' string to True.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value="1", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.debug", check_env=False) assert result is True def test_get_bool_setting_0_string(self): """get_bool_setting converts '0' string to False.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value="0", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.debug", check_env=False) assert result is False def test_get_bool_setting_boolean_true(self): """get_bool_setting handles actual boolean True.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value=True, ui_element="checkbox" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.debug", check_env=False) assert result is True def test_get_bool_setting_returns_default(self): """get_bool_setting returns default when setting not found.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.all.return_value = [] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.nonexistent", default=True) assert result is True def test_get_bool_setting_yes_string(self): """get_bool_setting converts 'yes' string to True.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.enabled", value="yes", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_bool_setting("app.enabled", check_env=False) assert result is True class TestUIElementTypeConversion: """Tests for UI element type conversion.""" def test_checkbox_returns_bool(self): """Checkbox ui_element returns boolean.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value=True, ui_element="checkbox" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("app.debug", check_env=False) assert isinstance(result, bool) def test_number_returns_float(self): """Number ui_element returns float.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.temperature", value=0.7, ui_element="number" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.temperature", check_env=False) assert isinstance(result, float) def test_range_returns_float(self): """Range ui_element returns float.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.top_p", value=0.9, ui_element="range" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.top_p", check_env=False) assert isinstance(result, float) def test_text_returns_string(self): """Text ui_element returns string.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.model", value="gpt-4", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.model", check_env=False) assert isinstance(result, str) def test_password_returns_string(self): """Password ui_element returns string.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.api_key", value="secret123", ui_element="password" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.api_key", check_env=False) assert isinstance(result, str) def test_select_returns_string(self): """Select ui_element returns string.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.theme", value="dark", ui_element="select" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("app.theme", check_env=False) assert isinstance(result, str) def test_json_returns_as_is(self): """JSON ui_element returns value as-is.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() json_value = {"key": "value", "nested": {"data": 123}} mock_setting = MockSetting( key="app.config", value=json_value, ui_element="json" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("app.config", check_env=False) assert result == json_value def test_unknown_ui_element_returns_default(self): """Unknown ui_element returns default value.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.unknown", value="test", ui_element="unknown_type" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting( "app.unknown", default="default_val", check_env=False ) assert result == "default_val" class TestEnvironmentVariableEdgeCases: """Tests for environment variable handling edge cases.""" def test_env_override_invalid_number(self): """Invalid number in env var falls back to DB value.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.temperature", value=0.7, ui_element="number" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query os.environ["LDR_LLM_TEMPERATURE"] = "not_a_number" try: manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.temperature", check_env=True) # Should fall back to DB value assert result == 0.7 finally: del os.environ["LDR_LLM_TEMPERATURE"] def test_env_override_empty_string(self): """Empty string env var is treated as unset (Docker/Unraid templates create blank entries).""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.model", value="gpt-4", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query os.environ["LDR_LLM_MODEL"] = "" try: manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.model", check_env=True) # Empty env var should NOT override the DB value assert result == "gpt-4" finally: del os.environ["LDR_LLM_MODEL"] def test_env_override_empty_string_no_db_value(self): """Empty env var with no DB value falls through to default. This is the first-launch Unraid scenario: env vars are empty strings, no DB row exists yet, so the default should be returned. """ from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() # No DB rows match this key mock_query.filter.return_value.all.return_value = [] mock_session.query.return_value = mock_query os.environ["LDR_LLM_PROVIDER"] = "" try: manager = SettingsManager(db_session=mock_session) result = manager.get_setting( "llm.provider", default="openai", check_env=True ) assert result == "openai" finally: del os.environ["LDR_LLM_PROVIDER"] def test_env_override_empty_string_checkbox(self): """Empty env var for checkbox setting falls through to DB value.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="app.debug", value=True, ui_element="checkbox" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query os.environ["LDR_APP_DEBUG"] = "" try: manager = SettingsManager(db_session=mock_session) result = manager.get_setting("app.debug", check_env=True) assert result is True finally: del os.environ["LDR_APP_DEBUG"] def test_env_override_empty_string_number(self): """Empty env var for number setting falls through to DB value.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.temperature", value=0.7, ui_element="number" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query os.environ["LDR_LLM_TEMPERATURE"] = "" try: manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.temperature", check_env=True) assert result == 0.7 finally: del os.environ["LDR_LLM_TEMPERATURE"] def test_env_override_with_nested_key(self): """Nested key with multiple dots converts correctly.""" from local_deep_research.settings.manager import ( check_env_setting, ) os.environ["LDR_SEARCH_TOOL_MAX_RESULTS"] = "50" try: result = check_env_setting("search.tool.max_results") assert result == "50" finally: del os.environ["LDR_SEARCH_TOOL_MAX_RESULTS"] class TestNestedSettingsPaths: """Tests for nested settings path handling.""" def test_get_setting_returns_nested_dict(self): """Getting higher-level key returns nested dict.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_settings = [ MockSetting(key="llm.model", value="gpt-4", ui_element="text"), MockSetting(key="llm.temperature", value=0.7, ui_element="number"), ] mock_query.filter.return_value.all.return_value = mock_settings mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm", check_env=False) assert isinstance(result, dict) assert "model" in result assert "temperature" in result def test_get_setting_exact_match_single(self): """Getting exact key returns single value.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_setting = MockSetting( key="llm.model", value="gpt-4", ui_element="text" ) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.get_setting("llm.model", check_env=False) assert result == "gpt-4" class TestImportExportSettings: """Tests for import/export functionality.""" def test_import_settings_basic(self): """import_settings loads settings from dict.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.delete.return_value = 1 mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) settings_data = { "app.debug": { "value": True, "type": "APP", "name": "Debug", "ui_element": "checkbox", }, } with patch.object(manager, "_emit_settings_changed"): manager.import_settings(settings_data) mock_session.add.assert_called() mock_session.commit.assert_called() def test_import_settings_no_overwrite(self): """import_settings preserves existing values when overwrite=False.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.delete.return_value = 0 mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) manager.get_setting = Mock(return_value="existing_value") settings_data = { "app.key": { "value": "new_value", "type": "APP", "name": "Key", "ui_element": "text", }, } with patch.object(manager, "_emit_settings_changed"): manager.import_settings(settings_data, overwrite=False) # Check that existing value was preserved added_setting = mock_session.add.call_args[0][0] assert added_setting.value == "existing_value" def test_import_settings_delete_extra(self): """import_settings deletes extra settings when delete_extra=True.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.delete.return_value = 1 mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) # Mock get_all_settings to return extra setting manager.get_all_settings = Mock( return_value={ "app.keep": {"value": True}, "app.extra": {"value": False}, } ) manager.delete_setting = Mock(return_value=True) settings_data = { "app.keep": { "value": True, "type": "APP", "name": "Keep", "ui_element": "checkbox", }, } with patch.object(manager, "_emit_settings_changed"): manager.import_settings(settings_data, delete_extra=True) # Should have deleted the extra setting manager.delete_setting.assert_any_call("app.extra", commit=False) class TestLoadFromDefaultsFile: """Tests for load_from_defaults_file method.""" def test_load_from_defaults_file_calls_import(self): """load_from_defaults_file calls import_settings.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() manager = SettingsManager(db_session=mock_session) # Mock import_settings and default_settings manager.import_settings = Mock() manager.__dict__.pop("default_settings", None) with patch.object( type(manager), "default_settings", new_callable=lambda: property( lambda self: {"app.test": {"value": True}} ), ): manager.load_from_defaults_file() manager.import_settings.assert_called_once() class TestVersionChecking: """Tests for version checking functionality.""" def test_update_db_version(self): """update_db_version updates the version in DB.""" from local_deep_research.settings.manager import ( SettingsManager, ) from local_deep_research.__version__ import __version__ mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.delete.return_value = 1 mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) manager.update_db_version() mock_session.add.assert_called_once() added_setting = mock_session.add.call_args[0][0] assert added_setting.value == __version__ mock_session.commit.assert_called_once() class TestWebSocketEmission: """Tests for WebSocket event emission.""" @staticmethod def _request_ctx(username="alice"): """A Flask request context with ``username`` in the session, so _emit_settings_changed can resolve the owning user to scope the emit.""" from flask import Flask, session app = Flask(__name__) app.secret_key = "test-secret" ctx = app.test_request_context() ctx.push() if username is not None: session["username"] = username return ctx def _patched_socket(self, mock_socket_instance): # Give user_room a realistic return so room scoping can be asserted. mock_socket_instance.user_room.side_effect = lambda u: f"user:{u}" return patch.dict( "sys.modules", { "local_deep_research.web.services.socket_service": MagicMock( SocketIOService=Mock(return_value=mock_socket_instance) ) }, ) @staticmethod def _working_manager(): """A SettingsManager whose get_setting("app.debug") resolves to a real value, so the only thing that can suppress the emit is the scoping guard under test — not an incidental failure reading the setting.""" from local_deep_research.settings.manager import SettingsManager mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.all.return_value = [ MockSetting(key="app.debug", value=True) ] mock_session.query.return_value = mock_query return SettingsManager(db_session=mock_session) def test_emit_settings_changed_scoped_to_owning_user_room(self): """The event is emitted only to the changing user's per-user room — never broadcast — so one user's setting values (incl. plaintext API keys) never reach other connected clients.""" from local_deep_research.settings.manager import SettingsManager mock_session = Mock() mock_query = Mock() mock_setting = MockSetting(key="app.debug", value=True) mock_query.filter.return_value.all.return_value = [mock_setting] mock_session.query.return_value = mock_query mock_socket_instance = Mock() manager = SettingsManager(db_session=mock_session) ctx = self._request_ctx(username="alice") try: with self._patched_socket(mock_socket_instance): manager._emit_settings_changed(["app.debug"]) finally: ctx.pop() mock_socket_instance.emit_socket_event.assert_called_once() args, kwargs = mock_socket_instance.emit_socket_event.call_args assert args[0] == "settings_changed" assert "app.debug" in args[1]["changed_keys"] # The targeting room must be the owning user's room. assert kwargs.get("room") == "user:alice" def test_emit_settings_changed_skipped_without_request_context(self): """A settings change outside any request (start-up defaults, background workers, migrations) has no user tab to notify, so nothing is emitted — crucially, it must not fall back to a cross-user broadcast.""" mock_socket_instance = Mock() manager = self._working_manager() # No request context pushed. with self._patched_socket(mock_socket_instance): manager._emit_settings_changed(["app.debug"]) mock_socket_instance.emit_socket_event.assert_not_called() def test_emit_settings_changed_skipped_when_no_username(self): """A request without an authenticated username emits nothing.""" mock_socket_instance = Mock() manager = self._working_manager() ctx = self._request_ctx(username=None) try: with self._patched_socket(mock_socket_instance): manager._emit_settings_changed(["app.debug"]) finally: ctx.pop() mock_socket_instance.emit_socket_event.assert_not_called() def test_emit_settings_changed_handles_exception(self): """_emit_settings_changed handles exceptions gracefully.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() manager = SettingsManager(db_session=mock_session) # Mock SocketIOService to raise ValueError mock_socket_module = MagicMock() mock_socket_module.SocketIOService.side_effect = ValueError( "Not initialized" ) with patch.dict( "sys.modules", { "local_deep_research.web.services.socket_service": mock_socket_module }, ): # Should not raise manager._emit_settings_changed(["app.debug"]) class TestDefaultSettingsProperty: """Tests for default_settings property.""" @patch("local_deep_research.settings.manager.defaults") def test_default_settings_loads_json_files(self, mock_defaults): """default_settings loads JSON files from defaults directory.""" from local_deep_research.settings.manager import ( SettingsManager, ) import tempfile with tempfile.TemporaryDirectory() as tmpdir: # Create mock defaults path from pathlib import Path mock_defaults.__file__ = str(Path(tmpdir) / "__init__.py") # Create a test JSON file json_file = Path(tmpdir) / "test_settings.json" json_file.write_text( json.dumps( { "test.setting": { "value": "test_value", "type": "APP", "name": "Test", "ui_element": "text", } } ) ) manager = SettingsManager() settings = manager.default_settings assert "test.setting" in settings def test_default_settings_handles_invalid_json(self): """default_settings handles invalid JSON gracefully.""" from local_deep_research.settings.manager import ( SettingsManager, ) manager = SettingsManager() # Should not raise even if there are issues settings = manager.default_settings assert isinstance(settings, dict) class TestSettingTypeDetermination: """Tests for automatic setting type determination.""" def test_set_setting_determines_llm_type(self): """set_setting creates LLM type for llm. keys.""" from local_deep_research.settings.manager import ( SettingsManager, ) from local_deep_research.database.models import SettingType mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.first.return_value = None mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) with patch.object(manager, "_emit_settings_changed"): manager.set_setting("llm.new_setting", "value") added_setting = mock_session.add.call_args[0][0] assert added_setting.type == SettingType.LLM def test_set_setting_determines_search_type(self): """set_setting creates SEARCH type for search. keys.""" from local_deep_research.settings.manager import ( SettingsManager, ) from local_deep_research.database.models import SettingType mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.first.return_value = None mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) with patch.object(manager, "_emit_settings_changed"): manager.set_setting("search.new_setting", "value") added_setting = mock_session.add.call_args[0][0] assert added_setting.type == SettingType.SEARCH def test_set_setting_determines_report_type(self): """set_setting creates REPORT type for report. keys.""" from local_deep_research.settings.manager import ( SettingsManager, ) from local_deep_research.database.models import SettingType mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.first.return_value = None mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) with patch.object(manager, "_emit_settings_changed"): manager.set_setting("report.new_setting", "value") added_setting = mock_session.add.call_args[0][0] assert added_setting.type == SettingType.REPORT def test_set_setting_defaults_to_app_type(self): """set_setting creates APP type for other keys.""" from local_deep_research.settings.manager import ( SettingsManager, ) from local_deep_research.database.models import SettingType mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.first.return_value = None mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) with patch.object(manager, "_emit_settings_changed"): manager.set_setting("other.new_setting", "value") added_setting = mock_session.add.call_args[0][0] assert added_setting.type == SettingType.APP class TestCreateOrUpdateSettingTypes: """Tests for create_or_update_setting type handling.""" def test_create_or_update_with_llm_setting_class(self): """create_or_update_setting handles LLMSetting class.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.first.return_value = None mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) with patch.object(manager, "_emit_settings_changed"): result = manager.create_or_update_setting( { "key": "llm.model", "value": "gpt-4", "name": "Model", "description": "LLM model", } ) assert result is not None def test_create_or_update_with_search_setting_class(self): """create_or_update_setting handles SearchSetting class.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_query.filter.return_value.first.return_value = None mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) with patch.object(manager, "_emit_settings_changed"): result = manager.create_or_update_setting( { "key": "search.max_results", "value": 10, "name": "Max Results", "description": "Maximum results", } ) assert result is not None def test_create_or_update_with_non_editable_returns_none(self): """create_or_update_setting returns None for non-editable setting.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() existing_setting = MockSetting( key="app.version", value="1.0", editable=False ) mock_query.filter.return_value.first.return_value = existing_setting mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.create_or_update_setting( {"key": "app.version", "value": "2.0", "name": "Version"} ) assert result is None class TestEdgeCases: """Tests for edge cases and boundary conditions.""" def test_get_setting_without_db_uses_defaults(self): """get_setting uses defaults when no DB session.""" from local_deep_research.settings.manager import ( SettingsManager, ) manager = SettingsManager() # No db_session # Should use default_settings result = manager.get_setting("app.nonexistent", default="fallback") # Returns default since setting likely doesn't exist assert result == "fallback" def test_get_all_settings_marks_locked_non_editable(self): """get_all_settings marks settings non-editable when locked.""" from local_deep_research.settings.manager import ( SettingsManager, ) mock_session = Mock() mock_query = Mock() mock_settings = [ MockSetting(key="app.debug", value=True, editable=True), ] mock_query.all.return_value = mock_settings mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) manager._SettingsManager__settings_locked = True result = manager.get_all_settings() assert result["app.debug"]["editable"] is False def test_db_error_returns_default(self): """Database error returns default value.""" from local_deep_research.settings.manager import ( SettingsManager, ) from sqlalchemy.exc import SQLAlchemyError mock_session = Mock() # Let __init__'s _ensure_settings_initialized() succeed mock_session.query.return_value.count.return_value = 1 manager = SettingsManager(db_session=mock_session) # Now make query raise for get_setting mock_session.query.side_effect = SQLAlchemyError("DB Error") result = manager.get_setting("app.test", default="default") assert result == "default" def test_thread_safety_no_db_passes(self): """Thread safety check passes without DB session.""" from local_deep_research.settings.manager import ( SettingsManager, ) manager = SettingsManager() # No db_session # Should not raise even from different thread concept manager._check_thread_safety() def test_set_setting_rollback_on_error(self): """set_setting calls rollback on SQLAlchemy error.""" from local_deep_research.settings.manager import ( SettingsManager, ) from sqlalchemy.exc import SQLAlchemyError mock_session = Mock() mock_session.commit.side_effect = SQLAlchemyError("Commit failed") mock_query = Mock() mock_query.filter.return_value.first.return_value = MockSetting( key="app.test", value="old" ) mock_session.query.return_value = mock_query manager = SettingsManager(db_session=mock_session) result = manager.set_setting("app.test", "new") assert result is False mock_session.rollback.assert_called_once()