| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- from unittest.mock import patch
- import pytest
- from faker import Faker
- from constants.model_template import default_app_templates
- from models.model import App, Site
- from services.account_service import AccountService, TenantService
- from services.app_service import AppService
- class TestAppService:
- """Integration tests for AppService using testcontainers."""
- @pytest.fixture
- def mock_external_service_dependencies(self):
- """Mock setup for external service dependencies."""
- with (
- patch("services.app_service.FeatureService") as mock_feature_service,
- patch("services.app_service.EnterpriseService") as mock_enterprise_service,
- patch("services.app_service.ModelManager") as mock_model_manager,
- patch("services.account_service.FeatureService") as mock_account_feature_service,
- ):
- # Setup default mock returns for app service
- mock_feature_service.get_system_features.return_value.webapp_auth.enabled = False
- mock_enterprise_service.WebAppAuth.update_app_access_mode.return_value = None
- mock_enterprise_service.WebAppAuth.cleanup_webapp.return_value = None
- # Setup default mock returns for account service
- mock_account_feature_service.get_system_features.return_value.is_allow_register = True
- # Mock ModelManager for model configuration
- mock_model_instance = mock_model_manager.return_value
- mock_model_instance.get_default_model_instance.return_value = None
- mock_model_instance.get_default_provider_model_name.return_value = ("openai", "gpt-3.5-turbo")
- yield {
- "feature_service": mock_feature_service,
- "enterprise_service": mock_enterprise_service,
- "model_manager": mock_model_manager,
- "account_feature_service": mock_account_feature_service,
- }
- def test_create_app_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app creation with basic parameters.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Setup app creation arguments
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🤖",
- "icon_background": "#FF6B6B",
- "api_rph": 100,
- "api_rpm": 10,
- }
- # Create app
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Verify app was created correctly
- assert app.name == app_args["name"]
- assert app.description == app_args["description"]
- assert app.mode == app_args["mode"]
- assert app.icon_type == app_args["icon_type"]
- assert app.icon == app_args["icon"]
- assert app.icon_background == app_args["icon_background"]
- assert app.tenant_id == tenant.id
- assert app.api_rph == app_args["api_rph"]
- assert app.api_rpm == app_args["api_rpm"]
- assert app.created_by == account.id
- assert app.updated_by == account.id
- assert app.status == "normal"
- assert app.enable_site is True
- assert app.enable_api is True
- assert app.is_demo is False
- assert app.is_public is False
- assert app.is_universal is False
- def test_create_app_with_different_modes(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test app creation with different app modes.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- app_service = AppService()
- # Test different app modes
- # from AppMode enum in default_app_model_template
- app_modes = [v.value for v in default_app_templates]
- for mode in app_modes:
- app_args = {
- "name": f"{fake.company()} {mode}",
- "description": f"Test app for {mode} mode",
- "mode": mode,
- "icon_type": "emoji",
- "icon": "🚀",
- "icon_background": "#4ECDC4",
- }
- app = app_service.create_app(tenant.id, app_args, account)
- # Verify app mode was set correctly
- assert app.mode == mode
- assert app.name == app_args["name"]
- assert app.tenant_id == tenant.id
- assert app.created_by == account.id
- def test_get_app_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app retrieval.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🎯",
- "icon_background": "#45B7D1",
- }
- app_service = AppService()
- created_app = app_service.create_app(tenant.id, app_args, account)
- # Get app using the service
- retrieved_app = app_service.get_app(created_app)
- # Verify retrieved app matches created app
- assert retrieved_app.id == created_app.id
- assert retrieved_app.name == created_app.name
- assert retrieved_app.description == created_app.description
- assert retrieved_app.mode == created_app.mode
- assert retrieved_app.tenant_id == created_app.tenant_id
- assert retrieved_app.created_by == created_app.created_by
- def test_get_paginate_apps_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful paginated app list retrieval.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- app_service = AppService()
- # Create multiple apps
- app_names = [fake.company() for _ in range(5)]
- for name in app_names:
- app_args = {
- "name": name,
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "📱",
- "icon_background": "#96CEB4",
- }
- app_service.create_app(tenant.id, app_args, account)
- # Get paginated apps
- args = {
- "page": 1,
- "limit": 10,
- "mode": "chat",
- }
- paginated_apps = app_service.get_paginate_apps(account.id, tenant.id, args)
- # Verify pagination results
- assert paginated_apps is not None
- assert len(paginated_apps.items) >= 5 # Should have at least 5 apps
- assert paginated_apps.page == 1
- assert paginated_apps.per_page == 10
- # Verify all apps belong to the correct tenant
- for app in paginated_apps.items:
- assert app.tenant_id == tenant.id
- assert app.mode == "chat"
- def test_get_paginate_apps_with_filters(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test paginated app list with various filters.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- app_service = AppService()
- # Create apps with different modes
- chat_app_args = {
- "name": "Chat App",
- "description": "A chat application",
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "💬",
- "icon_background": "#FF6B6B",
- }
- completion_app_args = {
- "name": "Completion App",
- "description": "A completion application",
- "mode": "completion",
- "icon_type": "emoji",
- "icon": "✍️",
- "icon_background": "#4ECDC4",
- }
- chat_app = app_service.create_app(tenant.id, chat_app_args, account)
- completion_app = app_service.create_app(tenant.id, completion_app_args, account)
- # Test filter by mode
- chat_args = {
- "page": 1,
- "limit": 10,
- "mode": "chat",
- }
- chat_apps = app_service.get_paginate_apps(account.id, tenant.id, chat_args)
- assert len(chat_apps.items) == 1
- assert chat_apps.items[0].mode == "chat"
- # Test filter by name
- name_args = {
- "page": 1,
- "limit": 10,
- "mode": "chat",
- "name": "Chat",
- }
- filtered_apps = app_service.get_paginate_apps(account.id, tenant.id, name_args)
- assert len(filtered_apps.items) == 1
- assert "Chat" in filtered_apps.items[0].name
- # Test filter by created_by_me
- created_by_me_args = {
- "page": 1,
- "limit": 10,
- "mode": "completion",
- "is_created_by_me": True,
- }
- my_apps = app_service.get_paginate_apps(account.id, tenant.id, created_by_me_args)
- assert len(my_apps.items) == 1
- def test_get_paginate_apps_with_tag_filters(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test paginated app list with tag filters.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- app_service = AppService()
- # Create an app
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🏷️",
- "icon_background": "#FFEAA7",
- }
- app = app_service.create_app(tenant.id, app_args, account)
- # Mock TagService to return the app ID for tag filtering
- with patch("services.app_service.TagService.get_target_ids_by_tag_ids") as mock_tag_service:
- mock_tag_service.return_value = [app.id]
- # Test with tag filter
- args = {
- "page": 1,
- "limit": 10,
- "mode": "chat",
- "tag_ids": ["tag1", "tag2"],
- }
- paginated_apps = app_service.get_paginate_apps(account.id, tenant.id, args)
- # Verify tag service was called
- mock_tag_service.assert_called_once_with("app", tenant.id, ["tag1", "tag2"])
- # Verify results
- assert paginated_apps is not None
- assert len(paginated_apps.items) == 1
- assert paginated_apps.items[0].id == app.id
- # Test with tag filter that returns no results
- with patch("services.app_service.TagService.get_target_ids_by_tag_ids") as mock_tag_service:
- mock_tag_service.return_value = []
- args = {
- "page": 1,
- "limit": 10,
- "mode": "chat",
- "tag_ids": ["nonexistent_tag"],
- }
- paginated_apps = app_service.get_paginate_apps(account.id, tenant.id, args)
- # Should return None when no apps match tag filter
- assert paginated_apps is None
- def test_update_app_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app update with all fields.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🎯",
- "icon_background": "#45B7D1",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store original values
- original_name = app.name
- original_description = app.description
- original_icon = app.icon
- original_icon_background = app.icon_background
- original_use_icon_as_answer_icon = app.use_icon_as_answer_icon
- # Update app
- update_args = {
- "name": "Updated App Name",
- "description": "Updated app description",
- "icon_type": "emoji",
- "icon": "🔄",
- "icon_background": "#FF8C42",
- "use_icon_as_answer_icon": True,
- }
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app(app, update_args)
- # Verify updated fields
- assert updated_app.name == update_args["name"]
- assert updated_app.description == update_args["description"]
- assert updated_app.icon == update_args["icon"]
- assert updated_app.icon_background == update_args["icon_background"]
- assert updated_app.use_icon_as_answer_icon is True
- assert updated_app.updated_by == account.id
- # Verify other fields remain unchanged
- assert updated_app.mode == app.mode
- assert updated_app.tenant_id == app.tenant_id
- assert updated_app.created_by == app.created_by
- def test_update_app_name_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app name update.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🎯",
- "icon_background": "#45B7D1",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store original name
- original_name = app.name
- # Update app name
- new_name = "New App Name"
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app_name(app, new_name)
- assert updated_app.name == new_name
- assert updated_app.updated_by == account.id
- # Verify other fields remain unchanged
- assert updated_app.description == app.description
- assert updated_app.mode == app.mode
- assert updated_app.tenant_id == app.tenant_id
- assert updated_app.created_by == app.created_by
- def test_update_app_icon_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app icon update.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🎯",
- "icon_background": "#45B7D1",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store original values
- original_icon = app.icon
- original_icon_background = app.icon_background
- # Update app icon
- new_icon = "🌟"
- new_icon_background = "#FFD93D"
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app_icon(app, new_icon, new_icon_background)
- assert updated_app.icon == new_icon
- assert updated_app.icon_background == new_icon_background
- assert updated_app.updated_by == account.id
- # Verify other fields remain unchanged
- assert updated_app.name == app.name
- assert updated_app.description == app.description
- assert updated_app.mode == app.mode
- assert updated_app.tenant_id == app.tenant_id
- assert updated_app.created_by == app.created_by
- def test_update_app_site_status_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app site status update.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🌐",
- "icon_background": "#74B9FF",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store original site status
- original_site_status = app.enable_site
- # Update site status to disabled
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app_site_status(app, False)
- assert updated_app.enable_site is False
- assert updated_app.updated_by == account.id
- # Update site status back to enabled
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app_site_status(updated_app, True)
- assert updated_app.enable_site is True
- assert updated_app.updated_by == account.id
- # Verify other fields remain unchanged
- assert updated_app.name == app.name
- assert updated_app.description == app.description
- assert updated_app.mode == app.mode
- assert updated_app.tenant_id == app.tenant_id
- assert updated_app.created_by == app.created_by
- def test_update_app_api_status_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app API status update.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🔌",
- "icon_background": "#A29BFE",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store original API status
- original_api_status = app.enable_api
- # Update API status to disabled
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app_api_status(app, False)
- assert updated_app.enable_api is False
- assert updated_app.updated_by == account.id
- # Update API status back to enabled
- with patch("flask_login.utils._get_user", return_value=account):
- updated_app = app_service.update_app_api_status(updated_app, True)
- assert updated_app.enable_api is True
- assert updated_app.updated_by == account.id
- # Verify other fields remain unchanged
- assert updated_app.name == app.name
- assert updated_app.description == app.description
- assert updated_app.mode == app.mode
- assert updated_app.tenant_id == app.tenant_id
- assert updated_app.created_by == app.created_by
- def test_update_app_site_status_no_change(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test app site status update when status doesn't change.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🔄",
- "icon_background": "#FD79A8",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store original values
- original_site_status = app.enable_site
- original_updated_at = app.updated_at
- # Update site status to the same value (no change)
- updated_app = app_service.update_app_site_status(app, original_site_status)
- # Verify app is returned unchanged
- assert updated_app.id == app.id
- assert updated_app.enable_site == original_site_status
- assert updated_app.updated_at == original_updated_at
- # Verify other fields remain unchanged
- assert updated_app.name == app.name
- assert updated_app.description == app.description
- assert updated_app.mode == app.mode
- assert updated_app.tenant_id == app.tenant_id
- assert updated_app.created_by == app.created_by
- def test_delete_app_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app deletion.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🗑️",
- "icon_background": "#E17055",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store app ID for verification
- app_id = app.id
- # Mock the async deletion task
- with patch("services.app_service.remove_app_and_related_data_task") as mock_delete_task:
- mock_delete_task.delay.return_value = None
- # Delete app
- app_service.delete_app(app)
- # Verify async deletion task was called
- mock_delete_task.delay.assert_called_once_with(tenant_id=tenant.id, app_id=app_id)
- # Verify app was deleted from database
- from extensions.ext_database import db
- deleted_app = db.session.query(App).filter_by(id=app_id).first()
- assert deleted_app is None
- def test_delete_app_with_related_data(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test app deletion with related data cleanup.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🧹",
- "icon_background": "#00B894",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Store app ID for verification
- app_id = app.id
- # Mock webapp auth cleanup
- mock_external_service_dependencies[
- "feature_service"
- ].get_system_features.return_value.webapp_auth.enabled = True
- # Mock the async deletion task
- with patch("services.app_service.remove_app_and_related_data_task") as mock_delete_task:
- mock_delete_task.delay.return_value = None
- # Delete app
- app_service.delete_app(app)
- # Verify webapp auth cleanup was called
- mock_external_service_dependencies["enterprise_service"].WebAppAuth.cleanup_webapp.assert_called_once_with(
- app_id
- )
- # Verify async deletion task was called
- mock_delete_task.delay.assert_called_once_with(tenant_id=tenant.id, app_id=app_id)
- # Verify app was deleted from database
- from extensions.ext_database import db
- deleted_app = db.session.query(App).filter_by(id=app_id).first()
- assert deleted_app is None
- def test_get_app_meta_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app metadata retrieval.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "📊",
- "icon_background": "#6C5CE7",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Get app metadata
- app_meta = app_service.get_app_meta(app)
- # Verify metadata contains expected fields
- assert "tool_icons" in app_meta
- # Note: get_app_meta currently only returns tool_icons
- def test_get_app_code_by_id_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app code retrieval by app ID.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🔗",
- "icon_background": "#FDCB6E",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Get app code by ID
- app_code = AppService.get_app_code_by_id(app.id)
- # Verify app code was retrieved correctly
- # Note: Site would be created when App is created, site.code is auto-generated
- assert app_code is not None
- assert len(app_code) > 0
- def test_get_app_id_by_code_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful app ID retrieval by app code.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Create app first
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "chat",
- "icon_type": "emoji",
- "icon": "🆔",
- "icon_background": "#E84393",
- }
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Create a site for the app
- site = Site()
- site.app_id = app.id
- site.code = fake.postalcode()
- site.title = fake.company()
- site.status = "normal"
- site.default_language = "en-US"
- site.customize_token_strategy = "uuid"
- from extensions.ext_database import db
- db.session.add(site)
- db.session.commit()
- # Get app ID by code
- app_id = AppService.get_app_id_by_code(site.code)
- # Verify app ID was retrieved correctly
- assert app_id == app.id
- def test_create_app_invalid_mode(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test app creation with invalid mode.
- """
- fake = Faker()
- # Create account and tenant first
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Setup app creation arguments with invalid mode
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "invalid_mode", # Invalid mode
- "icon_type": "emoji",
- "icon": "❌",
- "icon_background": "#D63031",
- }
- app_service = AppService()
- # Attempt to create app with invalid mode
- with pytest.raises(ValueError, match="invalid mode value"):
- app_service.create_app(tenant.id, app_args, account)
|