"""Shared test helpers for the settings_routes coverage suites. Extracted from the previously copy-pasted headers of the ``test_settings_routes_*_coverage`` suites so the mock-Setting builder, the Flask-app factory and the authenticated-client plumbing live in one place. The versions here are the canonical, verified-identical copies that those suites each carried locally. Divergent per-file variants (e.g. the expanded ``_authenticated_client`` that builds a Setting query mock, or ``deep_coverage2``'s trimmed ``_make_setting``) intentionally stay in their own files and are not represented here. """ from contextlib import contextmanager from unittest.mock import MagicMock, Mock, patch from flask import Flask, jsonify from local_deep_research.web.auth.routes import auth_bp from local_deep_research.web.routes.settings_routes import settings_bp _MODULE = "local_deep_research.web.routes.settings_routes" _DECORATOR_MODULE = "local_deep_research.web.utils.route_decorators" def _make_setting( key="test.key", value="val", ui_element="text", name="Test Key", description="desc", category="general", setting_type="app", editable=True, visible=True, options=None, min_value=None, max_value=None, step=None, updated_at=None, ): """Build a mock Setting ORM object.""" s = MagicMock() s.key = key s.value = value s.ui_element = ui_element s.name = name s.description = description s.category = category s.type = setting_type s.editable = editable s.visible = visible s.options = options s.min_value = min_value s.max_value = max_value s.step = step s.updated_at = updated_at return s def _create_test_app(): """Create a minimal Flask app with only the settings blueprint.""" app = Flask(__name__) app.config["SECRET_KEY"] = "test-secret" app.config["WTF_CSRF_ENABLED"] = False app.register_blueprint(auth_bp) app.register_blueprint(settings_bp) @app.errorhandler(500) def _handle_500(error): return jsonify({"error": "Internal server error"}), 500 return app @contextmanager def _authenticated_client(app): """Provide an authenticated test client with mocked auth and settings_limit.""" mock_db = Mock() mock_db.connections = {"testuser": True} mock_db.has_encryption = False @contextmanager def _fake_session(*args, **kwargs): yield MagicMock() patches = [ patch("local_deep_research.web.auth.decorators.db_manager", mock_db), patch( f"{_DECORATOR_MODULE}.get_user_db_session", side_effect=_fake_session, ), patch(f"{_MODULE}.settings_limit", lambda f: f), ] try: for p in patches: p.start() with app.test_client() as client: with client.session_transaction() as sess: sess["username"] = "testuser" sess["session_id"] = "test-session-id" yield client finally: for p in reversed(patches): p.stop()