From 9f4b1628117413263bc30524d4fdfc22ec6bf0d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:56:58 +0000 Subject: [PATCH] fix(tests): resolve CI test failures from asyncio event loop and settings reload side-effects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two root causes identified and fixed: 1. tests/test_api_settings.py (TestListCredentials): asyncio.get_event_loop().run_until_complete() raised RuntimeError in Python 3.12 because test_api_auth_enabled.py's asyncio.run() sets the current event loop to None on completion. Replace all 7 occurrences with asyncio.run() which creates its own event loop each time. 2. tests/test_cors.py: reload(app.config) replaced the app.config.settings singleton with a new instance, so app modules holding the original reference no longer saw patches applied to app.config.settings.X. This caused the notification, OpenAI, and file-upload tests to behave as if unpatched. Remove the redundant reload() calls — the tests only need a fresh Settings(...) instance constructed with the env var already set. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- tests/test_api_settings.py | 14 +++++++------- tests/test_cors.py | 14 ++++---------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/tests/test_api_settings.py b/tests/test_api_settings.py index de9c65fe..8512387d 100644 --- a/tests/test_api_settings.py +++ b/tests/test_api_settings.py @@ -226,7 +226,7 @@ class TestListCredentials: for key in SETTING_METADATA: setattr(mock_settings, key, None) - result = asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + result = asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) returned_keys = {c["key"] for c in result["credentials"]} sensitive_keys = {k for k, v in SETTING_METADATA.items() if v.get("sensitive")} @@ -247,7 +247,7 @@ class TestListCredentials: with patch("app.api.settings.settings") as mock_settings: mock_settings.openai_api_key = "sk-env-key" - result = asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + result = asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) openai_entry = next(c for c in result["credentials"] if c["key"] == "openai_api_key") assert openai_entry["source"] == "db" @@ -268,7 +268,7 @@ class TestListCredentials: with patch("app.api.settings.settings") as mock_settings: mock_settings.openai_api_key = "sk-env-key" - result = asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + result = asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) openai_entry = next(c for c in result["credentials"] if c["key"] == "openai_api_key") assert openai_entry["source"] == "env" @@ -289,7 +289,7 @@ class TestListCredentials: with patch("app.api.settings.settings") as mock_settings: mock_settings.openai_api_key = None - result = asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + result = asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) openai_entry = next(c for c in result["credentials"] if c["key"] == "openai_api_key") assert openai_entry["configured"] is False @@ -311,7 +311,7 @@ class TestListCredentials: # Most keys will be None, one will be set via db_settings mock mock_settings.openai_api_key = "sk-key" - result = asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + result = asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) assert result["total"] == len(result["credentials"]) assert result["configured_count"] + result["unconfigured_count"] == result["total"] @@ -331,7 +331,7 @@ class TestListCredentials: mock_admin = {"is_admin": True} with pytest.raises(HTTPException) as exc_info: - asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) assert exc_info.value.status_code == 500 def test_list_credentials_endpoint_requires_admin(self, client): @@ -354,7 +354,7 @@ class TestListCredentials: with patch("app.api.settings.settings") as mock_settings: mock_settings.openai_api_key = None - result = asyncio.get_event_loop().run_until_complete(list_credentials(mock_request, mock_db, mock_admin)) + result = asyncio.run(list_credentials(mock_request, mock_db, mock_admin)) for cred in result["credentials"]: assert "key" in cred diff --git a/tests/test_cors.py b/tests/test_cors.py index ae9a4025..9357c21a 100644 --- a/tests/test_cors.py +++ b/tests/test_cors.py @@ -169,12 +169,9 @@ def test_cors_parse_comma_separated_origins(): original = os.environ.get("CORS_ALLOWED_ORIGINS") os.environ["CORS_ALLOWED_ORIGINS"] = "https://app.example.com,https://admin.example.com" try: - from importlib import reload + from app.config import Settings - import app.config as config_module - - reload(config_module) - test_settings = config_module.Settings( + test_settings = Settings( database_url="sqlite:///:memory:", redis_url="redis://localhost:6379/0", openai_api_key="test-key", @@ -204,12 +201,9 @@ def test_cors_single_origin_string_to_list(): original = os.environ.get("CORS_ALLOWED_ORIGINS") os.environ["CORS_ALLOWED_ORIGINS"] = "https://app.example.com" try: - from importlib import reload + from app.config import Settings - import app.config as config_module - - reload(config_module) - test_settings = config_module.Settings( + test_settings = Settings( database_url="sqlite:///:memory:", redis_url="redis://localhost:6379/0", openai_api_key="test-key",