From ae9513b4d17b6d70b2621adfa3ccf079dc22f613 Mon Sep 17 00:00:00 2001 From: Desel72 Date: Mon, 23 Mar 2026 18:32:32 +0000 Subject: [PATCH 1/5] test: migrate oauth tests to testcontainers --- .../controllers/console/auth/test_oauth.py | 88 +++++++------------ 1 file changed, 34 insertions(+), 54 deletions(-) rename api/tests/{unit_tests => test_containers_integration_tests}/controllers/console/auth/test_oauth.py (90%) diff --git a/api/tests/unit_tests/controllers/console/auth/test_oauth.py b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py similarity index 90% rename from api/tests/unit_tests/controllers/console/auth/test_oauth.py rename to api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py index 6345c2ab23..df8f93d460 100644 --- a/api/tests/unit_tests/controllers/console/auth/test_oauth.py +++ b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py @@ -1,7 +1,10 @@ +"""Testcontainers integration tests for OAuth controller endpoints.""" + +from __future__ import annotations + from unittest.mock import MagicMock, patch import pytest -from flask import Flask from controllers.console.auth.oauth import ( OAuthCallback, @@ -18,10 +21,8 @@ from services.errors.account import AccountRegisterError class TestGetOAuthProviders: @pytest.fixture - def app(self): - app = Flask(__name__) - app.config["TESTING"] = True - return app + def app(self, flask_app_with_containers): + return flask_app_with_containers @pytest.mark.parametrize( ("github_config", "google_config", "expected_github", "expected_google"), @@ -64,10 +65,8 @@ class TestOAuthLogin: return OAuthLogin() @pytest.fixture - def app(self): - app = Flask(__name__) - app.config["TESTING"] = True - return app + def app(self, flask_app_with_containers): + return flask_app_with_containers @pytest.fixture def mock_oauth_provider(self): @@ -131,10 +130,8 @@ class TestOAuthCallback: return OAuthCallback() @pytest.fixture - def app(self): - app = Flask(__name__) - app.config["TESTING"] = True - return app + def app(self, flask_app_with_containers): + return flask_app_with_containers @pytest.fixture def oauth_setup(self): @@ -190,15 +187,10 @@ class TestOAuthCallback: (KeyError("Missing key"), "OAuth process failed"), ], ) - @patch("controllers.console.auth.oauth.db") @patch("controllers.console.auth.oauth.get_oauth_providers") def test_should_handle_oauth_exceptions( - self, mock_get_providers, mock_db, resource, app, exception, expected_error + self, mock_get_providers, resource, app, exception, expected_error ): - # Mock database session - mock_db.session = MagicMock() - mock_db.session.rollback = MagicMock() - # Import the real requests module to create a proper exception import httpx @@ -258,7 +250,6 @@ class TestOAuthCallback: ) @patch("controllers.console.auth.oauth.AccountService") @patch("controllers.console.auth.oauth.TenantService") - @patch("controllers.console.auth.oauth.db") @patch("controllers.console.auth.oauth.dify_config") @patch("controllers.console.auth.oauth.get_oauth_providers") @patch("controllers.console.auth.oauth._generate_account") @@ -269,7 +260,6 @@ class TestOAuthCallback: mock_generate_account, mock_get_providers, mock_config, - mock_db, mock_tenant_service, mock_account_service, resource, @@ -278,10 +268,6 @@ class TestOAuthCallback: account_status, expected_redirect, ): - # Mock database session - mock_db.session = MagicMock() - mock_db.session.rollback = MagicMock() - mock_db.session.commit = MagicMock() mock_config.CONSOLE_WEB_URL = "http://localhost:3000" mock_get_providers.return_value = {"github": oauth_setup["provider"]} @@ -306,14 +292,12 @@ class TestOAuthCallback: @patch("controllers.console.auth.oauth.dify_config") @patch("controllers.console.auth.oauth.get_oauth_providers") @patch("controllers.console.auth.oauth._generate_account") - @patch("controllers.console.auth.oauth.db") @patch("controllers.console.auth.oauth.TenantService") @patch("controllers.console.auth.oauth.AccountService") def test_should_activate_pending_account( self, mock_account_service, mock_tenant_service, - mock_db, mock_generate_account, mock_get_providers, mock_config, @@ -338,12 +322,10 @@ class TestOAuthCallback: assert mock_account.status == AccountStatus.ACTIVE assert mock_account.initialized_at is not None - mock_db.session.commit.assert_called_once() @patch("controllers.console.auth.oauth.dify_config") @patch("controllers.console.auth.oauth.get_oauth_providers") @patch("controllers.console.auth.oauth._generate_account") - @patch("controllers.console.auth.oauth.db") @patch("controllers.console.auth.oauth.TenantService") @patch("controllers.console.auth.oauth.AccountService") @patch("controllers.console.auth.oauth.redirect") @@ -352,7 +334,6 @@ class TestOAuthCallback: mock_redirect, mock_account_service, mock_tenant_service, - mock_db, mock_generate_account, mock_get_providers, mock_config, @@ -425,15 +406,10 @@ class TestAccountGeneration: return account @patch("controllers.console.auth.oauth.AccountService.get_account_by_email_with_case_fallback") - @patch("controllers.console.auth.oauth.Session") @patch("controllers.console.auth.oauth.Account") - @patch("controllers.console.auth.oauth.db") def test_should_get_account_by_openid_or_email( - self, mock_db, mock_account_model, mock_session, mock_get_account, user_info, mock_account + self, mock_account_model, mock_get_account, user_info, mock_account ): - # Mock db.engine for Session creation - mock_db.engine = MagicMock() - # Test OpenID found mock_account_model.get_by_openid.return_value = mock_account result = _get_account_by_openid_or_email("github", user_info) @@ -443,27 +419,35 @@ class TestAccountGeneration: # Test fallback to email lookup mock_account_model.get_by_openid.return_value = None - mock_session_instance = MagicMock() - mock_session.return_value.__enter__.return_value = mock_session_instance mock_get_account.return_value = mock_account result = _get_account_by_openid_or_email("github", user_info) assert result == mock_account - mock_get_account.assert_called_once_with(user_info.email, session=mock_session_instance) + mock_get_account.assert_called_once() - def test_get_account_by_email_with_case_fallback_uses_lowercase_lookup(self): - mock_session = MagicMock() - first_result = MagicMock() - first_result.scalar_one_or_none.return_value = None - expected_account = MagicMock() - second_result = MagicMock() - second_result.scalar_one_or_none.return_value = expected_account - mock_session.execute.side_effect = [first_result, second_result] + def test_get_account_by_email_with_case_fallback_uses_real_db(self, db_session_with_containers): + """Test case-insensitive email lookup against real PostgreSQL.""" + from models.account import Account - result = AccountService.get_account_by_email_with_case_fallback("Case@Test.com", session=mock_session) + account = Account( + email="Case@Test.com", + name="Test User", + interface_language="en-US", + status="active", + ) + db_session_with_containers.add(account) + db_session_with_containers.commit() - assert result == expected_account - assert mock_session.execute.call_count == 2 + result = AccountService.get_account_by_email_with_case_fallback( + "Case@Test.com", session=db_session_with_containers + ) + assert result is not None + + result_lower = AccountService.get_account_by_email_with_case_fallback( + "case@test.com", session=db_session_with_containers + ) + assert result_lower is not None + assert result_lower.id == account.id @pytest.mark.parametrize( ("allow_register", "existing_account", "should_create"), @@ -478,10 +462,8 @@ class TestAccountGeneration: @patch("controllers.console.auth.oauth.RegisterService") @patch("controllers.console.auth.oauth.AccountService") @patch("controllers.console.auth.oauth.TenantService") - @patch("controllers.console.auth.oauth.db") def test_should_handle_account_generation_scenarios( self, - mock_db, mock_tenant_service, mock_account_service, mock_register_service, @@ -519,10 +501,8 @@ class TestAccountGeneration: @patch("controllers.console.auth.oauth.RegisterService") @patch("controllers.console.auth.oauth.AccountService") @patch("controllers.console.auth.oauth.TenantService") - @patch("controllers.console.auth.oauth.db") def test_should_register_with_lowercase_email( self, - mock_db, mock_tenant_service, mock_account_service, mock_register_service, From 96eab76bfd25292a860ac0bfa52814f9ac8d3e88 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 18:36:03 +0000 Subject: [PATCH 2/5] [autofix.ci] apply automated fixes --- .../controllers/console/auth/test_oauth.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py index df8f93d460..d03988098d 100644 --- a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py +++ b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py @@ -188,9 +188,7 @@ class TestOAuthCallback: ], ) @patch("controllers.console.auth.oauth.get_oauth_providers") - def test_should_handle_oauth_exceptions( - self, mock_get_providers, resource, app, exception, expected_error - ): + def test_should_handle_oauth_exceptions(self, mock_get_providers, resource, app, exception, expected_error): # Import the real requests module to create a proper exception import httpx @@ -407,9 +405,7 @@ class TestAccountGeneration: @patch("controllers.console.auth.oauth.AccountService.get_account_by_email_with_case_fallback") @patch("controllers.console.auth.oauth.Account") - def test_should_get_account_by_openid_or_email( - self, mock_account_model, mock_get_account, user_info, mock_account - ): + def test_should_get_account_by_openid_or_email(self, mock_account_model, mock_get_account, user_info, mock_account): # Test OpenID found mock_account_model.get_by_openid.return_value = mock_account result = _get_account_by_openid_or_email("github", user_info) From 20f5e307ad986a6d6a563575c332eeadbf27cba7 Mon Sep 17 00:00:00 2001 From: Desel72 Date: Mon, 23 Mar 2026 18:49:42 +0000 Subject: [PATCH 3/5] fix: add flask context and fix Account status in oauth tests --- .../controllers/console/auth/test_oauth.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py index d03988098d..cd3fd05901 100644 --- a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py +++ b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py @@ -405,7 +405,9 @@ class TestAccountGeneration: @patch("controllers.console.auth.oauth.AccountService.get_account_by_email_with_case_fallback") @patch("controllers.console.auth.oauth.Account") - def test_should_get_account_by_openid_or_email(self, mock_account_model, mock_get_account, user_info, mock_account): + def test_should_get_account_by_openid_or_email( + self, mock_account_model, mock_get_account, flask_req_ctx_with_containers, user_info, mock_account + ): # Test OpenID found mock_account_model.get_by_openid.return_value = mock_account result = _get_account_by_openid_or_email("github", user_info) @@ -423,24 +425,26 @@ class TestAccountGeneration: def test_get_account_by_email_with_case_fallback_uses_real_db(self, db_session_with_containers): """Test case-insensitive email lookup against real PostgreSQL.""" + from uuid import uuid4 + from models.account import Account account = Account( - email="Case@Test.com", + email=f"Case-{uuid4()}@Test.com", name="Test User", interface_language="en-US", - status="active", + status=AccountStatus.ACTIVE, ) db_session_with_containers.add(account) db_session_with_containers.commit() result = AccountService.get_account_by_email_with_case_fallback( - "Case@Test.com", session=db_session_with_containers + account.email, session=db_session_with_containers ) assert result is not None result_lower = AccountService.get_account_by_email_with_case_fallback( - "case@test.com", session=db_session_with_containers + account.email.lower(), session=db_session_with_containers ) assert result_lower is not None assert result_lower.id == account.id From a3fa0a5577781d3aa924c6ea29c2cbfcabac30e0 Mon Sep 17 00:00:00 2001 From: Desel72 Date: Tue, 24 Mar 2026 03:18:58 +0000 Subject: [PATCH 4/5] fix: add flask context and expire_all for case fallback test --- .../controllers/console/auth/test_oauth.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py index cd3fd05901..6d3adcf09c 100644 --- a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py +++ b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py @@ -423,28 +423,32 @@ class TestAccountGeneration: assert result == mock_account mock_get_account.assert_called_once() - def test_get_account_by_email_with_case_fallback_uses_real_db(self, db_session_with_containers): + def test_get_account_by_email_with_case_fallback_uses_real_db( + self, flask_req_ctx_with_containers, db_session_with_containers + ): """Test case-insensitive email lookup against real PostgreSQL.""" from uuid import uuid4 from models.account import Account + test_email = f"Case-{uuid4()}@Test.com" account = Account( - email=f"Case-{uuid4()}@Test.com", + email=test_email, name="Test User", interface_language="en-US", status=AccountStatus.ACTIVE, ) db_session_with_containers.add(account) db_session_with_containers.commit() + db_session_with_containers.expire_all() result = AccountService.get_account_by_email_with_case_fallback( - account.email, session=db_session_with_containers + test_email, session=db_session_with_containers ) assert result is not None result_lower = AccountService.get_account_by_email_with_case_fallback( - account.email.lower(), session=db_session_with_containers + test_email.lower(), session=db_session_with_containers ) assert result_lower is not None assert result_lower.id == account.id From d1e477e372c63fd46d32150a8c69abe711e7984c Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 03:21:19 +0000 Subject: [PATCH 5/5] [autofix.ci] apply automated fixes --- .../controllers/console/auth/test_oauth.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py index 6d3adcf09c..111eda759d 100644 --- a/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py +++ b/api/tests/test_containers_integration_tests/controllers/console/auth/test_oauth.py @@ -442,9 +442,7 @@ class TestAccountGeneration: db_session_with_containers.commit() db_session_with_containers.expire_all() - result = AccountService.get_account_by_email_with_case_fallback( - test_email, session=db_session_with_containers - ) + result = AccountService.get_account_by_email_with_case_fallback(test_email, session=db_session_with_containers) assert result is not None result_lower = AccountService.get_account_by_email_with_case_fallback(