mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:32:01 +08:00
chore: add type to test (#36324)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
59e96fbb2a
commit
76bba64b79
@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from sqlalchemy import delete
|
||||
from sqlalchemy.orm import Session
|
||||
@ -126,7 +127,7 @@ class TestAppApiKeyResource:
|
||||
|
||||
def test_delete_forbidden_for_non_admin(
|
||||
self,
|
||||
flask_app_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
) -> None:
|
||||
"""A non-admin member cannot delete API keys via the controller permission check."""
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
||||
@ -575,7 +575,7 @@ class TestTriggerSubscriptionVerifyApi:
|
||||
assert method(api, "github", "s1") == {"ok": True}
|
||||
|
||||
@pytest.mark.parametrize("raised_exception", [ValueError("bad"), Exception("boom")])
|
||||
def test_verify_errors(self, app, raised_exception):
|
||||
def test_verify_errors(self, app: Flask, raised_exception):
|
||||
api = TriggerSubscriptionVerifyApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -277,7 +277,7 @@ class TestDecodeJwtToken:
|
||||
mock_extract: MagicMock,
|
||||
mock_passport_cls: MagicMock,
|
||||
mock_features: MagicMock,
|
||||
app,
|
||||
app: Flask,
|
||||
) -> None:
|
||||
non_existent_id = str(uuid4())
|
||||
mock_extract.return_value = "jwt-token"
|
||||
|
||||
@ -5,6 +5,7 @@ from unittest.mock import Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from models.source import DataSourceApiKeyAuthBinding
|
||||
@ -45,7 +46,7 @@ class TestApiKeyAuthService:
|
||||
return binding
|
||||
|
||||
def test_get_provider_auth_list_success(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, category, provider
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id, category, provider
|
||||
):
|
||||
self._create_binding(db_session_with_containers, tenant_id=tenant_id, category=category, provider=provider)
|
||||
db_session_with_containers.expire_all()
|
||||
@ -58,7 +59,7 @@ class TestApiKeyAuthService:
|
||||
assert tenant_results[0].provider == provider
|
||||
|
||||
def test_get_provider_auth_list_empty(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id
|
||||
):
|
||||
result = ApiKeyAuthService.get_provider_auth_list(tenant_id)
|
||||
|
||||
@ -66,7 +67,7 @@ class TestApiKeyAuthService:
|
||||
assert tenant_results == []
|
||||
|
||||
def test_get_provider_auth_list_filters_disabled(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, category, provider
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id, category, provider
|
||||
):
|
||||
self._create_binding(
|
||||
db_session_with_containers, tenant_id=tenant_id, category=category, provider=provider, disabled=True
|
||||
@ -84,7 +85,7 @@ class TestApiKeyAuthService:
|
||||
self,
|
||||
mock_encrypter,
|
||||
mock_factory,
|
||||
flask_app_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id,
|
||||
mock_args,
|
||||
@ -106,7 +107,7 @@ class TestApiKeyAuthService:
|
||||
|
||||
@patch("services.auth.api_key_auth_service.ApiKeyAuthFactory")
|
||||
def test_create_provider_auth_validation_failed(
|
||||
self, mock_factory, flask_app_with_containers, db_session_with_containers: Session, tenant_id, mock_args
|
||||
self, mock_factory, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id, mock_args
|
||||
):
|
||||
mock_auth_instance = Mock()
|
||||
mock_auth_instance.validate_credentials.return_value = False
|
||||
@ -124,7 +125,7 @@ class TestApiKeyAuthService:
|
||||
self,
|
||||
mock_encrypter,
|
||||
mock_factory,
|
||||
flask_app_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id,
|
||||
mock_args,
|
||||
@ -144,7 +145,7 @@ class TestApiKeyAuthService:
|
||||
|
||||
def test_get_auth_credentials_success(
|
||||
self,
|
||||
flask_app_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id,
|
||||
category,
|
||||
@ -165,14 +166,14 @@ class TestApiKeyAuthService:
|
||||
assert result == mock_credentials
|
||||
|
||||
def test_get_auth_credentials_not_found(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, category, provider
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id, category, provider
|
||||
):
|
||||
result = ApiKeyAuthService.get_auth_credentials(tenant_id, category, provider)
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_get_auth_credentials_json_parsing(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, category, provider
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id, category, provider
|
||||
):
|
||||
special_credentials = {"auth_type": "api_key", "config": {"api_key": "key_with_中文_and_special_chars_!@#$%"}}
|
||||
self._create_binding(
|
||||
@ -190,7 +191,7 @@ class TestApiKeyAuthService:
|
||||
assert result["config"]["api_key"] == "key_with_中文_and_special_chars_!@#$%"
|
||||
|
||||
def test_delete_provider_auth_success(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, category, provider
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id, category, provider
|
||||
):
|
||||
binding = self._create_binding(
|
||||
db_session_with_containers, tenant_id=tenant_id, category=category, provider=provider
|
||||
@ -205,7 +206,7 @@ class TestApiKeyAuthService:
|
||||
assert remaining is None
|
||||
|
||||
def test_delete_provider_auth_not_found(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id
|
||||
):
|
||||
# Should not raise when binding not found
|
||||
ApiKeyAuthService.delete_provider_auth(tenant_id, str(uuid4()))
|
||||
@ -275,7 +276,7 @@ class TestApiKeyAuthService:
|
||||
@patch("services.auth.api_key_auth_service.ApiKeyAuthFactory")
|
||||
@patch("services.auth.api_key_auth_service.encrypter")
|
||||
def test_create_provider_auth_database_error_handling(
|
||||
self, mock_encrypter, mock_factory, flask_app_with_containers, tenant_id, mock_args
|
||||
self, mock_encrypter, mock_factory, flask_app_with_containers: Flask, tenant_id, mock_args
|
||||
):
|
||||
mock_auth_instance = Mock()
|
||||
mock_auth_instance.validate_credentials.return_value = True
|
||||
|
||||
@ -10,6 +10,7 @@ from uuid import uuid4
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from models.source import DataSourceApiKeyAuthBinding
|
||||
@ -45,8 +46,8 @@ class TestAuthIntegration:
|
||||
self,
|
||||
mock_encrypt,
|
||||
mock_http,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id_1,
|
||||
category,
|
||||
firecrawl_credentials,
|
||||
@ -86,8 +87,8 @@ class TestAuthIntegration:
|
||||
mock_jina_http,
|
||||
mock_fc_http,
|
||||
mock_encrypt,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id_1,
|
||||
tenant_id_2,
|
||||
category,
|
||||
@ -115,7 +116,7 @@ class TestAuthIntegration:
|
||||
assert result2[0].tenant_id == tenant_id_2
|
||||
|
||||
def test_cross_tenant_access_prevention(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id_2, category
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, tenant_id_2, category
|
||||
):
|
||||
result = ApiKeyAuthService.get_auth_credentials(tenant_id_2, category, AuthType.FIRECRAWL)
|
||||
|
||||
@ -139,8 +140,8 @@ class TestAuthIntegration:
|
||||
self,
|
||||
mock_encrypt,
|
||||
mock_http,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id_1,
|
||||
category,
|
||||
firecrawl_credentials,
|
||||
@ -201,8 +202,8 @@ class TestAuthIntegration:
|
||||
def test_network_failure_recovery(
|
||||
self,
|
||||
mock_http,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id_1,
|
||||
category,
|
||||
firecrawl_credentials,
|
||||
@ -239,8 +240,8 @@ class TestAuthIntegration:
|
||||
self,
|
||||
mock_http,
|
||||
mock_encrypt,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id_1,
|
||||
category,
|
||||
firecrawl_credentials,
|
||||
|
||||
@ -14,7 +14,7 @@ from sqlalchemy.orm import Session
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from core.rag.index_processor.constant.index_type import IndexTechniqueType
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models import Account, AccountStatus, Tenant, TenantAccountJoin, TenantAccountRole, TenantStatus
|
||||
from models.dataset import AppDatasetJoin, Dataset, DatasetPermissionEnum
|
||||
from models.enums import DataSourceType
|
||||
from models.model import App
|
||||
@ -38,13 +38,13 @@ class DatasetUpdateDeleteTestDataFactory:
|
||||
email=f"{uuid4()}@example.com",
|
||||
name=f"user-{uuid4()}",
|
||||
interface_language="en-US",
|
||||
status="active",
|
||||
status=AccountStatus.ACTIVE,
|
||||
)
|
||||
db_session_with_containers.add(account)
|
||||
db_session_with_containers.commit()
|
||||
|
||||
if tenant is None:
|
||||
tenant = Tenant(name=f"tenant-{uuid4()}", status="normal")
|
||||
tenant = Tenant(name=f"tenant-{uuid4()}", status=TenantStatus.NORMAL)
|
||||
db_session_with_containers.add(tenant)
|
||||
db_session_with_containers.commit()
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from redis import RedisError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@ -123,7 +124,7 @@ class TestSyncAccountDeletion:
|
||||
mock_queue_task.assert_not_called()
|
||||
|
||||
def test_sync_account_deletion_multiple_workspaces(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, mock_queue_task
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, mock_queue_task
|
||||
):
|
||||
account_id = str(uuid4())
|
||||
tenant_ids = [str(uuid4()) for _ in range(3)]
|
||||
@ -145,7 +146,7 @@ class TestSyncAccountDeletion:
|
||||
assert queued_workspace_ids == set(tenant_ids)
|
||||
|
||||
def test_sync_account_deletion_no_workspaces(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, mock_queue_task
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, mock_queue_task
|
||||
):
|
||||
with patch("services.enterprise.account_deletion_sync.dify_config") as mock_config:
|
||||
mock_config.ENTERPRISE_ENABLED = True
|
||||
@ -156,7 +157,7 @@ class TestSyncAccountDeletion:
|
||||
mock_queue_task.assert_not_called()
|
||||
|
||||
def test_sync_account_deletion_partial_failure(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, mock_queue_task
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, mock_queue_task
|
||||
):
|
||||
account_id = str(uuid4())
|
||||
tenant_ids = [str(uuid4()) for _ in range(3)]
|
||||
@ -181,7 +182,7 @@ class TestSyncAccountDeletion:
|
||||
assert mock_queue_task.call_count == 3
|
||||
|
||||
def test_sync_account_deletion_all_failures(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, mock_queue_task
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session, mock_queue_task
|
||||
):
|
||||
account_id = str(uuid4())
|
||||
tenant_id = str(uuid4())
|
||||
|
||||
@ -11,6 +11,7 @@ from unittest.mock import MagicMock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from core.plugin.entities.plugin_daemon import CredentialType
|
||||
from models.tools import BuiltinToolProvider
|
||||
@ -49,8 +50,8 @@ class TestGetDynamicSelectOptionsTool:
|
||||
mock_tool_mgr,
|
||||
mock_encrypter_fn,
|
||||
mock_client_cls,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
provider_ctrl = MagicMock()
|
||||
@ -91,8 +92,8 @@ class TestGetDynamicSelectOptionsTool:
|
||||
self,
|
||||
mock_tool_mgr,
|
||||
mock_encrypter_fn,
|
||||
flask_app_with_containers,
|
||||
db_session_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
):
|
||||
provider_ctrl = MagicMock()
|
||||
provider_ctrl.need_credentials = True
|
||||
|
||||
@ -11,10 +11,13 @@ from unittest.mock import MagicMock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from core.plugin.entities.plugin import PluginInstallationSource
|
||||
from core.plugin.entities.plugin_daemon import PluginVerification
|
||||
from models import ProviderType
|
||||
from models.provider import Provider, ProviderCredential, TenantPreferredModelProvider
|
||||
from services.errors.plugin import PluginInstallationForbiddenError
|
||||
from services.feature_service import PluginInstallationScope
|
||||
@ -346,7 +349,7 @@ class TestUninstall:
|
||||
|
||||
@patch("services.plugin.plugin_service.PluginInstaller")
|
||||
def test_cleans_credentials_when_plugin_found(
|
||||
self, mock_installer_cls, flask_app_with_containers, db_session_with_containers
|
||||
self, mock_installer_cls, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
plugin_id = "org/myplugin"
|
||||
@ -374,7 +377,7 @@ class TestUninstall:
|
||||
pref = TenantPreferredModelProvider(
|
||||
tenant_id=tenant_id,
|
||||
provider_name=provider_name,
|
||||
preferred_provider_type="custom",
|
||||
preferred_provider_type=ProviderType.CUSTOM,
|
||||
)
|
||||
db_session_with_containers.add(pref)
|
||||
db_session_with_containers.commit()
|
||||
|
||||
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
from flask import Flask
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from models.model import App, RecommendedApp, Site
|
||||
@ -10,7 +11,7 @@ from services.recommend_app.database.database_retrieval import DatabaseRecommend
|
||||
from services.recommend_app.recommend_app_type import RecommendAppType
|
||||
|
||||
|
||||
def _create_app(db_session, *, tenant_id: str, is_public: bool = True) -> App:
|
||||
def _create_app(db_session: Session, *, tenant_id: str, is_public: bool = True) -> App:
|
||||
app = App(
|
||||
tenant_id=tenant_id,
|
||||
name=f"app-{uuid4()}",
|
||||
@ -25,7 +26,7 @@ def _create_app(db_session, *, tenant_id: str, is_public: bool = True) -> App:
|
||||
return app
|
||||
|
||||
|
||||
def _create_site(db_session, *, app_id: str) -> Site:
|
||||
def _create_site(db_session: Session, *, app_id: str) -> Site:
|
||||
site = Site(
|
||||
app_id=app_id,
|
||||
title=f"site-{uuid4()}",
|
||||
@ -95,7 +96,9 @@ class TestDatabaseRecommendAppRetrieval:
|
||||
|
||||
|
||||
class TestFetchRecommendedAppsFromDb:
|
||||
def test_returns_apps_and_sorted_categories(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_returns_apps_and_sorted_categories(
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
app1 = _create_app(db_session_with_containers, tenant_id=tenant_id)
|
||||
_create_site(db_session_with_containers, app_id=app1.id)
|
||||
@ -116,7 +119,7 @@ class TestFetchRecommendedAppsFromDb:
|
||||
assert "writing" in result["categories"]
|
||||
|
||||
def test_returns_multiple_categories_for_one_app(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
created_app = _create_app(db_session_with_containers, tenant_id=tenant_id)
|
||||
@ -139,7 +142,7 @@ class TestFetchRecommendedAppsFromDb:
|
||||
|
||||
def test_ignores_legacy_category_when_categories_are_empty(
|
||||
self,
|
||||
flask_app_with_containers,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
):
|
||||
legacy_category = f"legacy-empty-{uuid4()}"
|
||||
@ -163,7 +166,7 @@ class TestFetchRecommendedAppsFromDb:
|
||||
assert legacy_category not in result["categories"]
|
||||
|
||||
def test_falls_back_to_default_language_when_empty(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
app1 = _create_app(db_session_with_containers, tenant_id=tenant_id)
|
||||
@ -177,7 +180,7 @@ class TestFetchRecommendedAppsFromDb:
|
||||
app_ids = {r["app_id"] for r in result["recommended_apps"]}
|
||||
assert app1.id in app_ids
|
||||
|
||||
def test_skips_non_public_apps(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_skips_non_public_apps(self, flask_app_with_containers: Flask, db_session_with_containers: Session):
|
||||
tenant_id = str(uuid4())
|
||||
app1 = _create_app(db_session_with_containers, tenant_id=tenant_id, is_public=False)
|
||||
_create_site(db_session_with_containers, app_id=app1.id)
|
||||
@ -190,7 +193,7 @@ class TestFetchRecommendedAppsFromDb:
|
||||
app_ids = {r["app_id"] for r in result["recommended_apps"]}
|
||||
assert app1.id not in app_ids
|
||||
|
||||
def test_skips_apps_without_site(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_skips_apps_without_site(self, flask_app_with_containers: Flask, db_session_with_containers: Session):
|
||||
tenant_id = str(uuid4())
|
||||
app1 = _create_app(db_session_with_containers, tenant_id=tenant_id)
|
||||
_create_recommended_app(db_session_with_containers, app_id=app1.id)
|
||||
@ -204,12 +207,14 @@ class TestFetchRecommendedAppsFromDb:
|
||||
|
||||
|
||||
class TestFetchRecommendedAppDetailFromDb:
|
||||
def test_returns_none_when_not_listed(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_returns_none_when_not_listed(self, flask_app_with_containers: Flask, db_session_with_containers: Session):
|
||||
result = DatabaseRecommendAppRetrieval.fetch_recommended_app_detail_from_db(str(uuid4()))
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_returns_none_when_app_not_public(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_returns_none_when_app_not_public(
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
app1 = _create_app(db_session_with_containers, tenant_id=tenant_id, is_public=False)
|
||||
_create_recommended_app(db_session_with_containers, app_id=app1.id)
|
||||
@ -221,7 +226,9 @@ class TestFetchRecommendedAppDetailFromDb:
|
||||
assert result is None
|
||||
|
||||
@patch("services.recommend_app.database.database_retrieval.AppDslService")
|
||||
def test_returns_detail_on_success(self, mock_dsl, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_returns_detail_on_success(
|
||||
self, mock_dsl, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
app1 = _create_app(db_session_with_containers, tenant_id=tenant_id)
|
||||
_create_site(db_session_with_containers, app_id=app1.id)
|
||||
|
||||
@ -6,7 +6,7 @@ from faker import Faker
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from core.plugin.impl.exc import PluginDaemonClientSideError
|
||||
from models import Account, CreatorUserRole
|
||||
from models import Account, AppMode, CreatorUserRole
|
||||
from models.enums import ConversationFromSource, MessageFileBelongsTo
|
||||
from models.model import AppModelConfig, Conversation, EndUser, Message, MessageAgentThought
|
||||
from services.account_service import AccountService, TenantService
|
||||
@ -134,7 +134,7 @@ class TestAgentService:
|
||||
app = app_service.create_app(tenant.id, app_args, account)
|
||||
|
||||
# Update the app model config to set agent_mode for agent-chat mode
|
||||
if app.mode == "agent-chat" and app.app_model_config:
|
||||
if app.mode == AppMode.AGENT_CHAT and app.app_model_config:
|
||||
app.app_model_config.agent_mode = json.dumps({"enabled": True, "strategy": "react", "tools": []})
|
||||
|
||||
db_session_with_containers.commit()
|
||||
@ -272,7 +272,7 @@ class TestAgentService:
|
||||
tool_input=json.dumps({"dataset_tool": {"query": "test_query"}}),
|
||||
observation=json.dumps({"dataset_tool": {"results": "test_results"}}),
|
||||
tokens=30,
|
||||
created_by_role="account",
|
||||
created_by_role=CreatorUserRole.ACCOUNT,
|
||||
created_by=message.from_account_id,
|
||||
)
|
||||
db_session_with_containers.add(thought2)
|
||||
|
||||
@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import Unauthorized
|
||||
|
||||
import services.api_token_service as api_token_service_module
|
||||
@ -14,7 +15,7 @@ from services.api_token_service import ApiTokenCache, CachedApiToken
|
||||
|
||||
class TestQueryTokenFromDb:
|
||||
def test_should_return_api_token_and_cache_when_token_exists(
|
||||
self, flask_app_with_containers, db_session_with_containers
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
app_id = str(uuid4())
|
||||
@ -41,7 +42,7 @@ class TestQueryTokenFromDb:
|
||||
mock_record_usage.assert_called_once_with(token_value, "app")
|
||||
|
||||
def test_should_cache_null_and_raise_unauthorized_when_token_not_found(
|
||||
self, flask_app_with_containers, db_session_with_containers
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers
|
||||
):
|
||||
with (
|
||||
patch.object(api_token_service_module.ApiTokenCache, "set") as mock_cache_set,
|
||||
|
||||
@ -15,6 +15,7 @@ from uuid import uuid4
|
||||
from zipfile import ZipFile
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import services.file_service as file_service_module
|
||||
from extensions.storage.storage_type import StorageType
|
||||
@ -23,7 +24,7 @@ from models.model import UploadFile
|
||||
from services.file_service import FileService
|
||||
|
||||
|
||||
def _create_upload_file(db_session, *, tenant_id: str, key: str, name: str) -> UploadFile:
|
||||
def _create_upload_file(db_session: Session, *, tenant_id: str, key: str, name: str) -> UploadFile:
|
||||
upload_file = UploadFile(
|
||||
tenant_id=tenant_id,
|
||||
storage_type=StorageType.OPENDAL,
|
||||
@ -66,12 +67,12 @@ def test_build_upload_files_zip_tempfile_sanitizes_and_dedupes_names(monkeypatch
|
||||
assert zf.read("b (2).txt") == b"three"
|
||||
|
||||
|
||||
def test_get_upload_files_by_ids_returns_empty_when_no_ids(db_session_with_containers) -> None:
|
||||
def test_get_upload_files_by_ids_returns_empty_when_no_ids(db_session_with_containers: Session) -> None:
|
||||
"""Ensure empty input returns an empty mapping without hitting the database."""
|
||||
assert FileService.get_upload_files_by_ids(str(uuid4()), []) == {}
|
||||
|
||||
|
||||
def test_get_upload_files_by_ids_returns_id_keyed_mapping(db_session_with_containers) -> None:
|
||||
def test_get_upload_files_by_ids_returns_id_keyed_mapping(db_session_with_containers: Session) -> None:
|
||||
"""Ensure batch lookup returns a dict keyed by stringified UploadFile ids."""
|
||||
tenant_id = str(uuid4())
|
||||
file1 = _create_upload_file(db_session_with_containers, tenant_id=tenant_id, key="k1", name="file1.txt")
|
||||
@ -84,7 +85,7 @@ def test_get_upload_files_by_ids_returns_id_keyed_mapping(db_session_with_contai
|
||||
assert result[file2.id].id == file2.id
|
||||
|
||||
|
||||
def test_get_upload_files_by_ids_filters_by_tenant(db_session_with_containers) -> None:
|
||||
def test_get_upload_files_by_ids_filters_by_tenant(db_session_with_containers: Session) -> None:
|
||||
"""Ensure files from other tenants are not returned."""
|
||||
tenant_a = str(uuid4())
|
||||
tenant_b = str(uuid4())
|
||||
|
||||
@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@ -89,7 +90,7 @@ class TestDeliveryTestRegistry:
|
||||
with pytest.raises(DeliveryTestUnsupportedError, match="Delivery method does not support test send."):
|
||||
registry.dispatch(context=context, method=method)
|
||||
|
||||
def test_default(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_default(self, flask_app_with_containers: Flask, db_session_with_containers: Session):
|
||||
registry = DeliveryTestRegistry.default()
|
||||
assert len(registry._handlers) == 1
|
||||
assert isinstance(registry._handlers[0], EmailDeliveryTestHandler)
|
||||
@ -261,7 +262,7 @@ class TestEmailDeliveryTestHandler:
|
||||
)
|
||||
assert handler._resolve_recipients(tenant_id="t1", method=method) == ["ext@example.com"]
|
||||
|
||||
def test_resolve_recipients_member(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_resolve_recipients_member(self, flask_app_with_containers: Flask, db_session_with_containers: Session):
|
||||
tenant_id = str(uuid4())
|
||||
account = Account(name="Test User", email="member@example.com")
|
||||
db_session_with_containers.add(account)
|
||||
@ -283,7 +284,9 @@ class TestEmailDeliveryTestHandler:
|
||||
)
|
||||
assert handler._resolve_recipients(tenant_id=tenant_id, method=method) == ["member@example.com"]
|
||||
|
||||
def test_resolve_recipients_whole_workspace(self, flask_app_with_containers, db_session_with_containers: Session):
|
||||
def test_resolve_recipients_whole_workspace(
|
||||
self, flask_app_with_containers: Flask, db_session_with_containers: Session
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
account1 = Account(name="User 1", email=f"u1-{uuid4()}@example.com")
|
||||
account2 = Account(name="User 2", email=f"u2-{uuid4()}@example.com")
|
||||
|
||||
@ -4,6 +4,7 @@ from unittest.mock import Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@ -17,7 +18,7 @@ from services.entities.knowledge_entities.knowledge_entities import (
|
||||
from services.metadata_service import MetadataService
|
||||
|
||||
|
||||
def _create_dataset(db_session, *, tenant_id: str, built_in_field_enabled: bool = False) -> Dataset:
|
||||
def _create_dataset(db_session: Session, *, tenant_id: str, built_in_field_enabled: bool = False) -> Dataset:
|
||||
dataset = Dataset(
|
||||
tenant_id=tenant_id,
|
||||
name=f"dataset-{uuid4()}",
|
||||
@ -31,7 +32,9 @@ def _create_dataset(db_session, *, tenant_id: str, built_in_field_enabled: bool
|
||||
return dataset
|
||||
|
||||
|
||||
def _create_document(db_session, *, dataset_id: str, tenant_id: str, doc_metadata: dict | None = None) -> Document:
|
||||
def _create_document(
|
||||
db_session: Session, *, dataset_id: str, tenant_id: str, doc_metadata: dict | None = None
|
||||
) -> Document:
|
||||
document = Document(
|
||||
tenant_id=tenant_id,
|
||||
dataset_id=dataset_id,
|
||||
@ -66,7 +69,11 @@ class TestMetadataPartialUpdate:
|
||||
yield account
|
||||
|
||||
def test_partial_update_merges_metadata(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, mock_current_account
|
||||
self,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id: str,
|
||||
mock_current_account,
|
||||
):
|
||||
dataset = _create_dataset(db_session_with_containers, tenant_id=tenant_id)
|
||||
document = _create_document(
|
||||
@ -93,7 +100,11 @@ class TestMetadataPartialUpdate:
|
||||
assert updated_doc.doc_metadata["new_key"] == "new_value"
|
||||
|
||||
def test_full_update_replaces_metadata(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, mock_current_account
|
||||
self,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id: str,
|
||||
mock_current_account,
|
||||
):
|
||||
dataset = _create_dataset(db_session_with_containers, tenant_id=tenant_id)
|
||||
document = _create_document(
|
||||
@ -120,7 +131,12 @@ class TestMetadataPartialUpdate:
|
||||
assert "existing_key" not in updated_doc.doc_metadata
|
||||
|
||||
def test_partial_update_skips_existing_binding(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, user_id, mock_current_account
|
||||
self,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id,
|
||||
user_id,
|
||||
mock_current_account,
|
||||
):
|
||||
dataset = _create_dataset(db_session_with_containers, tenant_id=tenant_id)
|
||||
document = _create_document(
|
||||
@ -160,7 +176,11 @@ class TestMetadataPartialUpdate:
|
||||
assert len(bindings) == 1
|
||||
|
||||
def test_rollback_called_on_commit_failure(
|
||||
self, flask_app_with_containers, db_session_with_containers: Session, tenant_id, mock_current_account
|
||||
self,
|
||||
flask_app_with_containers: Flask,
|
||||
db_session_with_containers: Session,
|
||||
tenant_id: str,
|
||||
mock_current_account,
|
||||
):
|
||||
dataset = _create_dataset(db_session_with_containers, tenant_id=tenant_id)
|
||||
document = _create_document(
|
||||
|
||||
@ -6,6 +6,7 @@ from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from controllers.console.app import app_import as app_import_module
|
||||
from services.app_dsl_service import ImportStatus
|
||||
@ -48,7 +49,9 @@ class TestAppImportApi:
|
||||
def api(self):
|
||||
return app_import_module.AppImportApi()
|
||||
|
||||
def test_import_post_returns_failed_status_and_rolls_back(self, api, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_import_post_returns_failed_status_and_rolls_back(
|
||||
self, api, app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
method = _unwrap(api.post)
|
||||
|
||||
_install_features(monkeypatch, enabled=False)
|
||||
@ -68,7 +71,9 @@ class TestAppImportApi:
|
||||
assert status == 400
|
||||
assert response["status"] == ImportStatus.FAILED
|
||||
|
||||
def test_import_post_returns_pending_status_and_commits(self, api, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_import_post_returns_pending_status_and_commits(
|
||||
self, api, app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
method = _unwrap(api.post)
|
||||
|
||||
_install_features(monkeypatch, enabled=False)
|
||||
@ -88,7 +93,9 @@ class TestAppImportApi:
|
||||
assert status == 202
|
||||
assert response["status"] == ImportStatus.PENDING
|
||||
|
||||
def test_import_post_updates_webapp_auth_when_enabled(self, api, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_import_post_updates_webapp_auth_when_enabled(
|
||||
self, api, app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
method = _unwrap(api.post)
|
||||
|
||||
_install_features(monkeypatch, enabled=True)
|
||||
@ -118,7 +125,7 @@ class TestAppImportConfirmApi:
|
||||
return app_import_module.AppImportConfirmApi()
|
||||
|
||||
def test_import_confirm_returns_failed_status_and_rolls_back(
|
||||
self, api, app, monkeypatch: pytest.MonkeyPatch
|
||||
self, api, app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
method = _unwrap(api.post)
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ from datetime import UTC, datetime
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from pydantic import ValidationError
|
||||
|
||||
from controllers.console.app import conversation_variables as conversation_variables_module
|
||||
@ -20,7 +21,7 @@ def _unwrap(func):
|
||||
return func
|
||||
|
||||
|
||||
def test_get_conversation_variables_returns_paginated_response(app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_get_conversation_variables_returns_paginated_response(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
api = conversation_variables_module.ConversationVariablesApi()
|
||||
method = _unwrap(api.get)
|
||||
|
||||
@ -63,7 +64,9 @@ def test_get_conversation_variables_returns_paginated_response(app, monkeypatch:
|
||||
assert response["data"][0]["updated_at"] == int(updated_at.timestamp())
|
||||
|
||||
|
||||
def test_get_conversation_variables_normalizes_value_type_and_value(app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_get_conversation_variables_normalizes_value_type_and_value(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
api = conversation_variables_module.ConversationVariablesApi()
|
||||
method = _unwrap(api.get)
|
||||
|
||||
|
||||
@ -20,8 +20,11 @@ from models.workflow import WorkflowRun
|
||||
|
||||
|
||||
def _make_account() -> Account:
|
||||
account = Account(name="tester", email="tester@example.com")
|
||||
account.status = AccountStatus.ACTIVE
|
||||
account = Account(
|
||||
name="tester",
|
||||
email="tester@example.com",
|
||||
status=AccountStatus.ACTIVE,
|
||||
)
|
||||
account.role = TenantAccountRole.OWNER
|
||||
account.id = "account-123" # type: ignore[assignment]
|
||||
account._current_tenant = SimpleNamespace(id="tenant-123") # type: ignore[attr-defined]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Response
|
||||
from flask import Flask, Response
|
||||
|
||||
from controllers.console import console_ns
|
||||
from controllers.console.app.error import DraftWorkflowNotExist
|
||||
@ -46,7 +46,7 @@ def restx_config(app):
|
||||
|
||||
|
||||
class TestRagPipelineVariableCollectionApi:
|
||||
def test_get_variables_success(self, app, fake_db, editor_user, restx_config):
|
||||
def test_get_variables_success(self, app: Flask, fake_db, editor_user, restx_config):
|
||||
api = RagPipelineVariableCollectionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -80,7 +80,7 @@ class TestRagPipelineVariableCollectionApi:
|
||||
|
||||
assert result["items"] == []
|
||||
|
||||
def test_get_variables_workflow_not_exist(self, app, fake_db, editor_user):
|
||||
def test_get_variables_workflow_not_exist(self, app: Flask, fake_db, editor_user):
|
||||
api = RagPipelineVariableCollectionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -101,7 +101,7 @@ class TestRagPipelineVariableCollectionApi:
|
||||
with pytest.raises(DraftWorkflowNotExist):
|
||||
method(api, pipeline)
|
||||
|
||||
def test_delete_variables_success(self, app, fake_db, editor_user):
|
||||
def test_delete_variables_success(self, app: Flask, fake_db, editor_user):
|
||||
api = RagPipelineVariableCollectionApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -120,7 +120,7 @@ class TestRagPipelineVariableCollectionApi:
|
||||
|
||||
|
||||
class TestRagPipelineNodeVariableCollectionApi:
|
||||
def test_get_node_variables_success(self, app, fake_db, editor_user, restx_config):
|
||||
def test_get_node_variables_success(self, app: Flask, fake_db, editor_user, restx_config):
|
||||
api = RagPipelineNodeVariableCollectionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -146,7 +146,7 @@ class TestRagPipelineNodeVariableCollectionApi:
|
||||
|
||||
assert result["items"] == []
|
||||
|
||||
def test_get_node_variables_invalid_node(self, app, editor_user):
|
||||
def test_get_node_variables_invalid_node(self, app: Flask, editor_user):
|
||||
api = RagPipelineNodeVariableCollectionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -159,7 +159,7 @@ class TestRagPipelineNodeVariableCollectionApi:
|
||||
|
||||
|
||||
class TestRagPipelineVariableApi:
|
||||
def test_get_variable_not_found(self, app, fake_db, editor_user):
|
||||
def test_get_variable_not_found(self, app: Flask, fake_db, editor_user):
|
||||
api = RagPipelineVariableApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -178,7 +178,7 @@ class TestRagPipelineVariableApi:
|
||||
with pytest.raises(NotFoundError):
|
||||
method(api, MagicMock(), "v1")
|
||||
|
||||
def test_patch_variable_invalid_file_payload(self, app, fake_db, editor_user):
|
||||
def test_patch_variable_invalid_file_payload(self, app: Flask, fake_db, editor_user):
|
||||
api = RagPipelineVariableApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -203,7 +203,7 @@ class TestRagPipelineVariableApi:
|
||||
with pytest.raises(InvalidArgumentError):
|
||||
method(api, pipeline, "v1")
|
||||
|
||||
def test_delete_variable_success(self, app, fake_db, editor_user):
|
||||
def test_delete_variable_success(self, app: Flask, fake_db, editor_user):
|
||||
api = RagPipelineVariableApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -228,7 +228,7 @@ class TestRagPipelineVariableApi:
|
||||
|
||||
|
||||
class TestRagPipelineVariableResetApi:
|
||||
def test_reset_variable_success(self, app, fake_db, editor_user):
|
||||
def test_reset_variable_success(self, app: Flask, fake_db, editor_user):
|
||||
api = RagPipelineVariableResetApi()
|
||||
method = unwrap(api.put)
|
||||
|
||||
@ -266,7 +266,7 @@ class TestRagPipelineVariableResetApi:
|
||||
|
||||
|
||||
class TestSystemAndEnvironmentVariablesApi:
|
||||
def test_system_variables_success(self, app, fake_db, editor_user, restx_config):
|
||||
def test_system_variables_success(self, app: Flask, fake_db, editor_user, restx_config):
|
||||
api = RagPipelineSystemVariableCollectionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -292,7 +292,7 @@ class TestSystemAndEnvironmentVariablesApi:
|
||||
|
||||
assert result["items"] == []
|
||||
|
||||
def test_environment_variables_success(self, app, editor_user):
|
||||
def test_environment_variables_success(self, app: Flask, editor_user):
|
||||
api = RagPipelineEnvironmentVariableCollectionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ def patch_permission():
|
||||
|
||||
|
||||
class TestGetProcessRuleApi:
|
||||
def test_get_default_success(self, app, patch_tenant):
|
||||
def test_get_default_success(self, app: Flask, patch_tenant):
|
||||
api = GetProcessRuleApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -104,7 +104,7 @@ class TestGetProcessRuleApi:
|
||||
|
||||
assert "rules" in response
|
||||
|
||||
def test_get_with_document_dataset_not_found(self, app, patch_tenant):
|
||||
def test_get_with_document_dataset_not_found(self, app: Flask, patch_tenant):
|
||||
api = GetProcessRuleApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -126,7 +126,7 @@ class TestGetProcessRuleApi:
|
||||
|
||||
|
||||
class TestDatasetDocumentListApi:
|
||||
def test_get_with_fetch_true_counts_segments(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_get_with_fetch_true_counts_segments(self, app: Flask, patch_tenant, patch_dataset, patch_permission):
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -158,7 +158,9 @@ class TestDatasetDocumentListApi:
|
||||
|
||||
assert resp["data"]
|
||||
|
||||
def test_get_with_search_status_and_created_at_sort(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_get_with_search_status_and_created_at_sort(
|
||||
self, app: Flask, patch_tenant, patch_dataset, patch_permission
|
||||
):
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -187,7 +189,7 @@ class TestDatasetDocumentListApi:
|
||||
|
||||
assert resp["total"] == 1
|
||||
|
||||
def test_get_success(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_get_success(self, app: Flask, patch_tenant, patch_dataset, patch_permission):
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -212,7 +214,7 @@ class TestDatasetDocumentListApi:
|
||||
|
||||
assert response["total"] == 1
|
||||
|
||||
def test_post_success(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_post_success(self, app: Flask, patch_tenant, patch_dataset, patch_permission):
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -261,7 +263,7 @@ class TestDatasetDocumentListApi:
|
||||
with pytest.raises(Forbidden):
|
||||
method(api, "ds-1")
|
||||
|
||||
def test_get_with_fetch_true_and_invalid_fetch(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_get_with_fetch_true_and_invalid_fetch(self, app: Flask, patch_tenant, patch_dataset, patch_permission):
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -286,7 +288,7 @@ class TestDatasetDocumentListApi:
|
||||
|
||||
assert response["total"] == 1
|
||||
|
||||
def test_get_sort_hit_count(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_get_sort_hit_count(self, app: Flask, patch_tenant, patch_dataset, patch_permission):
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -309,7 +311,7 @@ class TestDatasetDocumentListApi:
|
||||
|
||||
|
||||
class TestDocumentApi:
|
||||
def test_get_success(self, app, patch_tenant):
|
||||
def test_get_success(self, app: Flask, patch_tenant):
|
||||
api = DocumentApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -327,7 +329,7 @@ class TestDocumentApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_get_invalid_metadata(self, app, patch_tenant):
|
||||
def test_get_invalid_metadata(self, app: Flask, patch_tenant):
|
||||
api = DocumentApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -335,7 +337,7 @@ class TestDocumentApi:
|
||||
with pytest.raises(InvalidMetadataError):
|
||||
method(api, "ds-1", "doc-1")
|
||||
|
||||
def test_delete_success(self, app, patch_tenant, patch_dataset):
|
||||
def test_delete_success(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -355,7 +357,7 @@ class TestDocumentApi:
|
||||
|
||||
assert status == 204
|
||||
|
||||
def test_delete_indexing_error(self, app, patch_tenant, patch_dataset):
|
||||
def test_delete_indexing_error(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -376,7 +378,7 @@ class TestDocumentApi:
|
||||
|
||||
|
||||
class TestDocumentDownloadApi:
|
||||
def test_download_success(self, app, patch_tenant):
|
||||
def test_download_success(self, app: Flask, patch_tenant):
|
||||
api = DocumentDownloadApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -413,7 +415,7 @@ class TestDocumentProcessingApi:
|
||||
with pytest.raises(Forbidden):
|
||||
method(api, "ds-1", "doc-1", "pause")
|
||||
|
||||
def test_resume_from_error_state(self, app, patch_tenant):
|
||||
def test_resume_from_error_state(self, app: Flask, patch_tenant):
|
||||
api = DocumentProcessingApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -431,7 +433,7 @@ class TestDocumentProcessingApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_resume_success(self, app, patch_tenant):
|
||||
def test_resume_success(self, app: Flask, patch_tenant):
|
||||
api = DocumentProcessingApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -449,7 +451,7 @@ class TestDocumentProcessingApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_pause_success(self, app, patch_tenant):
|
||||
def test_pause_success(self, app: Flask, patch_tenant):
|
||||
api = DocumentProcessingApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -467,7 +469,7 @@ class TestDocumentProcessingApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_pause_invalid(self, app, patch_tenant):
|
||||
def test_pause_invalid(self, app: Flask, patch_tenant):
|
||||
api = DocumentProcessingApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -479,7 +481,7 @@ class TestDocumentProcessingApi:
|
||||
|
||||
|
||||
class TestDocumentMetadataApi:
|
||||
def test_put_metadata_schema_filtering(self, app, patch_tenant):
|
||||
def test_put_metadata_schema_filtering(self, app: Flask, patch_tenant):
|
||||
api = DocumentMetadataApi()
|
||||
method = unwrap(api.put)
|
||||
|
||||
@ -508,7 +510,7 @@ class TestDocumentMetadataApi:
|
||||
|
||||
assert doc.doc_metadata == {"amount": 10}
|
||||
|
||||
def test_put_success(self, app, patch_tenant):
|
||||
def test_put_success(self, app: Flask, patch_tenant):
|
||||
api = DocumentMetadataApi()
|
||||
method = unwrap(api.put)
|
||||
|
||||
@ -532,7 +534,7 @@ class TestDocumentMetadataApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_put_invalid_payload(self, app, patch_tenant):
|
||||
def test_put_invalid_payload(self, app: Flask, patch_tenant):
|
||||
api = DocumentMetadataApi()
|
||||
method = unwrap(api.put)
|
||||
|
||||
@ -540,7 +542,7 @@ class TestDocumentMetadataApi:
|
||||
with pytest.raises(ValueError):
|
||||
method(api, "ds-1", "doc-1")
|
||||
|
||||
def test_put_invalid_doc_type(self, app, patch_tenant):
|
||||
def test_put_invalid_doc_type(self, app: Flask, patch_tenant):
|
||||
api = DocumentMetadataApi()
|
||||
method = unwrap(api.put)
|
||||
|
||||
@ -559,7 +561,7 @@ class TestDocumentMetadataApi:
|
||||
|
||||
|
||||
class TestDocumentStatusApi:
|
||||
def test_patch_success(self, app, patch_tenant, patch_dataset):
|
||||
def test_patch_success(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentStatusApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -582,7 +584,7 @@ class TestDocumentStatusApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_patch_invalid_action(self, app, patch_tenant, patch_dataset):
|
||||
def test_patch_invalid_action(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentStatusApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -606,7 +608,7 @@ class TestDocumentStatusApi:
|
||||
|
||||
|
||||
class TestDocumentRetryApi:
|
||||
def test_retry_archived_document_skipped(self, app, patch_tenant, patch_dataset):
|
||||
def test_retry_archived_document_skipped(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentRetryApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -634,7 +636,7 @@ class TestDocumentRetryApi:
|
||||
assert status == 204
|
||||
retry_mock.assert_called_once_with("ds-1", [])
|
||||
|
||||
def test_retry_success(self, app, patch_tenant, patch_dataset):
|
||||
def test_retry_success(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentRetryApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -663,7 +665,7 @@ class TestDocumentRetryApi:
|
||||
assert status == 204
|
||||
retry_mock.assert_called_once_with("ds-1", [document])
|
||||
|
||||
def test_retry_skips_completed_document(self, app, patch_tenant, patch_dataset):
|
||||
def test_retry_skips_completed_document(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentRetryApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -690,7 +692,7 @@ class TestDocumentRetryApi:
|
||||
|
||||
|
||||
class TestDocumentPipelineExecutionLogApi:
|
||||
def test_get_log_success(self, app, patch_tenant, patch_dataset):
|
||||
def test_get_log_success(self, app: Flask, patch_tenant, patch_dataset):
|
||||
api = DocumentPipelineExecutionLogApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -718,7 +720,7 @@ class TestDocumentPipelineExecutionLogApi:
|
||||
|
||||
|
||||
class TestDocumentGenerateSummaryApi:
|
||||
def test_generate_summary_missing_documents(self, app, patch_tenant, patch_permission):
|
||||
def test_generate_summary_missing_documents(self, app: Flask, patch_tenant, patch_permission):
|
||||
api = DocumentGenerateSummaryApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -744,7 +746,7 @@ class TestDocumentGenerateSummaryApi:
|
||||
with pytest.raises(NotFound):
|
||||
method(api, "ds-1")
|
||||
|
||||
def test_generate_not_enabled(self, app, patch_tenant, patch_permission):
|
||||
def test_generate_not_enabled(self, app: Flask, patch_tenant, patch_permission):
|
||||
api = DocumentGenerateSummaryApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -763,7 +765,7 @@ class TestDocumentGenerateSummaryApi:
|
||||
with pytest.raises(ValueError):
|
||||
method(api, "ds-1")
|
||||
|
||||
def test_generate_summary_success_with_qa_skip(self, app, patch_tenant, patch_permission):
|
||||
def test_generate_summary_success_with_qa_skip(self, app: Flask, patch_tenant, patch_permission):
|
||||
api = DocumentGenerateSummaryApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -799,7 +801,7 @@ class TestDocumentGenerateSummaryApi:
|
||||
|
||||
|
||||
class TestDocumentSummaryStatusApi:
|
||||
def test_get_success(self, app, patch_tenant, patch_permission):
|
||||
def test_get_success(self, app: Flask, patch_tenant, patch_permission):
|
||||
api = DocumentSummaryStatusApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -820,7 +822,7 @@ class TestDocumentSummaryStatusApi:
|
||||
|
||||
|
||||
class TestDocumentIndexingEstimateApi:
|
||||
def test_indexing_estimate_file_not_found(self, app, patch_tenant):
|
||||
def test_indexing_estimate_file_not_found(self, app: Flask, patch_tenant):
|
||||
api = DocumentIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -844,7 +846,7 @@ class TestDocumentIndexingEstimateApi:
|
||||
with pytest.raises(NotFound):
|
||||
method(api, "ds-1", "doc-1")
|
||||
|
||||
def test_indexing_estimate_generic_exception(self, app, patch_tenant):
|
||||
def test_indexing_estimate_generic_exception(self, app: Flask, patch_tenant):
|
||||
api = DocumentIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -881,7 +883,7 @@ class TestDocumentIndexingEstimateApi:
|
||||
with pytest.raises(IndexingEstimateError):
|
||||
method(api, "ds-1", "doc-1")
|
||||
|
||||
def test_get_finished(self, app, patch_tenant):
|
||||
def test_get_finished(self, app: Flask, patch_tenant):
|
||||
api = DocumentIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -893,7 +895,7 @@ class TestDocumentIndexingEstimateApi:
|
||||
|
||||
|
||||
class TestDocumentBatchDownloadZipApi:
|
||||
def test_post_no_documents(self, app, patch_tenant):
|
||||
def test_post_no_documents(self, app: Flask, patch_tenant):
|
||||
api = DocumentBatchDownloadZipApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -905,7 +907,7 @@ class TestDocumentBatchDownloadZipApi:
|
||||
|
||||
|
||||
class TestDatasetDocumentListApiDelete:
|
||||
def test_delete_success(self, app, patch_tenant, patch_dataset):
|
||||
def test_delete_success(self, app: Flask, patch_tenant, patch_dataset):
|
||||
"""Test successful deletion of documents"""
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.delete)
|
||||
@ -925,7 +927,7 @@ class TestDatasetDocumentListApiDelete:
|
||||
|
||||
assert status == 204
|
||||
|
||||
def test_delete_indexing_error(self, app, patch_tenant, patch_dataset):
|
||||
def test_delete_indexing_error(self, app: Flask, patch_tenant, patch_dataset):
|
||||
"""Test deletion with indexing error"""
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.delete)
|
||||
@ -944,7 +946,7 @@ class TestDatasetDocumentListApiDelete:
|
||||
with pytest.raises(DocumentIndexingError):
|
||||
method(api, "ds-1")
|
||||
|
||||
def test_delete_dataset_not_found(self, app, patch_tenant):
|
||||
def test_delete_dataset_not_found(self, app: Flask, patch_tenant):
|
||||
"""Test deletion when dataset not found"""
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.delete)
|
||||
@ -961,7 +963,7 @@ class TestDatasetDocumentListApiDelete:
|
||||
|
||||
|
||||
class TestDocumentBatchIndexingEstimateApi:
|
||||
def test_batch_indexing_estimate_website(self, app, patch_tenant):
|
||||
def test_batch_indexing_estimate_website(self, app: Flask, patch_tenant):
|
||||
api = DocumentBatchIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -990,7 +992,7 @@ class TestDocumentBatchIndexingEstimateApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_batch_indexing_estimate_notion(self, app, patch_tenant):
|
||||
def test_batch_indexing_estimate_notion(self, app: Flask, patch_tenant):
|
||||
api = DocumentBatchIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -1018,7 +1020,7 @@ class TestDocumentBatchIndexingEstimateApi:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_batch_estimate_unsupported_datasource(self, app, patch_tenant):
|
||||
def test_batch_estimate_unsupported_datasource(self, app: Flask, patch_tenant):
|
||||
api = DocumentBatchIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -1033,7 +1035,7 @@ class TestDocumentBatchIndexingEstimateApi:
|
||||
with pytest.raises(ValueError):
|
||||
method(api, "ds-1", "batch-1")
|
||||
|
||||
def test_get_batch_estimate_invalid_batch(self, app, patch_tenant):
|
||||
def test_get_batch_estimate_invalid_batch(self, app: Flask, patch_tenant):
|
||||
"""Test batch estimation with invalid batch"""
|
||||
api = DocumentBatchIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
@ -1044,7 +1046,7 @@ class TestDocumentBatchIndexingEstimateApi:
|
||||
|
||||
|
||||
class TestDocumentBatchIndexingStatusApi:
|
||||
def test_get_batch_status_invalid_batch(self, app, patch_tenant):
|
||||
def test_get_batch_status_invalid_batch(self, app: Flask, patch_tenant):
|
||||
"""Test batch status with invalid batch"""
|
||||
api = DocumentBatchIndexingStatusApi()
|
||||
method = unwrap(api.get)
|
||||
@ -1055,7 +1057,7 @@ class TestDocumentBatchIndexingStatusApi:
|
||||
|
||||
|
||||
class TestDocumentIndexingStatusApi:
|
||||
def test_get_status_document_not_found(self, app, patch_tenant):
|
||||
def test_get_status_document_not_found(self, app: Flask, patch_tenant):
|
||||
"""Test getting status for non-existent document"""
|
||||
api = DocumentIndexingStatusApi()
|
||||
method = unwrap(api.get)
|
||||
@ -1066,7 +1068,7 @@ class TestDocumentIndexingStatusApi:
|
||||
|
||||
|
||||
class TestDocumentApiMetadata:
|
||||
def test_get_with_only_option(self, app, patch_tenant):
|
||||
def test_get_with_only_option(self, app: Flask, patch_tenant):
|
||||
"""Test get with 'only' metadata option"""
|
||||
api = DocumentApi()
|
||||
method = unwrap(api.get)
|
||||
@ -1085,7 +1087,7 @@ class TestDocumentApiMetadata:
|
||||
|
||||
assert status == 200
|
||||
|
||||
def test_get_with_without_option(self, app, patch_tenant):
|
||||
def test_get_with_without_option(self, app: Flask, patch_tenant):
|
||||
"""Test get with 'without' metadata option"""
|
||||
api = DocumentApi()
|
||||
method = unwrap(api.get)
|
||||
@ -1106,7 +1108,7 @@ class TestDocumentApiMetadata:
|
||||
|
||||
|
||||
class TestDocumentGenerateSummaryApiSuccess:
|
||||
def test_generate_not_enabled_high_quality(self, app, patch_tenant, patch_permission):
|
||||
def test_generate_not_enabled_high_quality(self, app: Flask, patch_tenant, patch_permission):
|
||||
"""Test summary generation on non-high-quality dataset"""
|
||||
api = DocumentGenerateSummaryApi()
|
||||
method = unwrap(api.post)
|
||||
@ -1128,7 +1130,7 @@ class TestDocumentGenerateSummaryApiSuccess:
|
||||
|
||||
|
||||
class TestDocumentProcessingApiResume:
|
||||
def test_resume_invalid_status(self, app, patch_tenant):
|
||||
def test_resume_invalid_status(self, app: Flask, patch_tenant):
|
||||
"""Test resume on non-paused document"""
|
||||
api = DocumentProcessingApi()
|
||||
method = unwrap(api.patch)
|
||||
@ -1141,7 +1143,7 @@ class TestDocumentProcessingApiResume:
|
||||
|
||||
|
||||
class TestDocumentPermissionCases:
|
||||
def test_document_batch_get_permission_denied(self, app, patch_tenant):
|
||||
def test_document_batch_get_permission_denied(self, app: Flask, patch_tenant):
|
||||
api = DocumentBatchIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -1159,7 +1161,7 @@ class TestDocumentPermissionCases:
|
||||
with pytest.raises(Forbidden):
|
||||
method(api, "ds-1", "batch-1")
|
||||
|
||||
def test_document_batch_get_documents_not_found(self, app, patch_tenant):
|
||||
def test_document_batch_get_documents_not_found(self, app: Flask, patch_tenant):
|
||||
api = DocumentBatchIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -1218,7 +1220,7 @@ class TestDocumentPermissionCases:
|
||||
with pytest.raises(Forbidden):
|
||||
method(api, "ds-1", "doc-1")
|
||||
|
||||
def test_process_rule_get_by_document_success(self, app, patch_tenant):
|
||||
def test_process_rule_get_by_document_success(self, app: Flask, patch_tenant):
|
||||
api = GetProcessRuleApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -1284,7 +1286,7 @@ class TestDocumentPermissionCases:
|
||||
|
||||
|
||||
class TestDocumentListAdvancedCases:
|
||||
def test_document_list_with_multiple_sort_options(self, app, patch_tenant, patch_dataset, patch_permission):
|
||||
def test_document_list_with_multiple_sort_options(self, app: Flask, patch_tenant, patch_dataset, patch_permission):
|
||||
"""Test document list with different sort options"""
|
||||
api = DatasetDocumentListApi()
|
||||
method = unwrap(api.get)
|
||||
@ -1310,7 +1312,7 @@ class TestDocumentListAdvancedCases:
|
||||
|
||||
assert response["total"] == 1
|
||||
|
||||
def test_document_metadata_with_schema_validation(self, app, patch_tenant):
|
||||
def test_document_metadata_with_schema_validation(self, app: Flask, patch_tenant):
|
||||
"""Test document metadata update with schema validation"""
|
||||
api = DocumentMetadataApi()
|
||||
method = unwrap(api.put)
|
||||
@ -1342,7 +1344,7 @@ class TestDocumentListAdvancedCases:
|
||||
|
||||
|
||||
class TestDocumentIndexingEdgeCases:
|
||||
def test_document_indexing_with_extraction_setting(self, app, patch_tenant):
|
||||
def test_document_indexing_with_extraction_setting(self, app: Flask, patch_tenant):
|
||||
api = DocumentIndexingEstimateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
|
||||
@ -292,7 +292,7 @@ class TestBedrockRetrievalApi:
|
||||
|
||||
|
||||
class TestExternalApiTemplateListApiAdvanced:
|
||||
def test_post_duplicate_name_error(self, app, mock_auth, current_user):
|
||||
def test_post_duplicate_name_error(self, app: Flask, mock_auth, current_user):
|
||||
api = ExternalApiTemplateListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -310,7 +310,7 @@ class TestExternalApiTemplateListApiAdvanced:
|
||||
with pytest.raises(DatasetNameDuplicateError):
|
||||
method(api)
|
||||
|
||||
def test_get_with_pagination(self, app, mock_auth, current_user):
|
||||
def test_get_with_pagination(self, app: Flask, mock_auth, current_user):
|
||||
api = ExternalApiTemplateListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -331,7 +331,7 @@ class TestExternalApiTemplateListApiAdvanced:
|
||||
|
||||
|
||||
class TestExternalDatasetCreateApiAdvanced:
|
||||
def test_create_forbidden(self, app, mock_auth, current_user):
|
||||
def test_create_forbidden(self, app: Flask, mock_auth, current_user):
|
||||
"""Test creating external dataset without permission"""
|
||||
api = ExternalDatasetCreateApi()
|
||||
method = unwrap(api.post)
|
||||
@ -351,7 +351,7 @@ class TestExternalDatasetCreateApiAdvanced:
|
||||
|
||||
|
||||
class TestExternalKnowledgeHitTestingApiAdvanced:
|
||||
def test_hit_testing_dataset_not_found(self, app, mock_auth, current_user):
|
||||
def test_hit_testing_dataset_not_found(self, app: Flask, mock_auth, current_user):
|
||||
"""Test hit testing on non-existent dataset"""
|
||||
api = ExternalKnowledgeHitTestingApi()
|
||||
method = unwrap(api.post)
|
||||
@ -372,7 +372,7 @@ class TestExternalKnowledgeHitTestingApiAdvanced:
|
||||
with pytest.raises(NotFound):
|
||||
method(api, "ds-1")
|
||||
|
||||
def test_hit_testing_with_custom_retrieval_model(self, app, mock_auth, current_user):
|
||||
def test_hit_testing_with_custom_retrieval_model(self, app: Flask, mock_auth, current_user):
|
||||
api = ExternalKnowledgeHitTestingApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -402,7 +402,7 @@ class TestExternalKnowledgeHitTestingApiAdvanced:
|
||||
|
||||
|
||||
class TestBedrockRetrievalApiAdvanced:
|
||||
def test_bedrock_retrieval_with_invalid_setting(self, app, mock_auth, current_user):
|
||||
def test_bedrock_retrieval_with_invalid_setting(self, app: Flask, mock_auth, current_user):
|
||||
api = BedrockRetrievalApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ def bypass_decorators(mocker: MockerFixture):
|
||||
|
||||
|
||||
class TestDatasetMetadataCreateApi:
|
||||
def test_create_metadata_success(self, app, current_user, dataset, dataset_id):
|
||||
def test_create_metadata_success(self, app: Flask, current_user, dataset, dataset_id):
|
||||
api = DatasetMetadataCreateApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -125,7 +125,7 @@ class TestDatasetMetadataCreateApi:
|
||||
assert status == 201
|
||||
assert result["name"] == "author"
|
||||
|
||||
def test_create_metadata_dataset_not_found(self, app, current_user, dataset_id):
|
||||
def test_create_metadata_dataset_not_found(self, app: Flask, current_user, dataset_id):
|
||||
api = DatasetMetadataCreateApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -162,7 +162,7 @@ class TestDatasetMetadataCreateApi:
|
||||
|
||||
|
||||
class TestDatasetMetadataGetApi:
|
||||
def test_get_metadata_success(self, app, dataset, dataset_id):
|
||||
def test_get_metadata_success(self, app: Flask, dataset, dataset_id):
|
||||
api = DatasetMetadataCreateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -184,7 +184,7 @@ class TestDatasetMetadataGetApi:
|
||||
assert status == 200
|
||||
assert isinstance(result, list)
|
||||
|
||||
def test_get_metadata_dataset_not_found(self, app, dataset_id):
|
||||
def test_get_metadata_dataset_not_found(self, app: Flask, dataset_id):
|
||||
api = DatasetMetadataCreateApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -201,7 +201,7 @@ class TestDatasetMetadataGetApi:
|
||||
|
||||
|
||||
class TestDatasetMetadataApi:
|
||||
def test_update_metadata_success(self, app, current_user, dataset, dataset_id, metadata_id):
|
||||
def test_update_metadata_success(self, app: Flask, current_user, dataset, dataset_id, metadata_id):
|
||||
api = DatasetMetadataApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -239,7 +239,7 @@ class TestDatasetMetadataApi:
|
||||
assert status == 200
|
||||
assert result["name"] == "updated-name"
|
||||
|
||||
def test_delete_metadata_success(self, app, current_user, dataset, dataset_id, metadata_id):
|
||||
def test_delete_metadata_success(self, app: Flask, current_user, dataset, dataset_id, metadata_id):
|
||||
api = DatasetMetadataApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -289,7 +289,7 @@ class TestDatasetMetadataBuiltInFieldApi:
|
||||
|
||||
|
||||
class TestDatasetMetadataBuiltInFieldActionApi:
|
||||
def test_enable_built_in_field(self, app, current_user, dataset, dataset_id):
|
||||
def test_enable_built_in_field(self, app: Flask, current_user, dataset, dataset_id):
|
||||
api = DatasetMetadataBuiltInFieldActionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -320,7 +320,7 @@ class TestDatasetMetadataBuiltInFieldActionApi:
|
||||
|
||||
|
||||
class TestDocumentMetadataEditApi:
|
||||
def test_update_document_metadata_success(self, app, current_user, dataset, dataset_id):
|
||||
def test_update_document_metadata_success(self, app: Flask, current_user, dataset, dataset_id):
|
||||
api = DocumentMetadataEditApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ def bypass_auth_and_setup(mocker: MockerFixture):
|
||||
|
||||
|
||||
class TestWebsiteCrawlApi:
|
||||
def test_crawl_success(self, app, mocker: MockerFixture):
|
||||
def test_crawl_success(self, app: Flask, mocker: MockerFixture):
|
||||
api = WebsiteCrawlApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -86,7 +86,7 @@ class TestWebsiteCrawlApi:
|
||||
assert status == 200
|
||||
assert result["job_id"] == "job-1"
|
||||
|
||||
def test_crawl_invalid_payload(self, app, mocker: MockerFixture):
|
||||
def test_crawl_invalid_payload(self, app: Flask, mocker: MockerFixture):
|
||||
api = WebsiteCrawlApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -114,7 +114,7 @@ class TestWebsiteCrawlApi:
|
||||
with pytest.raises(WebsiteCrawlError, match="invalid payload"):
|
||||
method(api)
|
||||
|
||||
def test_crawl_service_error(self, app, mocker: MockerFixture):
|
||||
def test_crawl_service_error(self, app: Flask, mocker: MockerFixture):
|
||||
api = WebsiteCrawlApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -151,7 +151,7 @@ class TestWebsiteCrawlApi:
|
||||
|
||||
|
||||
class TestWebsiteCrawlStatusApi:
|
||||
def test_get_status_success(self, app, mocker: MockerFixture):
|
||||
def test_get_status_success(self, app: Flask, mocker: MockerFixture):
|
||||
api = WebsiteCrawlStatusApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -182,7 +182,7 @@ class TestWebsiteCrawlStatusApi:
|
||||
assert status == 200
|
||||
assert result["status"] == "completed"
|
||||
|
||||
def test_get_status_invalid_provider(self, app, mocker: MockerFixture):
|
||||
def test_get_status_invalid_provider(self, app: Flask, mocker: MockerFixture):
|
||||
api = WebsiteCrawlStatusApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -204,7 +204,7 @@ class TestWebsiteCrawlStatusApi:
|
||||
with pytest.raises(WebsiteCrawlError, match="invalid provider"):
|
||||
method(api, job_id)
|
||||
|
||||
def test_get_status_service_error(self, app, mocker: MockerFixture):
|
||||
def test_get_status_service_error(self, app: Flask, mocker: MockerFixture):
|
||||
api = WebsiteCrawlStatusApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ from io import BytesIO
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
|
||||
import controllers.console.explore.audio as audio_module
|
||||
@ -52,7 +53,7 @@ class TestChatAudioApi:
|
||||
self.api = audio_module.ChatAudioApi()
|
||||
self.method = unwrap(self.api.post)
|
||||
|
||||
def test_post_success(self, app, installed_app, audio_file):
|
||||
def test_post_success(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -69,7 +70,7 @@ class TestChatAudioApi:
|
||||
|
||||
assert resp == {"text": "ok"}
|
||||
|
||||
def test_app_unavailable(self, app, installed_app, audio_file):
|
||||
def test_app_unavailable(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -85,7 +86,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(AppUnavailableError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_no_audio_uploaded(self, app, installed_app, audio_file):
|
||||
def test_no_audio_uploaded(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -101,7 +102,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(NoAudioUploadedError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_audio_too_large(self, app, installed_app, audio_file):
|
||||
def test_audio_too_large(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -117,7 +118,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(AudioTooLargeError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_provider_quota_exceeded(self, app, installed_app, audio_file):
|
||||
def test_provider_quota_exceeded(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -133,7 +134,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(ProviderQuotaExceededError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_unknown_exception(self, app, installed_app, audio_file):
|
||||
def test_unknown_exception(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -149,7 +150,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(InternalServerError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_unsupported_audio_type(self, app, installed_app, audio_file):
|
||||
def test_unsupported_audio_type(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -165,7 +166,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(audio_module.UnsupportedAudioTypeError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_provider_not_support_speech_to_text(self, app, installed_app, audio_file):
|
||||
def test_provider_not_support_speech_to_text(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -181,7 +182,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(audio_module.ProviderNotSupportSpeechToTextError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_provider_not_initialized(self, app, installed_app, audio_file):
|
||||
def test_provider_not_initialized(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -197,7 +198,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_model_currently_not_supported(self, app, installed_app, audio_file):
|
||||
def test_model_currently_not_supported(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -213,7 +214,7 @@ class TestChatAudioApi:
|
||||
with pytest.raises(ProviderModelCurrentlyNotSupportError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_invoke_error_asr(self, app, installed_app, audio_file):
|
||||
def test_invoke_error_asr(self, app: Flask, installed_app, audio_file):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -235,7 +236,7 @@ class TestChatTextApi:
|
||||
self.api = audio_module.ChatTextApi()
|
||||
self.method = unwrap(self.api.post)
|
||||
|
||||
def test_post_success(self, app, installed_app):
|
||||
def test_post_success(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -251,7 +252,7 @@ class TestChatTextApi:
|
||||
|
||||
assert resp == {"audio": "ok"}
|
||||
|
||||
def test_provider_not_initialized(self, app, installed_app):
|
||||
def test_provider_not_initialized(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -266,7 +267,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_model_not_supported(self, app, installed_app):
|
||||
def test_model_not_supported(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -281,7 +282,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(ProviderModelCurrentlyNotSupportError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_invoke_error(self, app, installed_app):
|
||||
def test_invoke_error(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -296,7 +297,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(CompletionRequestError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_unknown_exception(self, app, installed_app):
|
||||
def test_unknown_exception(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -311,7 +312,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(InternalServerError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_app_unavailable_tts(self, app, installed_app):
|
||||
def test_app_unavailable_tts(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -326,7 +327,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(AppUnavailableError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_no_audio_uploaded_tts(self, app, installed_app):
|
||||
def test_no_audio_uploaded_tts(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -341,7 +342,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(NoAudioUploadedError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_audio_too_large_tts(self, app, installed_app):
|
||||
def test_audio_too_large_tts(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -356,7 +357,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(AudioTooLargeError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_unsupported_audio_type_tts(self, app, installed_app):
|
||||
def test_unsupported_audio_type_tts(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -371,7 +372,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(audio_module.UnsupportedAudioTypeError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_provider_not_support_speech_to_text_tts(self, app, installed_app):
|
||||
def test_provider_not_support_speech_to_text_tts(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
@ -386,7 +387,7 @@ class TestChatTextApi:
|
||||
with pytest.raises(audio_module.ProviderNotSupportSpeechToTextError):
|
||||
self.method(installed_app)
|
||||
|
||||
def test_quota_exceeded_tts(self, app, installed_app):
|
||||
def test_quota_exceeded_tts(self, app: Flask, installed_app):
|
||||
with (
|
||||
app.test_request_context(
|
||||
"/",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from unittest.mock import MagicMock, PropertyMock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
|
||||
import controllers.console.explore.completion as completion_module
|
||||
@ -51,7 +52,7 @@ def payload_patch(payload_data):
|
||||
|
||||
|
||||
class TestCompletionApi:
|
||||
def test_post_success(self, app, completion_app, user, payload_patch):
|
||||
def test_post_success(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -83,7 +84,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(NotCompletionAppError):
|
||||
method(installed_app)
|
||||
|
||||
def test_conversation_completed(self, app, completion_app, user, payload_patch):
|
||||
def test_conversation_completed(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -100,7 +101,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(ConversationCompletedError):
|
||||
method(completion_app)
|
||||
|
||||
def test_internal_error(self, app, completion_app, user, payload_patch):
|
||||
def test_internal_error(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -117,7 +118,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(InternalServerError):
|
||||
method(completion_app)
|
||||
|
||||
def test_conversation_not_exists(self, app, completion_app, user, payload_patch):
|
||||
def test_conversation_not_exists(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -134,7 +135,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(completion_module.NotFound):
|
||||
method(completion_app)
|
||||
|
||||
def test_app_unavailable(self, app, completion_app, user, payload_patch):
|
||||
def test_app_unavailable(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -151,7 +152,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(completion_module.AppUnavailableError):
|
||||
method(completion_app)
|
||||
|
||||
def test_provider_not_initialized(self, app, completion_app, user, payload_patch):
|
||||
def test_provider_not_initialized(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -168,7 +169,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(completion_module.ProviderNotInitializeError):
|
||||
method(completion_app)
|
||||
|
||||
def test_quota_exceeded(self, app, completion_app, user, payload_patch):
|
||||
def test_quota_exceeded(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -185,7 +186,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(completion_module.ProviderQuotaExceededError):
|
||||
method(completion_app)
|
||||
|
||||
def test_model_not_supported(self, app, completion_app, user, payload_patch):
|
||||
def test_model_not_supported(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -202,7 +203,7 @@ class TestCompletionApi:
|
||||
with pytest.raises(completion_module.ProviderModelCurrentlyNotSupportError):
|
||||
method(completion_app)
|
||||
|
||||
def test_invoke_error(self, app, completion_app, user, payload_patch):
|
||||
def test_invoke_error(self, app: Flask, completion_app, user, payload_patch):
|
||||
api = completion_module.CompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -247,7 +248,7 @@ class TestCompletionStopApi:
|
||||
|
||||
|
||||
class TestChatApi:
|
||||
def test_post_success(self, app, chat_app, user, payload_patch):
|
||||
def test_post_success(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -279,7 +280,7 @@ class TestChatApi:
|
||||
with pytest.raises(NotChatAppError):
|
||||
method(installed_app)
|
||||
|
||||
def test_rate_limit_error(self, app, chat_app, user, payload_patch):
|
||||
def test_rate_limit_error(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -296,7 +297,7 @@ class TestChatApi:
|
||||
with pytest.raises(InvokeRateLimitHttpError):
|
||||
method(chat_app)
|
||||
|
||||
def test_conversation_completed_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_conversation_completed_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -313,7 +314,7 @@ class TestChatApi:
|
||||
with pytest.raises(ConversationCompletedError):
|
||||
method(chat_app)
|
||||
|
||||
def test_conversation_not_exists_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_conversation_not_exists_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -330,7 +331,7 @@ class TestChatApi:
|
||||
with pytest.raises(completion_module.NotFound):
|
||||
method(chat_app)
|
||||
|
||||
def test_app_unavailable_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_app_unavailable_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -347,7 +348,7 @@ class TestChatApi:
|
||||
with pytest.raises(completion_module.AppUnavailableError):
|
||||
method(chat_app)
|
||||
|
||||
def test_provider_not_initialized_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_provider_not_initialized_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -364,7 +365,7 @@ class TestChatApi:
|
||||
with pytest.raises(completion_module.ProviderNotInitializeError):
|
||||
method(chat_app)
|
||||
|
||||
def test_quota_exceeded_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_quota_exceeded_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -381,7 +382,7 @@ class TestChatApi:
|
||||
with pytest.raises(completion_module.ProviderQuotaExceededError):
|
||||
method(chat_app)
|
||||
|
||||
def test_model_not_supported_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_model_not_supported_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -398,7 +399,7 @@ class TestChatApi:
|
||||
with pytest.raises(completion_module.ProviderModelCurrentlyNotSupportError):
|
||||
method(chat_app)
|
||||
|
||||
def test_invoke_error_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_invoke_error_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -415,7 +416,7 @@ class TestChatApi:
|
||||
with pytest.raises(completion_module.CompletionRequestError):
|
||||
method(chat_app)
|
||||
|
||||
def test_internal_error_chat(self, app, chat_app, user, payload_patch):
|
||||
def test_internal_error_chat(self, app: Flask, chat_app, user, payload_patch):
|
||||
api = completion_module.ChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ from datetime import datetime
|
||||
from unittest.mock import MagicMock, PropertyMock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import BadRequest, Forbidden, NotFound
|
||||
|
||||
import controllers.console.explore.installed_app as module
|
||||
@ -51,7 +52,7 @@ def payload_patch():
|
||||
|
||||
|
||||
class TestInstalledAppsListApi:
|
||||
def test_get_installed_apps(self, app, current_user, tenant_id, installed_app):
|
||||
def test_get_installed_apps(self, app: Flask, current_user, tenant_id, installed_app):
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -75,7 +76,7 @@ class TestInstalledAppsListApi:
|
||||
assert result["installed_apps"][0]["editable"] is True
|
||||
assert result["installed_apps"][0]["uninstallable"] is False
|
||||
|
||||
def test_get_installed_apps_with_app_id_filter(self, app, current_user, tenant_id):
|
||||
def test_get_installed_apps_with_app_id_filter(self, app: Flask, current_user, tenant_id):
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -97,7 +98,7 @@ class TestInstalledAppsListApi:
|
||||
|
||||
assert result == {"installed_apps": []}
|
||||
|
||||
def test_get_installed_apps_with_webapp_auth_enabled(self, app, current_user, tenant_id, installed_app):
|
||||
def test_get_installed_apps_with_webapp_auth_enabled(self, app: Flask, current_user, tenant_id, installed_app):
|
||||
"""Test filtering when webapp_auth is enabled."""
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
@ -133,7 +134,7 @@ class TestInstalledAppsListApi:
|
||||
|
||||
assert len(result["installed_apps"]) == 1
|
||||
|
||||
def test_get_installed_apps_with_webapp_auth_user_denied(self, app, current_user, tenant_id, installed_app):
|
||||
def test_get_installed_apps_with_webapp_auth_user_denied(self, app: Flask, current_user, tenant_id, installed_app):
|
||||
"""Test filtering when user doesn't have access."""
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
@ -169,7 +170,7 @@ class TestInstalledAppsListApi:
|
||||
|
||||
assert result["installed_apps"] == []
|
||||
|
||||
def test_get_installed_apps_with_sso_verified_access(self, app, current_user, tenant_id, installed_app):
|
||||
def test_get_installed_apps_with_sso_verified_access(self, app: Flask, current_user, tenant_id, installed_app):
|
||||
"""Test that sso_verified access mode apps are skipped in filtering."""
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
@ -200,7 +201,7 @@ class TestInstalledAppsListApi:
|
||||
|
||||
assert len(result["installed_apps"]) == 0
|
||||
|
||||
def test_get_installed_apps_filters_null_apps(self, app, current_user, tenant_id):
|
||||
def test_get_installed_apps_filters_null_apps(self, app: Flask, current_user, tenant_id):
|
||||
"""Test that installed apps with null app are filtered out."""
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
@ -226,7 +227,7 @@ class TestInstalledAppsListApi:
|
||||
|
||||
assert result["installed_apps"] == []
|
||||
|
||||
def test_get_installed_apps_current_tenant_none(self, app, tenant_id, installed_app):
|
||||
def test_get_installed_apps_current_tenant_none(self, app: Flask, tenant_id, installed_app):
|
||||
"""Test error when current_user.current_tenant is None."""
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.get)
|
||||
@ -247,7 +248,7 @@ class TestInstalledAppsListApi:
|
||||
|
||||
|
||||
class TestInstalledAppsCreateApi:
|
||||
def test_post_success(self, app, tenant_id, payload_patch):
|
||||
def test_post_success(self, app: Flask, tenant_id, payload_patch):
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -276,7 +277,7 @@ class TestInstalledAppsCreateApi:
|
||||
assert result == {"message": "App installed successfully"}
|
||||
assert recommended.install_count == 1
|
||||
|
||||
def test_post_recommended_not_found(self, app, payload_patch):
|
||||
def test_post_recommended_not_found(self, app: Flask, payload_patch):
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -291,7 +292,7 @@ class TestInstalledAppsCreateApi:
|
||||
with pytest.raises(NotFound):
|
||||
method(api)
|
||||
|
||||
def test_post_app_not_public(self, app, tenant_id, payload_patch):
|
||||
def test_post_app_not_public(self, app: Flask, tenant_id, payload_patch):
|
||||
api = module.InstalledAppsListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -315,7 +316,7 @@ class TestInstalledAppsCreateApi:
|
||||
|
||||
|
||||
class TestInstalledAppApi:
|
||||
def test_delete_success(self, tenant_id, installed_app):
|
||||
def test_delete_success(self, tenant_id: str, installed_app):
|
||||
api = module.InstalledAppApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -328,7 +329,7 @@ class TestInstalledAppApi:
|
||||
assert status == 204
|
||||
assert resp["result"] == "success"
|
||||
|
||||
def test_delete_owned_by_current_tenant(self, tenant_id):
|
||||
def test_delete_owned_by_current_tenant(self, tenant_id: str):
|
||||
api = module.InstalledAppApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -338,7 +339,7 @@ class TestInstalledAppApi:
|
||||
with pytest.raises(BadRequest):
|
||||
method(installed_app)
|
||||
|
||||
def test_patch_update_pin(self, app, payload_patch, installed_app):
|
||||
def test_patch_update_pin(self, app: Flask, payload_patch, installed_app):
|
||||
api = module.InstalledAppApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -352,7 +353,7 @@ class TestInstalledAppApi:
|
||||
assert installed_app.is_pinned is True
|
||||
assert result["result"] == "success"
|
||||
|
||||
def test_patch_no_change(self, app, payload_patch, installed_app):
|
||||
def test_patch_no_change(self, app: Flask, payload_patch, installed_app):
|
||||
api = module.InstalledAppApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ class TestSavedMessageListApi:
|
||||
with pytest.raises(NotCompletionAppError):
|
||||
method(installed_app)
|
||||
|
||||
def test_post_success(self, app, payload_patch):
|
||||
def test_post_success(self, app: Flask, payload_patch):
|
||||
api = module.SavedMessageListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -102,7 +102,7 @@ class TestSavedMessageListApi:
|
||||
save_mock.assert_called_once()
|
||||
assert result == {"result": "success"}
|
||||
|
||||
def test_post_message_not_exists(self, app, payload_patch):
|
||||
def test_post_message_not_exists(self, app: Flask, payload_patch):
|
||||
api = module.SavedMessageListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(NotWorkflowAppError):
|
||||
method(api, MagicMock(mode=AppMode.CHAT))
|
||||
|
||||
def test_success(self, app, trial_app_workflow, account):
|
||||
def test_success(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -116,7 +116,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
|
||||
assert result is not None
|
||||
|
||||
def test_workflow_provider_not_init(self, app, trial_app_workflow, account):
|
||||
def test_workflow_provider_not_init(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -132,7 +132,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
method(api, trial_app_workflow)
|
||||
|
||||
def test_workflow_quota_exceeded(self, app, trial_app_workflow, account):
|
||||
def test_workflow_quota_exceeded(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -148,7 +148,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(ProviderQuotaExceededError):
|
||||
method(api, trial_app_workflow)
|
||||
|
||||
def test_workflow_model_not_support(self, app, trial_app_workflow, account):
|
||||
def test_workflow_model_not_support(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -164,7 +164,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(ProviderModelCurrentlyNotSupportError):
|
||||
method(api, trial_app_workflow)
|
||||
|
||||
def test_workflow_invoke_error(self, app, trial_app_workflow, account):
|
||||
def test_workflow_invoke_error(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -180,7 +180,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(CompletionRequestError):
|
||||
method(api, trial_app_workflow)
|
||||
|
||||
def test_workflow_rate_limit_error(self, app, trial_app_workflow, account):
|
||||
def test_workflow_rate_limit_error(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -196,7 +196,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(InvokeRateLimitHttpError):
|
||||
method(api, trial_app_workflow)
|
||||
|
||||
def test_workflow_value_error(self, app, trial_app_workflow, account):
|
||||
def test_workflow_value_error(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -212,7 +212,7 @@ class TestTrialAppWorkflowRunApi:
|
||||
with pytest.raises(ValueError):
|
||||
method(api, trial_app_workflow)
|
||||
|
||||
def test_workflow_generic_exception(self, app, trial_app_workflow, account):
|
||||
def test_workflow_generic_exception(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -238,7 +238,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(NotChatAppError):
|
||||
method(api, MagicMock(mode="completion"))
|
||||
|
||||
def test_success(self, app, trial_app_chat, account):
|
||||
def test_success(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -252,7 +252,7 @@ class TestTrialChatApi:
|
||||
|
||||
assert result is not None
|
||||
|
||||
def test_chat_conversation_not_exists(self, app, trial_app_chat, account):
|
||||
def test_chat_conversation_not_exists(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -268,7 +268,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(NotFound):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_conversation_completed(self, app, trial_app_chat, account):
|
||||
def test_chat_conversation_completed(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -284,7 +284,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(ConversationCompletedError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_app_config_broken(self, app, trial_app_chat, account):
|
||||
def test_chat_app_config_broken(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -300,7 +300,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(AppUnavailableError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_provider_not_init(self, app, trial_app_chat, account):
|
||||
def test_chat_provider_not_init(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -316,7 +316,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_quota_exceeded(self, app, trial_app_chat, account):
|
||||
def test_chat_quota_exceeded(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -332,7 +332,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(ProviderQuotaExceededError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_model_not_support(self, app, trial_app_chat, account):
|
||||
def test_chat_model_not_support(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -348,7 +348,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(ProviderModelCurrentlyNotSupportError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_invoke_error(self, app, trial_app_chat, account):
|
||||
def test_chat_invoke_error(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -364,7 +364,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(CompletionRequestError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_rate_limit_error(self, app, trial_app_chat, account):
|
||||
def test_chat_rate_limit_error(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -380,7 +380,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(InvokeRateLimitHttpError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_value_error(self, app, trial_app_chat, account):
|
||||
def test_chat_value_error(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -396,7 +396,7 @@ class TestTrialChatApi:
|
||||
with pytest.raises(ValueError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_chat_generic_exception(self, app, trial_app_chat, account):
|
||||
def test_chat_generic_exception(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -422,7 +422,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(NotCompletionAppError):
|
||||
method(api, MagicMock(mode=AppMode.CHAT))
|
||||
|
||||
def test_success(self, app, trial_app_completion, account):
|
||||
def test_success(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -436,7 +436,7 @@ class TestTrialCompletionApi:
|
||||
|
||||
assert result is not None
|
||||
|
||||
def test_completion_app_config_broken(self, app, trial_app_completion, account):
|
||||
def test_completion_app_config_broken(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -452,7 +452,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(AppUnavailableError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_provider_not_init(self, app, trial_app_completion, account):
|
||||
def test_completion_provider_not_init(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -468,7 +468,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_quota_exceeded(self, app, trial_app_completion, account):
|
||||
def test_completion_quota_exceeded(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -484,7 +484,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(ProviderQuotaExceededError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_model_not_support(self, app, trial_app_completion, account):
|
||||
def test_completion_model_not_support(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -500,7 +500,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(ProviderModelCurrentlyNotSupportError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_invoke_error(self, app, trial_app_completion, account):
|
||||
def test_completion_invoke_error(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -516,7 +516,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(CompletionRequestError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_rate_limit_error(self, app, trial_app_completion, account):
|
||||
def test_completion_rate_limit_error(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -532,7 +532,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(InternalServerError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_value_error(self, app, trial_app_completion, account):
|
||||
def test_completion_value_error(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -548,7 +548,7 @@ class TestTrialCompletionApi:
|
||||
with pytest.raises(ValueError):
|
||||
method(api, trial_app_completion)
|
||||
|
||||
def test_completion_generic_exception(self, app, trial_app_completion, account):
|
||||
def test_completion_generic_exception(self, app: Flask, trial_app_completion, account):
|
||||
api = module.TrialCompletionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -574,7 +574,7 @@ class TestTrialMessageSuggestedQuestionApi:
|
||||
with pytest.raises(NotChatAppError):
|
||||
method(MagicMock(mode="completion"), str(uuid4()))
|
||||
|
||||
def test_success(self, app, trial_app_chat, account):
|
||||
def test_success(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialMessageSuggestedQuestionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -591,7 +591,7 @@ class TestTrialMessageSuggestedQuestionApi:
|
||||
|
||||
assert result == {"data": ["q1", "q2"]}
|
||||
|
||||
def test_conversation_not_exists(self, app, trial_app_chat, account):
|
||||
def test_conversation_not_exists(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialMessageSuggestedQuestionApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
@ -643,7 +643,7 @@ class TestTrialAppParameterApi:
|
||||
|
||||
|
||||
class TestTrialChatAudioApi:
|
||||
def test_success(self, app, trial_app_chat, account):
|
||||
def test_success(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -662,7 +662,7 @@ class TestTrialChatAudioApi:
|
||||
|
||||
assert result == {"text": "hello"}
|
||||
|
||||
def test_app_config_broken(self, app, trial_app_chat, account):
|
||||
def test_app_config_broken(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -683,7 +683,7 @@ class TestTrialChatAudioApi:
|
||||
with pytest.raises(module.AppUnavailableError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_no_audio_uploaded(self, app, trial_app_chat, account):
|
||||
def test_no_audio_uploaded(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -704,7 +704,7 @@ class TestTrialChatAudioApi:
|
||||
with pytest.raises(module.NoAudioUploadedError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_audio_too_large(self, app, trial_app_chat, account):
|
||||
def test_audio_too_large(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -725,7 +725,7 @@ class TestTrialChatAudioApi:
|
||||
with pytest.raises(module.AudioTooLargeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_unsupported_audio_type(self, app, trial_app_chat, account):
|
||||
def test_unsupported_audio_type(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -746,7 +746,7 @@ class TestTrialChatAudioApi:
|
||||
with pytest.raises(module.UnsupportedAudioTypeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_provider_not_support_tts(self, app, trial_app_chat, account):
|
||||
def test_provider_not_support_tts(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -767,7 +767,7 @@ class TestTrialChatAudioApi:
|
||||
with pytest.raises(module.ProviderNotSupportSpeechToTextError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_provider_not_init(self, app, trial_app_chat, account):
|
||||
def test_provider_not_init(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -784,7 +784,7 @@ class TestTrialChatAudioApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_quota_exceeded(self, app, trial_app_chat, account):
|
||||
def test_quota_exceeded(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -803,7 +803,7 @@ class TestTrialChatAudioApi:
|
||||
|
||||
|
||||
class TestTrialChatTextApi:
|
||||
def test_success(self, app, trial_app_chat, account):
|
||||
def test_success(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -817,7 +817,7 @@ class TestTrialChatTextApi:
|
||||
|
||||
assert result == {"audio": "base64_data"}
|
||||
|
||||
def test_app_config_broken(self, app, trial_app_chat, account):
|
||||
def test_app_config_broken(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -833,7 +833,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(module.AppUnavailableError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_provider_not_support(self, app, trial_app_chat, account):
|
||||
def test_provider_not_support(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -849,7 +849,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(module.ProviderNotSupportSpeechToTextError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_audio_too_large(self, app, trial_app_chat, account):
|
||||
def test_audio_too_large(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -865,7 +865,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(module.AudioTooLargeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_no_audio_uploaded(self, app, trial_app_chat, account):
|
||||
def test_no_audio_uploaded(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -881,7 +881,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(module.NoAudioUploadedError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_provider_not_init(self, app, trial_app_chat, account):
|
||||
def test_provider_not_init(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -893,7 +893,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_quota_exceeded(self, app, trial_app_chat, account):
|
||||
def test_quota_exceeded(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -905,7 +905,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(ProviderQuotaExceededError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_model_not_support(self, app, trial_app_chat, account):
|
||||
def test_model_not_support(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -917,7 +917,7 @@ class TestTrialChatTextApi:
|
||||
with pytest.raises(ProviderModelCurrentlyNotSupportError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_invoke_error(self, app, trial_app_chat, account):
|
||||
def test_invoke_error(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -931,7 +931,7 @@ class TestTrialChatTextApi:
|
||||
|
||||
|
||||
class TestTrialAppWorkflowTaskStopApi:
|
||||
def test_not_workflow_app(self, app, trial_app_chat):
|
||||
def test_not_workflow_app(self, app: Flask, trial_app_chat):
|
||||
api = module.TrialAppWorkflowTaskStopApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -939,7 +939,7 @@ class TestTrialAppWorkflowTaskStopApi:
|
||||
with pytest.raises(NotWorkflowAppError):
|
||||
method(api, trial_app_chat, str(uuid4()))
|
||||
|
||||
def test_success(self, app, trial_app_workflow, account):
|
||||
def test_success(self, app: Flask, trial_app_workflow, account):
|
||||
api = module.TrialAppWorkflowTaskStopApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -1009,7 +1009,7 @@ class TestTrialSitApi:
|
||||
|
||||
|
||||
class TestTrialChatAudioApiExceptionHandlers:
|
||||
def test_provider_not_init(self, app, trial_app_chat, account):
|
||||
def test_provider_not_init(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -1030,7 +1030,7 @@ class TestTrialChatAudioApiExceptionHandlers:
|
||||
with pytest.raises(ProviderNotInitializeError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_quota_exceeded(self, app, trial_app_chat, account):
|
||||
def test_quota_exceeded(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -1051,7 +1051,7 @@ class TestTrialChatAudioApiExceptionHandlers:
|
||||
with pytest.raises(ProviderQuotaExceededError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_invoke_error(self, app, trial_app_chat, account):
|
||||
def test_invoke_error(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatAudioApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -1074,7 +1074,7 @@ class TestTrialChatAudioApiExceptionHandlers:
|
||||
|
||||
|
||||
class TestTrialChatTextApiExceptionHandlers:
|
||||
def test_app_config_broken(self, app, trial_app_chat, account):
|
||||
def test_app_config_broken(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -1090,7 +1090,7 @@ class TestTrialChatTextApiExceptionHandlers:
|
||||
with pytest.raises(module.AppUnavailableError):
|
||||
method(api, trial_app_chat)
|
||||
|
||||
def test_unsupported_audio_type(self, app, trial_app_chat, account):
|
||||
def test_unsupported_audio_type(self, app: Flask, trial_app_chat, account):
|
||||
api = module.TrialChatTextApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ def payload():
|
||||
|
||||
|
||||
class TestInstalledAppWorkflowRunApi:
|
||||
def test_not_workflow_app(self, app, non_workflow_installed_app):
|
||||
def test_not_workflow_app(self, app: Flask, non_workflow_installed_app):
|
||||
api = InstalledAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -71,7 +71,7 @@ class TestInstalledAppWorkflowRunApi:
|
||||
with pytest.raises(NotWorkflowAppError):
|
||||
method(non_workflow_installed_app)
|
||||
|
||||
def test_success(self, app, installed_workflow_app, user, payload):
|
||||
def test_success(self, app: Flask, installed_workflow_app, user, payload):
|
||||
api = InstalledAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -91,7 +91,7 @@ class TestInstalledAppWorkflowRunApi:
|
||||
generate_mock.assert_called_once()
|
||||
assert result is not None
|
||||
|
||||
def test_rate_limit_error(self, app, installed_workflow_app, user, payload):
|
||||
def test_rate_limit_error(self, app: Flask, installed_workflow_app, user, payload):
|
||||
api = InstalledAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -109,7 +109,7 @@ class TestInstalledAppWorkflowRunApi:
|
||||
with pytest.raises(InvokeRateLimitHttpError):
|
||||
method(installed_workflow_app)
|
||||
|
||||
def test_unexpected_exception(self, app, installed_workflow_app, user, payload):
|
||||
def test_unexpected_exception(self, app: Flask, installed_workflow_app, user, payload):
|
||||
api = InstalledAppWorkflowRunApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -101,7 +101,7 @@ class TestTagListApi:
|
||||
assert status == 200
|
||||
assert result == [{"id": "1", "name": "tag", "type": "knowledge", "binding_count": "1"}]
|
||||
|
||||
def test_post_success(self, app, admin_user, tag, payload_patch):
|
||||
def test_post_success(self, app: Flask, admin_user, tag, payload_patch):
|
||||
api = TagListApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -144,7 +144,7 @@ class TestTagListApi:
|
||||
|
||||
|
||||
class TestTagUpdateDeleteApi:
|
||||
def test_patch_success(self, app, admin_user, tag, payload_patch):
|
||||
def test_patch_success(self, app: Flask, admin_user, tag, payload_patch):
|
||||
api = TagUpdateDeleteApi()
|
||||
method = unwrap(api.patch)
|
||||
|
||||
@ -191,7 +191,7 @@ class TestTagUpdateDeleteApi:
|
||||
with pytest.raises(Forbidden):
|
||||
method(api, "tag-1")
|
||||
|
||||
def test_delete_success(self, app, admin_user):
|
||||
def test_delete_success(self, app: Flask, admin_user):
|
||||
api = TagUpdateDeleteApi()
|
||||
method = unwrap(api.delete)
|
||||
|
||||
@ -210,7 +210,7 @@ class TestTagUpdateDeleteApi:
|
||||
|
||||
|
||||
class TestTagBindingCollectionApi:
|
||||
def test_create_success(self, app, admin_user, payload_patch):
|
||||
def test_create_success(self, app: Flask, admin_user, payload_patch):
|
||||
api = TagBindingCollectionApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
@ -252,7 +252,7 @@ class TestTagBindingCollectionApi:
|
||||
|
||||
|
||||
class TestTagBindingRemoveApi:
|
||||
def test_remove_success(self, app, admin_user, payload_patch):
|
||||
def test_remove_success(self, app: Flask, admin_user, payload_patch):
|
||||
api = TagBindingRemoveApi()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ class TestFileApiGet:
|
||||
|
||||
|
||||
class TestFileApiPost:
|
||||
def test_no_file_uploaded(self, app, mock_account_context):
|
||||
def test_no_file_uploaded(self, app: Flask, mock_account_context):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -103,7 +103,7 @@ class TestFileApiPost:
|
||||
with pytest.raises(NoFileUploadedError):
|
||||
post_method(api)
|
||||
|
||||
def test_too_many_files(self, app, mock_account_context):
|
||||
def test_too_many_files(self, app: Flask, mock_account_context):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -120,7 +120,7 @@ class TestFileApiPost:
|
||||
with pytest.raises(TooManyFilesError):
|
||||
post_method(api)
|
||||
|
||||
def test_filename_missing(self, app, mock_account_context):
|
||||
def test_filename_missing(self, app: Flask, mock_account_context):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -132,7 +132,7 @@ class TestFileApiPost:
|
||||
with pytest.raises(FilenameNotExistsError):
|
||||
post_method(api)
|
||||
|
||||
def test_dataset_upload_without_permission(self, app, mock_current_user):
|
||||
def test_dataset_upload_without_permission(self, app: Flask, mock_current_user):
|
||||
mock_current_user.is_dataset_editor = False
|
||||
|
||||
with patch(
|
||||
@ -151,7 +151,7 @@ class TestFileApiPost:
|
||||
with pytest.raises(Forbidden):
|
||||
post_method(api)
|
||||
|
||||
def test_successful_upload(self, app, mock_account_context, mock_file_service):
|
||||
def test_successful_upload(self, app: Flask, mock_account_context, mock_file_service):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -185,7 +185,7 @@ class TestFileApiPost:
|
||||
assert response["id"] == "file-id-123"
|
||||
assert response["name"] == "test.txt"
|
||||
|
||||
def test_upload_with_invalid_source(self, app, mock_account_context, mock_file_service):
|
||||
def test_upload_with_invalid_source(self, app: Flask, mock_account_context, mock_file_service):
|
||||
"""Test that invalid source parameter gets normalized to None"""
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
@ -225,7 +225,7 @@ class TestFileApiPost:
|
||||
call_kwargs = mock_file_service.upload_file.call_args[1]
|
||||
assert call_kwargs["source"] is None
|
||||
|
||||
def test_file_too_large_error(self, app, mock_account_context, mock_file_service):
|
||||
def test_file_too_large_error(self, app: Flask, mock_account_context, mock_file_service):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -242,7 +242,7 @@ class TestFileApiPost:
|
||||
with pytest.raises(FileTooLargeError):
|
||||
post_method(api)
|
||||
|
||||
def test_unsupported_file_type(self, app, mock_account_context, mock_file_service):
|
||||
def test_unsupported_file_type(self, app: Flask, mock_account_context, mock_file_service):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -259,7 +259,7 @@ class TestFileApiPost:
|
||||
with pytest.raises(UnsupportedFileTypeError):
|
||||
post_method(api)
|
||||
|
||||
def test_blocked_extension(self, app, mock_account_context, mock_file_service):
|
||||
def test_blocked_extension(self, app: Flask, mock_account_context, mock_file_service):
|
||||
api = FileApi()
|
||||
post_method = unwrap(api.post)
|
||||
|
||||
@ -278,7 +278,7 @@ class TestFileApiPost:
|
||||
|
||||
|
||||
class TestFilePreviewApi:
|
||||
def test_get_preview(self, app, mock_account_context, mock_file_service):
|
||||
def test_get_preview(self, app: Flask, mock_account_context, mock_file_service):
|
||||
api = FilePreviewApi()
|
||||
get_method = unwrap(api.get)
|
||||
mock_file_service.get_file_preview.return_value = "preview text"
|
||||
|
||||
@ -114,7 +114,7 @@ class TestAccountUpdateApis:
|
||||
(AccountTimezoneApi, {"timezone": "UTC"}),
|
||||
],
|
||||
)
|
||||
def test_update_success(self, app, api_cls, payload):
|
||||
def test_update_success(self, app: Flask, api_cls, payload):
|
||||
api = api_cls()
|
||||
method = unwrap(api.post)
|
||||
|
||||
|
||||
@ -302,7 +302,7 @@ class TestPluginFetchPermissionApi:
|
||||
|
||||
|
||||
class TestPluginFetchDynamicSelectOptionsApi:
|
||||
def test_fetch_dynamic_options(self, app, user):
|
||||
def test_fetch_dynamic_options(self, app: Flask, user):
|
||||
api = PluginFetchDynamicSelectOptionsApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ from types import SimpleNamespace
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask_restx.api import HTTPStatus
|
||||
|
||||
from controllers.service_api.app.annotation import (
|
||||
@ -163,7 +164,7 @@ class TestAnnotationErrorPatterns:
|
||||
|
||||
|
||||
class TestAnnotationReplyActionApi:
|
||||
def test_enable(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_enable(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
enable_mock = Mock()
|
||||
monkeypatch.setattr(AppAnnotationService, "enable_app_annotation", enable_mock)
|
||||
|
||||
@ -181,7 +182,7 @@ class TestAnnotationReplyActionApi:
|
||||
assert status == 200
|
||||
enable_mock.assert_called_once()
|
||||
|
||||
def test_disable(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_disable(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
disable_mock = Mock()
|
||||
monkeypatch.setattr(AppAnnotationService, "disable_app_annotation", disable_mock)
|
||||
|
||||
@ -231,7 +232,7 @@ class TestAnnotationReplyActionStatusApi:
|
||||
|
||||
|
||||
class TestAnnotationListApi:
|
||||
def test_get(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_get(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
annotation = SimpleNamespace(id="a1", question="q", content="a", created_at=0)
|
||||
monkeypatch.setattr(
|
||||
AppAnnotationService,
|
||||
@ -248,7 +249,7 @@ class TestAnnotationListApi:
|
||||
|
||||
assert response["total"] == 1
|
||||
|
||||
def test_create(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_create(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
annotation = SimpleNamespace(id="a1", question="q", content="a", created_at=0)
|
||||
monkeypatch.setattr(
|
||||
AppAnnotationService,
|
||||
@ -268,7 +269,7 @@ class TestAnnotationListApi:
|
||||
|
||||
|
||||
class TestAnnotationUpdateDeleteApi:
|
||||
def test_update_delete(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_update_delete(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
annotation = SimpleNamespace(id="a1", question="q", content="a", created_at=0)
|
||||
monkeypatch.setattr(
|
||||
AppAnnotationService,
|
||||
|
||||
@ -415,7 +415,7 @@ class TestChatRequestPayloadController:
|
||||
|
||||
|
||||
class TestCompletionApiController:
|
||||
def test_wrong_mode(self, app) -> None:
|
||||
def test_wrong_mode(self, app: Flask) -> None:
|
||||
api = CompletionApi()
|
||||
handler = _unwrap(api.post)
|
||||
app_model = SimpleNamespace(mode=AppMode.CHAT.value)
|
||||
@ -425,7 +425,7 @@ class TestCompletionApiController:
|
||||
with pytest.raises(AppUnavailableError):
|
||||
handler(api, app_model=app_model, end_user=end_user)
|
||||
|
||||
def test_conversation_not_found(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_conversation_not_found(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(
|
||||
AppGenerateService,
|
||||
"generate",
|
||||
@ -443,7 +443,7 @@ class TestCompletionApiController:
|
||||
|
||||
|
||||
class TestCompletionStopApiController:
|
||||
def test_wrong_mode(self, app) -> None:
|
||||
def test_wrong_mode(self, app: Flask) -> None:
|
||||
api = CompletionStopApi()
|
||||
handler = _unwrap(api.post)
|
||||
app_model = SimpleNamespace(mode=AppMode.CHAT.value)
|
||||
@ -453,7 +453,7 @@ class TestCompletionStopApiController:
|
||||
with pytest.raises(AppUnavailableError):
|
||||
handler(api, app_model=app_model, end_user=end_user, task_id="t1")
|
||||
|
||||
def test_success(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_success(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
stop_mock = Mock()
|
||||
monkeypatch.setattr(AppTaskService, "stop_task", stop_mock)
|
||||
|
||||
@ -470,7 +470,7 @@ class TestCompletionStopApiController:
|
||||
|
||||
|
||||
class TestChatApiController:
|
||||
def test_wrong_mode(self, app) -> None:
|
||||
def test_wrong_mode(self, app: Flask) -> None:
|
||||
api = ChatApi()
|
||||
handler = _unwrap(api.post)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION.value)
|
||||
@ -480,7 +480,7 @@ class TestChatApiController:
|
||||
with pytest.raises(NotChatAppError):
|
||||
handler(api, app_model=app_model, end_user=end_user)
|
||||
|
||||
def test_workflow_not_found(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_workflow_not_found(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(
|
||||
AppGenerateService,
|
||||
"generate",
|
||||
@ -496,7 +496,7 @@ class TestChatApiController:
|
||||
with pytest.raises(NotFound):
|
||||
handler(api, app_model=app_model, end_user=end_user)
|
||||
|
||||
def test_draft_workflow(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_draft_workflow(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(
|
||||
AppGenerateService,
|
||||
"generate",
|
||||
@ -514,10 +514,10 @@ class TestChatApiController:
|
||||
|
||||
|
||||
class TestChatStopApiController:
|
||||
def test_wrong_mode(self, app) -> None:
|
||||
def test_wrong_mode(self, app: Flask) -> None:
|
||||
api = ChatStopApi()
|
||||
handler = _unwrap(api.post)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION.value)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION)
|
||||
end_user = SimpleNamespace(id="u1")
|
||||
|
||||
with app.test_request_context("/chat-messages/1/stop", method="POST"):
|
||||
|
||||
@ -495,7 +495,7 @@ class TestConversationPayloadsController:
|
||||
|
||||
|
||||
class TestConversationApiController:
|
||||
def test_list_not_chat(self, app) -> None:
|
||||
def test_list_not_chat(self, app: Flask) -> None:
|
||||
api = ConversationApi()
|
||||
handler = _unwrap(api.get)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION)
|
||||
@ -543,7 +543,7 @@ class TestConversationApiController:
|
||||
|
||||
|
||||
class TestConversationDetailApiController:
|
||||
def test_delete_not_chat(self, app) -> None:
|
||||
def test_delete_not_chat(self, app: Flask) -> None:
|
||||
api = ConversationDetailApi()
|
||||
handler = _unwrap(api.delete)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION)
|
||||
@ -593,7 +593,7 @@ class TestConversationRenameApiController:
|
||||
|
||||
|
||||
class TestConversationVariablesApiController:
|
||||
def test_not_chat(self, app) -> None:
|
||||
def test_not_chat(self, app: Flask) -> None:
|
||||
api = ConversationVariablesApi()
|
||||
handler = _unwrap(api.get)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION)
|
||||
|
||||
@ -238,7 +238,7 @@ class TestFileApiPost:
|
||||
self,
|
||||
mock_db,
|
||||
mock_file_svc_cls,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_app_model,
|
||||
mock_end_user,
|
||||
):
|
||||
@ -342,7 +342,7 @@ class TestFileApiPost:
|
||||
self,
|
||||
mock_db,
|
||||
mock_file_svc_cls,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_app_model,
|
||||
mock_end_user,
|
||||
):
|
||||
@ -374,7 +374,7 @@ class TestFileApiPost:
|
||||
self,
|
||||
mock_db,
|
||||
mock_file_svc_cls,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_app_model,
|
||||
mock_end_user,
|
||||
):
|
||||
|
||||
@ -66,7 +66,7 @@ class TestFilePreviewApi:
|
||||
return message
|
||||
|
||||
def test_validate_file_ownership_success(
|
||||
self, file_preview_api, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
self, file_preview_api: FilePreviewApi, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
):
|
||||
"""Test successful file ownership validation"""
|
||||
file_id = str(uuid.uuid4())
|
||||
@ -97,7 +97,7 @@ class TestFilePreviewApi:
|
||||
assert result_message_file == mock_message_file
|
||||
assert result_upload_file == mock_upload_file
|
||||
|
||||
def test_validate_file_ownership_file_not_found(self, file_preview_api):
|
||||
def test_validate_file_ownership_file_not_found(self, file_preview_api: FilePreviewApi):
|
||||
"""Test file ownership validation when MessageFile not found"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
@ -112,7 +112,7 @@ class TestFilePreviewApi:
|
||||
|
||||
assert "File not found in message context" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_access_denied(self, file_preview_api, mock_message_file):
|
||||
def test_validate_file_ownership_access_denied(self, file_preview_api: FilePreviewApi, mock_message_file):
|
||||
"""Test file ownership validation when Message not owned by app"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
@ -130,7 +130,9 @@ class TestFilePreviewApi:
|
||||
|
||||
assert "not owned by requesting app" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_upload_file_not_found(self, file_preview_api, mock_message_file, mock_message):
|
||||
def test_validate_file_ownership_upload_file_not_found(
|
||||
self, file_preview_api: FilePreviewApi, mock_message_file, mock_message
|
||||
):
|
||||
"""Test file ownership validation when UploadFile not found"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
@ -151,7 +153,7 @@ class TestFilePreviewApi:
|
||||
assert "Upload file record not found" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_tenant_mismatch(
|
||||
self, file_preview_api, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
self, file_preview_api: FilePreviewApi, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
):
|
||||
"""Test file ownership validation with tenant mismatch"""
|
||||
file_id = str(uuid.uuid4())
|
||||
@ -182,7 +184,7 @@ class TestFilePreviewApi:
|
||||
|
||||
assert "tenant mismatch" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_invalid_input(self, file_preview_api):
|
||||
def test_validate_file_ownership_invalid_input(self, file_preview_api: FilePreviewApi):
|
||||
"""Test file ownership validation with invalid input"""
|
||||
|
||||
# Test with empty file_id
|
||||
@ -195,7 +197,7 @@ class TestFilePreviewApi:
|
||||
file_preview_api._validate_file_ownership("file_id", "")
|
||||
assert "Invalid file or app identifier" in str(exc_info.value)
|
||||
|
||||
def test_build_file_response_basic(self, file_preview_api, mock_upload_file):
|
||||
def test_build_file_response_basic(self, file_preview_api: FilePreviewApi, mock_upload_file):
|
||||
"""Test basic file response building"""
|
||||
mock_generator = Mock()
|
||||
|
||||
@ -207,7 +209,7 @@ class TestFilePreviewApi:
|
||||
assert response.headers["Content-Length"] == str(mock_upload_file.size)
|
||||
assert "Cache-Control" in response.headers
|
||||
|
||||
def test_build_file_response_as_attachment(self, file_preview_api, mock_upload_file):
|
||||
def test_build_file_response_as_attachment(self, file_preview_api: FilePreviewApi, mock_upload_file):
|
||||
"""Test file response building with attachment flag"""
|
||||
mock_generator = Mock()
|
||||
|
||||
@ -218,7 +220,7 @@ class TestFilePreviewApi:
|
||||
assert mock_upload_file.name in response.headers["Content-Disposition"]
|
||||
assert response.headers["Content-Type"] == "application/octet-stream"
|
||||
|
||||
def test_build_file_response_html_forces_attachment(self, file_preview_api, mock_upload_file):
|
||||
def test_build_file_response_html_forces_attachment(self, file_preview_api: FilePreviewApi, mock_upload_file):
|
||||
"""Test HTML files are forced to download"""
|
||||
mock_generator = Mock()
|
||||
mock_upload_file.mime_type = "text/html"
|
||||
@ -231,7 +233,7 @@ class TestFilePreviewApi:
|
||||
assert response.headers["Content-Type"] == "application/octet-stream"
|
||||
assert response.headers["X-Content-Type-Options"] == "nosniff"
|
||||
|
||||
def test_build_file_response_audio_video(self, file_preview_api, mock_upload_file):
|
||||
def test_build_file_response_audio_video(self, file_preview_api: FilePreviewApi, mock_upload_file):
|
||||
"""Test file response building for audio/video files"""
|
||||
mock_generator = Mock()
|
||||
mock_upload_file.mime_type = "video/mp4"
|
||||
@ -241,7 +243,7 @@ class TestFilePreviewApi:
|
||||
# Check Range support for media files
|
||||
assert response.headers["Accept-Ranges"] == "bytes"
|
||||
|
||||
def test_build_file_response_no_size(self, file_preview_api, mock_upload_file):
|
||||
def test_build_file_response_no_size(self, file_preview_api: FilePreviewApi, mock_upload_file):
|
||||
"""Test file response building when size is unknown"""
|
||||
mock_generator = Mock()
|
||||
mock_upload_file.size = 0 # Unknown size
|
||||
@ -253,7 +255,14 @@ class TestFilePreviewApi:
|
||||
|
||||
@patch("controllers.service_api.app.file_preview.storage")
|
||||
def test_get_method_integration(
|
||||
self, mock_storage, file_preview_api, mock_app, mock_end_user, mock_upload_file, mock_message_file, mock_message
|
||||
self,
|
||||
mock_storage,
|
||||
file_preview_api: FilePreviewApi,
|
||||
mock_app,
|
||||
mock_end_user,
|
||||
mock_upload_file,
|
||||
mock_message_file,
|
||||
mock_message,
|
||||
):
|
||||
"""Test the full GET method integration (without decorator)"""
|
||||
file_id = str(uuid.uuid4())
|
||||
@ -295,7 +304,13 @@ class TestFilePreviewApi:
|
||||
|
||||
@patch("controllers.service_api.app.file_preview.storage")
|
||||
def test_storage_error_handling(
|
||||
self, mock_storage, file_preview_api, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
self,
|
||||
mock_storage,
|
||||
file_preview_api: FilePreviewApi,
|
||||
mock_app,
|
||||
mock_upload_file,
|
||||
mock_message_file,
|
||||
mock_message,
|
||||
):
|
||||
"""Test storage error handling in the core logic"""
|
||||
file_id = str(uuid.uuid4())
|
||||
@ -334,7 +349,7 @@ class TestFilePreviewApi:
|
||||
assert "Storage error" in str(exc_info.value)
|
||||
|
||||
@patch("controllers.service_api.app.file_preview.logger")
|
||||
def test_validate_file_ownership_unexpected_error_logging(self, mock_logger, file_preview_api):
|
||||
def test_validate_file_ownership_unexpected_error_logging(self, mock_logger, file_preview_api: FilePreviewApi):
|
||||
"""Test that unexpected errors are logged properly"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
|
||||
@ -249,7 +249,9 @@ def _build_resumption_context(task_id: str) -> WorkflowResumptionContext:
|
||||
|
||||
class TestHitlServiceApi:
|
||||
# Service API event-stream continuation
|
||||
def test_workflow_events_continue_on_pause_keeps_stream_open(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_workflow_events_continue_on_pause_keeps_stream_open(
|
||||
self, app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
workflow_run = SimpleNamespace(
|
||||
id="run-1",
|
||||
app_id="app-1",
|
||||
|
||||
@ -9,6 +9,7 @@ from types import SimpleNamespace
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from controllers.service_api.app.human_input_form import WorkflowHumanInputFormApi
|
||||
@ -17,7 +18,7 @@ from tests.unit_tests.controllers.service_api.conftest import _unwrap
|
||||
|
||||
|
||||
class TestWorkflowHumanInputFormApi:
|
||||
def test_get_success(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_get_success(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
definition = SimpleNamespace(
|
||||
model_dump=lambda: {
|
||||
"rendered_content": "Rendered form content",
|
||||
@ -57,7 +58,7 @@ class TestWorkflowHumanInputFormApi:
|
||||
service_mock.get_form_by_token.assert_called_once_with("token-1")
|
||||
service_mock.ensure_form_active.assert_called_once_with(form)
|
||||
|
||||
def test_get_form_not_in_app(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_get_form_not_in_app(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
form = SimpleNamespace(
|
||||
app_id="another-app",
|
||||
tenant_id="tenant-1",
|
||||
@ -87,7 +88,7 @@ class TestWorkflowHumanInputFormApi:
|
||||
],
|
||||
)
|
||||
def test_get_rejects_non_service_api_recipient_types(
|
||||
self, app, monkeypatch: pytest.MonkeyPatch, recipient_type: RecipientType
|
||||
self, app: Flask, monkeypatch: pytest.MonkeyPatch, recipient_type: RecipientType
|
||||
) -> None:
|
||||
form = SimpleNamespace(
|
||||
app_id="app-1",
|
||||
@ -111,7 +112,7 @@ class TestWorkflowHumanInputFormApi:
|
||||
|
||||
service_mock.ensure_form_active.assert_not_called()
|
||||
|
||||
def test_post_success(self, app, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_post_success(self, app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
form = SimpleNamespace(
|
||||
app_id="app-1",
|
||||
tenant_id="tenant-1",
|
||||
@ -155,7 +156,7 @@ class TestWorkflowHumanInputFormApi:
|
||||
],
|
||||
)
|
||||
def test_post_rejects_non_service_api_recipient_types(
|
||||
self, app, monkeypatch: pytest.MonkeyPatch, recipient_type: RecipientType
|
||||
self, app: Flask, monkeypatch: pytest.MonkeyPatch, recipient_type: RecipientType
|
||||
) -> None:
|
||||
form = SimpleNamespace(
|
||||
app_id="app-1",
|
||||
|
||||
@ -381,7 +381,7 @@ class TestMessageService:
|
||||
|
||||
|
||||
class TestMessageListApi:
|
||||
def test_not_chat_app(self, app) -> None:
|
||||
def test_not_chat_app(self, app: Flask) -> None:
|
||||
api = MessageListApi()
|
||||
handler = _unwrap(api.get)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION.value)
|
||||
@ -467,7 +467,7 @@ class TestAppGetFeedbacksApi:
|
||||
|
||||
|
||||
class TestMessageSuggestedApi:
|
||||
def test_not_chat(self, app) -> None:
|
||||
def test_not_chat(self, app: Flask) -> None:
|
||||
api = MessageSuggestedApi()
|
||||
handler = _unwrap(api.get)
|
||||
app_model = SimpleNamespace(mode=AppMode.COMPLETION.value)
|
||||
|
||||
@ -32,7 +32,7 @@ def _mock_repo_for_run(monkeypatch: pytest.MonkeyPatch, workflow_run):
|
||||
|
||||
|
||||
class TestWorkflowEventsApi:
|
||||
def test_wrong_app_mode(self, app) -> None:
|
||||
def test_wrong_app_mode(self, app: Flask) -> None:
|
||||
api = WorkflowEventsApi()
|
||||
handler = _unwrap(api.get)
|
||||
app_model = SimpleNamespace(mode=AppMode.CHAT.value)
|
||||
|
||||
@ -19,6 +19,7 @@ import uuid
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import Forbidden, NotFound
|
||||
|
||||
from controllers.service_api.dataset.document import (
|
||||
@ -550,7 +551,7 @@ class TestDocumentApiGet:
|
||||
@patch("controllers.service_api.dataset.document.DatasetService")
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
def test_get_document_success_with_all_metadata(
|
||||
self, mock_doc_svc, mock_dataset_svc, app, mock_tenant, mock_doc_detail
|
||||
self, mock_doc_svc, mock_dataset_svc, app: Flask, mock_tenant, mock_doc_detail
|
||||
):
|
||||
"""Test successful document retrieval with metadata='all'."""
|
||||
# Arrange
|
||||
@ -579,7 +580,7 @@ class TestDocumentApiGet:
|
||||
assert "doc_metadata" in response
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
def test_get_document_not_found(self, mock_doc_svc, app, mock_tenant):
|
||||
def test_get_document_not_found(self, mock_doc_svc, app: Flask, mock_tenant):
|
||||
"""Test 404 when document is not found."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -599,7 +600,7 @@ class TestDocumentApiGet:
|
||||
api.get(tenant_id=mock_tenant.id, dataset_id=dataset_id, document_id="nonexistent")
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
def test_get_document_forbidden_wrong_tenant(self, mock_doc_svc, app, mock_tenant, mock_doc_detail):
|
||||
def test_get_document_forbidden_wrong_tenant(self, mock_doc_svc, app: Flask, mock_tenant, mock_doc_detail):
|
||||
"""Test 403 when document tenant doesn't match request tenant."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -620,7 +621,7 @@ class TestDocumentApiGet:
|
||||
api.get(tenant_id=mock_tenant.id, dataset_id=dataset_id, document_id=mock_doc_detail.id)
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
def test_get_document_metadata_only(self, mock_doc_svc, app, mock_tenant, mock_doc_detail):
|
||||
def test_get_document_metadata_only(self, mock_doc_svc, app: Flask, mock_tenant, mock_doc_detail):
|
||||
"""Test document retrieval with metadata='only'."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -647,7 +648,9 @@ class TestDocumentApiGet:
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DatasetService")
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
def test_get_document_metadata_without(self, mock_doc_svc, mock_dataset_svc, app, mock_tenant, mock_doc_detail):
|
||||
def test_get_document_metadata_without(
|
||||
self, mock_doc_svc, mock_dataset_svc, app: Flask, mock_tenant, mock_doc_detail
|
||||
):
|
||||
"""Test document retrieval with metadata='without'."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -674,7 +677,7 @@ class TestDocumentApiGet:
|
||||
assert "name" in response
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
def test_get_document_invalid_metadata_value(self, mock_doc_svc, app, mock_tenant, mock_doc_detail):
|
||||
def test_get_document_invalid_metadata_value(self, mock_doc_svc, app: Flask, mock_tenant, mock_doc_detail):
|
||||
"""Test error when metadata parameter has invalid value."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -713,7 +716,7 @@ class TestDocumentApiDelete:
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_delete_document_success(self, mock_db, mock_doc_svc, app, mock_tenant, mock_document):
|
||||
def test_delete_document_success(self, mock_db, mock_doc_svc, app: Flask, mock_tenant, mock_document):
|
||||
"""Test successful document deletion."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -741,7 +744,7 @@ class TestDocumentApiDelete:
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_delete_document_not_found(self, mock_db, mock_doc_svc, app, mock_tenant):
|
||||
def test_delete_document_not_found(self, mock_db, mock_doc_svc, app: Flask, mock_tenant):
|
||||
"""Test 404 when document not found."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -763,7 +766,7 @@ class TestDocumentApiDelete:
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_delete_document_archived_forbidden(self, mock_db, mock_doc_svc, app, mock_tenant, mock_document):
|
||||
def test_delete_document_archived_forbidden(self, mock_db, mock_doc_svc, app: Flask, mock_tenant, mock_document):
|
||||
"""Test ArchivedDocumentImmutableError when deleting archived document."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -785,7 +788,7 @@ class TestDocumentApiDelete:
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_delete_document_dataset_not_found(self, mock_db, mock_doc_svc, app, mock_tenant):
|
||||
def test_delete_document_dataset_not_found(self, mock_db, mock_doc_svc, app: Flask, mock_tenant):
|
||||
"""Test ValueError when dataset not found."""
|
||||
# Arrange
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -808,7 +811,7 @@ class TestDocumentListApi:
|
||||
@patch("controllers.service_api.dataset.document.marshal")
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_list_documents_success(self, mock_db, mock_doc_svc, mock_marshal, app, mock_tenant, mock_dataset):
|
||||
def test_list_documents_success(self, mock_db, mock_doc_svc, mock_marshal, app: Flask, mock_tenant, mock_dataset):
|
||||
"""Test successful document list retrieval."""
|
||||
# Arrange
|
||||
mock_db.session.scalar.return_value = mock_dataset
|
||||
@ -837,7 +840,7 @@ class TestDocumentListApi:
|
||||
assert response["total"] == 2
|
||||
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_list_documents_dataset_not_found(self, mock_db, app, mock_tenant, mock_dataset):
|
||||
def test_list_documents_dataset_not_found(self, mock_db, app: Flask, mock_tenant, mock_dataset):
|
||||
"""Test 404 when dataset not found."""
|
||||
# Arrange
|
||||
mock_db.session.scalar.return_value = None
|
||||
@ -858,7 +861,9 @@ class TestDocumentIndexingStatusApi:
|
||||
@patch("controllers.service_api.dataset.document.marshal")
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_get_indexing_status_success(self, mock_db, mock_doc_svc, mock_marshal, app, mock_tenant, mock_dataset):
|
||||
def test_get_indexing_status_success(
|
||||
self, mock_db, mock_doc_svc, mock_marshal, app: Flask, mock_tenant, mock_dataset
|
||||
):
|
||||
"""Test successful indexing status retrieval."""
|
||||
# Arrange
|
||||
batch_id = "batch_123"
|
||||
@ -894,7 +899,7 @@ class TestDocumentIndexingStatusApi:
|
||||
assert len(response["data"]) == 1
|
||||
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_get_indexing_status_dataset_not_found(self, mock_db, app, mock_tenant, mock_dataset):
|
||||
def test_get_indexing_status_dataset_not_found(self, mock_db, app: Flask, mock_tenant, mock_dataset):
|
||||
"""Test 404 when dataset not found."""
|
||||
# Arrange
|
||||
batch_id = "batch_123"
|
||||
@ -911,7 +916,9 @@ class TestDocumentIndexingStatusApi:
|
||||
|
||||
@patch("controllers.service_api.dataset.document.DocumentService")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_get_indexing_status_documents_not_found(self, mock_db, mock_doc_svc, app, mock_tenant, mock_dataset):
|
||||
def test_get_indexing_status_documents_not_found(
|
||||
self, mock_db, mock_doc_svc, app: Flask, mock_tenant, mock_dataset
|
||||
):
|
||||
"""Test 404 when no documents found for batch."""
|
||||
# Arrange
|
||||
batch_id = "batch_empty"
|
||||
@ -978,7 +985,7 @@ class TestDocumentAddByTextApi:
|
||||
mock_knowledge_config,
|
||||
mock_doc_svc,
|
||||
mock_marshal,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1029,7 +1036,7 @@ class TestDocumentAddByTextApi:
|
||||
@patch("controllers.service_api.wraps.validate_and_get_api_token")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_create_document_dataset_not_found(
|
||||
self, mock_db, mock_validate_token, mock_feature_svc, app, mock_tenant, mock_dataset
|
||||
self, mock_db, mock_validate_token, mock_feature_svc, app: Flask, mock_tenant, mock_dataset
|
||||
):
|
||||
"""Test ValueError when dataset not found."""
|
||||
# Arrange — neutralise billing decorators
|
||||
@ -1052,7 +1059,7 @@ class TestDocumentAddByTextApi:
|
||||
@patch("controllers.service_api.wraps.validate_and_get_api_token")
|
||||
@patch("controllers.service_api.dataset.document.db")
|
||||
def test_create_document_missing_indexing_technique(
|
||||
self, mock_db, mock_validate_token, mock_feature_svc, app, mock_tenant, mock_dataset
|
||||
self, mock_db, mock_validate_token, mock_feature_svc, app: Flask, mock_tenant, mock_dataset
|
||||
):
|
||||
"""Test error when both dataset and payload lack indexing_technique.
|
||||
|
||||
@ -1161,7 +1168,7 @@ class TestDocumentUpdateByTextApiPost:
|
||||
mock_file_svc_cls,
|
||||
mock_doc_svc,
|
||||
mock_marshal,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1206,7 +1213,7 @@ class TestDocumentUpdateByTextApiPost:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1245,7 +1252,7 @@ class TestDocumentAddByFileApiPost:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1275,7 +1282,7 @@ class TestDocumentAddByFileApiPost:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1306,7 +1313,7 @@ class TestDocumentAddByFileApiPost:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1338,7 +1345,7 @@ class TestDocumentAddByFileApiPost:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1381,7 +1388,7 @@ class TestDocumentUpdateByFileApiPatch:
|
||||
mock_feature_svc,
|
||||
mock_update_document_by_file,
|
||||
route_name,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1418,7 +1425,7 @@ class TestDocumentUpdateByFileApiPatch:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1453,7 +1460,7 @@ class TestDocumentUpdateByFileApiPatch:
|
||||
mock_validate_token,
|
||||
mock_feature_svc,
|
||||
mock_db,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
@ -1497,7 +1504,7 @@ class TestDocumentUpdateByFileApiPatch:
|
||||
mock_file_svc_cls,
|
||||
mock_doc_svc,
|
||||
mock_marshal,
|
||||
app,
|
||||
app: Flask,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
):
|
||||
|
||||
@ -18,6 +18,7 @@ import uuid
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import Forbidden, NotFound
|
||||
|
||||
import services
|
||||
@ -91,7 +92,7 @@ class TestHitTestingApiPost:
|
||||
mock_hit_svc,
|
||||
mock_marshal,
|
||||
mock_ns,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
"""Test successful hit testing request."""
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -129,7 +130,7 @@ class TestHitTestingApiPost:
|
||||
mock_hit_svc,
|
||||
mock_marshal,
|
||||
mock_ns,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
"""Test hit testing with custom retrieval model."""
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -183,7 +184,7 @@ class TestHitTestingApiPost:
|
||||
mock_hit_svc,
|
||||
mock_marshal,
|
||||
mock_ns,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
"""Service API retrieval payload should not drop metadata filters."""
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -239,7 +240,7 @@ class TestHitTestingApiPost:
|
||||
mock_hit_svc,
|
||||
mock_marshal,
|
||||
mock_ns,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
"""Test service API prepares nullable list fields from marshalled records."""
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -286,7 +287,7 @@ class TestHitTestingApiPost:
|
||||
mock_current_user,
|
||||
mock_dataset_svc,
|
||||
mock_ns,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
"""Test hit testing with non-existent dataset."""
|
||||
dataset_id = str(uuid.uuid4())
|
||||
@ -308,7 +309,7 @@ class TestHitTestingApiPost:
|
||||
mock_current_user,
|
||||
mock_dataset_svc,
|
||||
mock_ns,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
"""Test hit testing when user lacks dataset permission."""
|
||||
dataset_id = str(uuid.uuid4())
|
||||
|
||||
@ -54,7 +54,7 @@ class TestIndexApi:
|
||||
assert isinstance(response["server_version"], str)
|
||||
|
||||
@pytest.mark.parametrize("version", ["0.0.1", "1.0.0", "2.0.0-beta", "1.11.4"])
|
||||
def test_get_returns_correct_version(self, app, version):
|
||||
def test_get_returns_correct_version(self, app: Flask, version):
|
||||
"""Test that server_version matches config version."""
|
||||
# Arrange
|
||||
mock_config = MagicMock()
|
||||
|
||||
@ -44,7 +44,7 @@ class TestEmailCodeLoginSendEmailApi:
|
||||
self,
|
||||
mock_get_user,
|
||||
mock_send_email,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
mock_account = MagicMock()
|
||||
mock_get_user.return_value = mock_account
|
||||
@ -75,7 +75,7 @@ class TestEmailCodeLoginApi:
|
||||
mock_get_user,
|
||||
mock_login,
|
||||
mock_reset_login_rate,
|
||||
app,
|
||||
app: Flask,
|
||||
):
|
||||
mock_get_token_data.return_value = {"email": "User@Example.com", "code": "123456"}
|
||||
mock_get_user.return_value = MagicMock()
|
||||
|
||||
@ -8,14 +8,14 @@
|
||||
|
||||
Snapshot generated from `packages/contracts/generated/api/readiness.json` after running `pnpm -C packages/contracts gen-api-contract-from-openapi`.
|
||||
|
||||
Are we OpenAPI ready? **No.** Current generated API contracts are **16.6% ready**.
|
||||
Are we OpenAPI ready? **No.** Current generated API contracts are **16.7% ready**.
|
||||
|
||||
| Surface | Ready | Not ready | Total | Ready % |
|
||||
| --------- | ------: | --------: | ------: | --------: |
|
||||
| console | 95 | 475 | 570 | 16.7% |
|
||||
| console | 96 | 474 | 570 | 16.8% |
|
||||
| service | 16 | 72 | 88 | 18.2% |
|
||||
| web | 5 | 36 | 41 | 12.2% |
|
||||
| **total** | **116** | **583** | **699** | **16.6%** |
|
||||
| **total** | **117** | **582** | **699** | **16.7%** |
|
||||
|
||||
Readiness here means the generated contract operation is not marked with:
|
||||
|
||||
|
||||
@ -426,16 +426,10 @@ export const imports = {
|
||||
|
||||
/**
|
||||
* Get workflow online users
|
||||
*
|
||||
* Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const post3 = oc
|
||||
.route({
|
||||
deprecated: true,
|
||||
description:
|
||||
'Get workflow online users\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.',
|
||||
description: 'Get workflow online users',
|
||||
inputStructure: 'detailed',
|
||||
method: 'POST',
|
||||
operationId: 'postAppsWorkflowsOnlineUsers',
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"surfaces": {
|
||||
"console": {
|
||||
"notReady": 475,
|
||||
"notReady": 474,
|
||||
"total": 570
|
||||
},
|
||||
"service": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user