mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 15:08:06 +08:00
Merge branch 'main' into feat/mcp-06-18
This commit is contained in:
@ -8,7 +8,7 @@ from werkzeug.exceptions import Unauthorized
|
||||
|
||||
from configs import dify_config
|
||||
from controllers.console.error import AccountNotFound, NotAllowedCreateWorkspace
|
||||
from models.account import AccountStatus, TenantAccountJoin
|
||||
from models import AccountStatus, TenantAccountJoin
|
||||
from services.account_service import AccountService, RegisterService, TenantService, TokenPair
|
||||
from services.errors.account import (
|
||||
AccountAlreadyInTenantError,
|
||||
@ -470,7 +470,7 @@ class TestAccountService:
|
||||
|
||||
# Verify integration was created
|
||||
from extensions.ext_database import db
|
||||
from models.account import AccountIntegrate
|
||||
from models import AccountIntegrate
|
||||
|
||||
integration = db.session.query(AccountIntegrate).filter_by(account_id=account.id, provider="new-google").first()
|
||||
assert integration is not None
|
||||
@ -505,7 +505,7 @@ class TestAccountService:
|
||||
|
||||
# Verify integration was updated
|
||||
from extensions.ext_database import db
|
||||
from models.account import AccountIntegrate
|
||||
from models import AccountIntegrate
|
||||
|
||||
integration = (
|
||||
db.session.query(AccountIntegrate).filter_by(account_id=account.id, provider="exists-google").first()
|
||||
@ -2303,7 +2303,7 @@ class TestRegisterService:
|
||||
|
||||
# Verify account was created
|
||||
from extensions.ext_database import db
|
||||
from models.account import Account
|
||||
from models import Account
|
||||
from models.model import DifySetup
|
||||
|
||||
account = db.session.query(Account).filter_by(email=admin_email).first()
|
||||
@ -2352,7 +2352,7 @@ class TestRegisterService:
|
||||
|
||||
# Verify no entities were created (rollback worked)
|
||||
from extensions.ext_database import db
|
||||
from models.account import Account, Tenant, TenantAccountJoin
|
||||
from models import Account, Tenant, TenantAccountJoin
|
||||
from models.model import DifySetup
|
||||
|
||||
account = db.session.query(Account).filter_by(email=admin_email).first()
|
||||
@ -2446,7 +2446,7 @@ class TestRegisterService:
|
||||
|
||||
# Verify OAuth integration was created
|
||||
from extensions.ext_database import db
|
||||
from models.account import AccountIntegrate
|
||||
from models import AccountIntegrate
|
||||
|
||||
integration = db.session.query(AccountIntegrate).filter_by(account_id=account.id, provider=provider).first()
|
||||
assert integration is not None
|
||||
@ -2472,7 +2472,7 @@ class TestRegisterService:
|
||||
mock_external_service_dependencies["billing_service"].is_email_in_freeze.return_value = False
|
||||
|
||||
# Execute registration with pending status
|
||||
from models.account import AccountStatus
|
||||
from models import AccountStatus
|
||||
|
||||
account = RegisterService.register(
|
||||
email=email,
|
||||
@ -2661,7 +2661,7 @@ class TestRegisterService:
|
||||
|
||||
# Verify new account was created with pending status
|
||||
from extensions.ext_database import db
|
||||
from models.account import Account, TenantAccountJoin
|
||||
from models import Account, TenantAccountJoin
|
||||
|
||||
new_account = db.session.query(Account).filter_by(email=new_member_email).first()
|
||||
assert new_account is not None
|
||||
|
||||
@ -5,7 +5,7 @@ import pytest
|
||||
from faker import Faker
|
||||
|
||||
from core.plugin.impl.exc import PluginDaemonClientSideError
|
||||
from models.account import Account
|
||||
from models import Account
|
||||
from models.model import AppModelConfig, Conversation, EndUser, Message, MessageAgentThought
|
||||
from services.account_service import AccountService, TenantService
|
||||
from services.agent_service import AgentService
|
||||
|
||||
@ -4,7 +4,7 @@ import pytest
|
||||
from faker import Faker
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from models.account import Account
|
||||
from models import Account
|
||||
from models.model import MessageAnnotation
|
||||
from services.annotation_service import AppAnnotationService
|
||||
from services.app_service import AppService
|
||||
|
||||
@ -4,7 +4,7 @@ import pytest
|
||||
from faker import Faker
|
||||
|
||||
from constants.model_template import default_app_templates
|
||||
from models.account import Account
|
||||
from models import Account
|
||||
from models.model import App, Site
|
||||
from services.account_service import AccountService, TenantService
|
||||
from services.app_service import AppService
|
||||
|
||||
@ -8,7 +8,7 @@ from sqlalchemy import Engine
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from configs import dify_config
|
||||
from models.account import Account, Tenant
|
||||
from models import Account, Tenant
|
||||
from models.enums import CreatorUserRole
|
||||
from models.model import EndUser, UploadFile
|
||||
from services.errors.file import FileTooLargeError, UnsupportedFileTypeError
|
||||
|
||||
@ -4,7 +4,7 @@ import pytest
|
||||
from faker import Faker
|
||||
|
||||
from core.rag.index_processor.constant.built_in_field import BuiltInField
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, DatasetMetadata, DatasetMetadataBinding, Document
|
||||
from services.entities.knowledge_entities.knowledge_entities import MetadataArgs
|
||||
from services.metadata_service import MetadataService
|
||||
@ -17,9 +17,7 @@ class TestMetadataService:
|
||||
def mock_external_service_dependencies(self):
|
||||
"""Mock setup for external service dependencies."""
|
||||
with (
|
||||
patch(
|
||||
"services.metadata_service.current_user", create_autospec(Account, instance=True)
|
||||
) as mock_current_user,
|
||||
patch("libs.login.current_user", create_autospec(Account, instance=True)) as mock_current_user,
|
||||
patch("services.metadata_service.redis_client") as mock_redis_client,
|
||||
patch("services.dataset_service.DocumentService") as mock_document_service,
|
||||
):
|
||||
|
||||
@ -5,7 +5,7 @@ from faker import Faker
|
||||
|
||||
from core.entities.model_entities import ModelStatus
|
||||
from core.model_runtime.entities.model_entities import FetchFrom, ModelType
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.provider import Provider, ProviderModel, ProviderModelSetting, ProviderType
|
||||
from services.model_provider_service import ModelProviderService
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ from faker import Faker
|
||||
from sqlalchemy import select
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset
|
||||
from models.model import App, Tag, TagBinding
|
||||
from services.tag_service import TagService
|
||||
|
||||
@ -5,7 +5,7 @@ from faker import Faker
|
||||
from sqlalchemy import select
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from models.account import Account
|
||||
from models import Account
|
||||
from models.model import Conversation, EndUser
|
||||
from models.web import PinnedConversation
|
||||
from services.account_service import AccountService, TenantService
|
||||
|
||||
@ -7,7 +7,7 @@ from faker import Faker
|
||||
from werkzeug.exceptions import NotFound, Unauthorized
|
||||
|
||||
from libs.password import hash_password
|
||||
from models.account import Account, AccountStatus, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, AccountStatus, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.model import App, Site
|
||||
from services.errors.account import AccountLoginError, AccountNotFoundError, AccountPasswordError
|
||||
from services.webapp_auth_service import WebAppAuthService, WebAppAuthType
|
||||
@ -863,13 +863,14 @@ class TestWebAppAuthService:
|
||||
- Mock service integration
|
||||
"""
|
||||
# Arrange: Setup mock for enterprise service
|
||||
mock_webapp_auth = type("MockWebAppAuth", (), {"access_mode": "sso_verified"})()
|
||||
mock_external_service_dependencies["app_service"].get_app_id_by_code.return_value = "mock_app_id"
|
||||
setting = type("MockWebAppAuth", (), {"access_mode": "sso_verified"})()
|
||||
mock_external_service_dependencies[
|
||||
"enterprise_service"
|
||||
].WebAppAuth.get_app_access_mode_by_code.return_value = mock_webapp_auth
|
||||
].WebAppAuth.get_app_access_mode_by_id.return_value = setting
|
||||
|
||||
# Act: Execute authentication type determination
|
||||
result = WebAppAuthService.get_app_auth_type(app_code="mock_app_code")
|
||||
result: WebAppAuthType = WebAppAuthService.get_app_auth_type(app_code="mock_app_code")
|
||||
|
||||
# Assert: Verify correct result
|
||||
assert result == WebAppAuthType.EXTERNAL
|
||||
@ -877,7 +878,7 @@ class TestWebAppAuthService:
|
||||
# Verify mock service was called correctly
|
||||
mock_external_service_dependencies[
|
||||
"enterprise_service"
|
||||
].WebAppAuth.get_app_access_mode_by_code.assert_called_once_with("mock_app_code")
|
||||
].WebAppAuth.get_app_access_mode_by_id.assert_called_once_with(app_id="mock_app_id")
|
||||
|
||||
def test_get_app_auth_type_no_parameters(self, db_session_with_containers, mock_external_service_dependencies):
|
||||
"""
|
||||
|
||||
@ -3,7 +3,7 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from services.workspace_service import WorkspaceService
|
||||
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from models.account import Account, Tenant
|
||||
from models import Account, Tenant
|
||||
from models.tools import ApiToolProvider
|
||||
from services.tools.api_tools_manage_service import ApiToolManageService
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import pytest
|
||||
from faker import Faker
|
||||
|
||||
from core.tools.entities.tool_entities import ToolProviderType
|
||||
from models.account import Account, Tenant
|
||||
from models import Account, Tenant
|
||||
from models.tools import MCPToolProvider
|
||||
from services.tools.mcp_tools_manage_service import UNCHANGED_SERVER_URL_PLACEHOLDER, MCPToolManageService
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ from core.app.app_config.entities import (
|
||||
)
|
||||
from core.model_runtime.entities.llm_entities import LLMMode
|
||||
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
||||
from models.account import Account, Tenant
|
||||
from models import Account, Tenant
|
||||
from models.api_based_extension import APIBasedExtension
|
||||
from models.model import App, AppMode, AppModelConfig
|
||||
from models.workflow import Workflow
|
||||
|
||||
@ -6,7 +6,7 @@ from faker import Faker
|
||||
from core.rag.index_processor.constant.index_type import IndexType
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, DatasetAutoDisableLog, Document, DocumentSegment
|
||||
from tasks.add_document_to_index_task import add_document_to_index_task
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ from faker import Faker
|
||||
|
||||
from extensions.ext_database import db
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, Document, DocumentSegment
|
||||
from models.model import UploadFile
|
||||
from tasks.batch_clean_document_task import batch_clean_document_task
|
||||
|
||||
@ -18,7 +18,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, Document, DocumentSegment
|
||||
from models.enums import CreatorUserRole
|
||||
from models.model import UploadFile
|
||||
|
||||
@ -17,7 +17,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import (
|
||||
AppDatasetJoin,
|
||||
Dataset,
|
||||
|
||||
@ -13,7 +13,7 @@ import pytest
|
||||
from faker import Faker
|
||||
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, Document, DocumentSegment
|
||||
from tasks.create_segment_to_index_task import create_segment_to_index_task
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ from faker import Faker
|
||||
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, Document, DocumentSegment
|
||||
from tasks.disable_segment_from_index_task import disable_segment_from_index_task
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import pytest
|
||||
from faker import Faker
|
||||
|
||||
from extensions.ext_database import db
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, Document
|
||||
from tasks.document_indexing_task import document_indexing_task
|
||||
|
||||
|
||||
@ -0,0 +1,134 @@
|
||||
"""
|
||||
TestContainers-based integration tests for mail_register_task.py
|
||||
|
||||
This module provides integration tests for email registration tasks
|
||||
using TestContainers to ensure real database and service interactions.
|
||||
"""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from libs.email_i18n import EmailType
|
||||
from tasks.mail_register_task import send_email_register_mail_task, send_email_register_mail_task_when_account_exist
|
||||
|
||||
|
||||
class TestMailRegisterTask:
|
||||
"""Integration tests for mail_register_task using testcontainers."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_mail_dependencies(self):
|
||||
"""Mock setup for mail service dependencies."""
|
||||
with (
|
||||
patch("tasks.mail_register_task.mail") as mock_mail,
|
||||
patch("tasks.mail_register_task.get_email_i18n_service") as mock_get_email_service,
|
||||
):
|
||||
# Setup mock mail service
|
||||
mock_mail.is_inited.return_value = True
|
||||
|
||||
# Setup mock email i18n service
|
||||
mock_email_service = MagicMock()
|
||||
mock_get_email_service.return_value = mock_email_service
|
||||
|
||||
yield {
|
||||
"mail": mock_mail,
|
||||
"email_service": mock_email_service,
|
||||
"get_email_service": mock_get_email_service,
|
||||
}
|
||||
|
||||
def test_send_email_register_mail_task_success(self, db_session_with_containers, mock_mail_dependencies):
|
||||
"""Test successful email registration mail sending."""
|
||||
fake = Faker()
|
||||
language = "en-US"
|
||||
to_email = fake.email()
|
||||
code = fake.numerify("######")
|
||||
|
||||
send_email_register_mail_task(language=language, to=to_email, code=code)
|
||||
|
||||
mock_mail_dependencies["mail"].is_inited.assert_called_once()
|
||||
mock_mail_dependencies["email_service"].send_email.assert_called_once_with(
|
||||
email_type=EmailType.EMAIL_REGISTER,
|
||||
language_code=language,
|
||||
to=to_email,
|
||||
template_context={
|
||||
"to": to_email,
|
||||
"code": code,
|
||||
},
|
||||
)
|
||||
|
||||
def test_send_email_register_mail_task_mail_not_initialized(
|
||||
self, db_session_with_containers, mock_mail_dependencies
|
||||
):
|
||||
"""Test email registration task when mail service is not initialized."""
|
||||
mock_mail_dependencies["mail"].is_inited.return_value = False
|
||||
|
||||
send_email_register_mail_task(language="en-US", to="test@example.com", code="123456")
|
||||
|
||||
mock_mail_dependencies["get_email_service"].assert_not_called()
|
||||
mock_mail_dependencies["email_service"].send_email.assert_not_called()
|
||||
|
||||
def test_send_email_register_mail_task_exception_handling(self, db_session_with_containers, mock_mail_dependencies):
|
||||
"""Test email registration task exception handling."""
|
||||
mock_mail_dependencies["email_service"].send_email.side_effect = Exception("Email service error")
|
||||
|
||||
fake = Faker()
|
||||
to_email = fake.email()
|
||||
code = fake.numerify("######")
|
||||
|
||||
with patch("tasks.mail_register_task.logger") as mock_logger:
|
||||
send_email_register_mail_task(language="en-US", to=to_email, code=code)
|
||||
mock_logger.exception.assert_called_once_with("Send email register mail to %s failed", to_email)
|
||||
|
||||
def test_send_email_register_mail_task_when_account_exist_success(
|
||||
self, db_session_with_containers, mock_mail_dependencies
|
||||
):
|
||||
"""Test successful email registration mail sending when account exists."""
|
||||
fake = Faker()
|
||||
language = "en-US"
|
||||
to_email = fake.email()
|
||||
account_name = fake.name()
|
||||
|
||||
with patch("tasks.mail_register_task.dify_config") as mock_config:
|
||||
mock_config.CONSOLE_WEB_URL = "https://console.dify.ai"
|
||||
|
||||
send_email_register_mail_task_when_account_exist(language=language, to=to_email, account_name=account_name)
|
||||
|
||||
mock_mail_dependencies["email_service"].send_email.assert_called_once_with(
|
||||
email_type=EmailType.EMAIL_REGISTER_WHEN_ACCOUNT_EXIST,
|
||||
language_code=language,
|
||||
to=to_email,
|
||||
template_context={
|
||||
"to": to_email,
|
||||
"login_url": "https://console.dify.ai/signin",
|
||||
"reset_password_url": "https://console.dify.ai/reset-password",
|
||||
"account_name": account_name,
|
||||
},
|
||||
)
|
||||
|
||||
def test_send_email_register_mail_task_when_account_exist_mail_not_initialized(
|
||||
self, db_session_with_containers, mock_mail_dependencies
|
||||
):
|
||||
"""Test account exist email task when mail service is not initialized."""
|
||||
mock_mail_dependencies["mail"].is_inited.return_value = False
|
||||
|
||||
send_email_register_mail_task_when_account_exist(
|
||||
language="en-US", to="test@example.com", account_name="Test User"
|
||||
)
|
||||
|
||||
mock_mail_dependencies["get_email_service"].assert_not_called()
|
||||
mock_mail_dependencies["email_service"].send_email.assert_not_called()
|
||||
|
||||
def test_send_email_register_mail_task_when_account_exist_exception_handling(
|
||||
self, db_session_with_containers, mock_mail_dependencies
|
||||
):
|
||||
"""Test account exist email task exception handling."""
|
||||
mock_mail_dependencies["email_service"].send_email.side_effect = Exception("Email service error")
|
||||
|
||||
fake = Faker()
|
||||
to_email = fake.email()
|
||||
account_name = fake.name()
|
||||
|
||||
with patch("tasks.mail_register_task.logger") as mock_logger:
|
||||
send_email_register_mail_task_when_account_exist(language="en-US", to=to_email, account_name=account_name)
|
||||
mock_logger.exception.assert_called_once_with("Send email register mail to %s failed", to_email)
|
||||
Reference in New Issue
Block a user