Feature add test containers tool transform service (#24927)
This commit is contained in:
@@ -0,0 +1,788 @@
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from core.tools.entities.api_entities import ToolProviderApiEntity
|
||||
from core.tools.entities.common_entities import I18nObject
|
||||
from core.tools.entities.tool_entities import ToolProviderType
|
||||
from models.tools import ApiToolProvider, BuiltinToolProvider, MCPToolProvider, WorkflowToolProvider
|
||||
from services.tools.tools_transform_service import ToolTransformService
|
||||
|
||||
|
||||
class TestToolTransformService:
|
||||
"""Integration tests for ToolTransformService using testcontainers."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_external_service_dependencies(self):
|
||||
"""Mock setup for external service dependencies."""
|
||||
with (
|
||||
patch("services.tools.tools_transform_service.dify_config") as mock_dify_config,
|
||||
):
|
||||
# Setup default mock returns
|
||||
mock_dify_config.CONSOLE_API_URL = "https://console.example.com"
|
||||
|
||||
yield {
|
||||
"dify_config": mock_dify_config,
|
||||
}
|
||||
|
||||
def _create_test_tool_provider(
|
||||
self, db_session_with_containers, mock_external_service_dependencies, provider_type="api"
|
||||
):
|
||||
"""
|
||||
Helper method to create a test tool provider for testing.
|
||||
|
||||
Args:
|
||||
db_session_with_containers: Database session from testcontainers infrastructure
|
||||
mock_external_service_dependencies: Mock dependencies
|
||||
provider_type: Type of provider to create
|
||||
|
||||
Returns:
|
||||
Tool provider instance
|
||||
"""
|
||||
fake = Faker()
|
||||
|
||||
if provider_type == "api":
|
||||
provider = ApiToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
icon_dark='{"background": "#252525", "content": "🔧"}',
|
||||
tenant_id="test_tenant_id",
|
||||
user_id="test_user_id",
|
||||
credentials={"auth_type": "api_key_header", "api_key": "test_key"},
|
||||
provider_type="api",
|
||||
)
|
||||
elif provider_type == "builtin":
|
||||
provider = BuiltinToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon="🔧",
|
||||
icon_dark="🔧",
|
||||
tenant_id="test_tenant_id",
|
||||
provider="test_provider",
|
||||
credential_type="api_key",
|
||||
credentials={"api_key": "test_key"},
|
||||
)
|
||||
elif provider_type == "workflow":
|
||||
provider = WorkflowToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
icon_dark='{"background": "#252525", "content": "🔧"}',
|
||||
tenant_id="test_tenant_id",
|
||||
user_id="test_user_id",
|
||||
workflow_id="test_workflow_id",
|
||||
)
|
||||
elif provider_type == "mcp":
|
||||
provider = MCPToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
provider_icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
tenant_id="test_tenant_id",
|
||||
user_id="test_user_id",
|
||||
server_url="https://mcp.example.com",
|
||||
server_identifier="test_server",
|
||||
tools='[{"name": "test_tool", "description": "Test tool"}]',
|
||||
authed=True,
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown provider type: {provider_type}")
|
||||
|
||||
from extensions.ext_database import db
|
||||
|
||||
db.session.add(provider)
|
||||
db.session.commit()
|
||||
|
||||
return provider
|
||||
|
||||
def test_get_plugin_icon_url_success(self, db_session_with_containers, mock_external_service_dependencies):
|
||||
"""
|
||||
Test successful plugin icon URL generation.
|
||||
|
||||
This test verifies:
|
||||
- Proper URL construction for plugin icons
|
||||
- Correct tenant_id and filename handling
|
||||
- URL format compliance
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
tenant_id = fake.uuid4()
|
||||
filename = "test_icon.png"
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_plugin_icon_url(tenant_id, filename)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
assert "console/api/workspaces/current/plugin/icon" in result
|
||||
assert tenant_id in result
|
||||
assert filename in result
|
||||
assert result.startswith("https://console.example.com")
|
||||
|
||||
# Verify URL structure
|
||||
expected_url = f"https://console.example.com/console/api/workspaces/current/plugin/icon?tenant_id={tenant_id}&filename={filename}"
|
||||
assert result == expected_url
|
||||
|
||||
def test_get_plugin_icon_url_with_empty_console_url(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test plugin icon URL generation when CONSOLE_API_URL is empty.
|
||||
|
||||
This test verifies:
|
||||
- Fallback to relative URL when CONSOLE_API_URL is None
|
||||
- Proper URL construction with relative path
|
||||
"""
|
||||
# Arrange: Setup mock with empty console URL
|
||||
mock_external_service_dependencies["dify_config"].CONSOLE_API_URL = None
|
||||
fake = Faker()
|
||||
tenant_id = fake.uuid4()
|
||||
filename = "test_icon.png"
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_plugin_icon_url(tenant_id, filename)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
assert result.startswith("/console/api/workspaces/current/plugin/icon")
|
||||
assert tenant_id in result
|
||||
assert filename in result
|
||||
|
||||
# Verify URL structure
|
||||
expected_url = f"/console/api/workspaces/current/plugin/icon?tenant_id={tenant_id}&filename={filename}"
|
||||
assert result == expected_url
|
||||
|
||||
def test_get_tool_provider_icon_url_builtin_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful tool provider icon URL generation for builtin providers.
|
||||
|
||||
This test verifies:
|
||||
- Proper URL construction for builtin tool providers
|
||||
- Correct provider type handling
|
||||
- URL format compliance
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
provider_type = ToolProviderType.BUILT_IN.value
|
||||
provider_name = fake.company()
|
||||
icon = "🔧"
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_tool_provider_icon_url(provider_type, provider_name, icon)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
assert "console/api/workspaces/current/tool-provider/builtin" in result
|
||||
# Note: provider_name may contain spaces that get URL encoded
|
||||
assert provider_name.replace(" ", "%20") in result or provider_name in result
|
||||
assert result.endswith("/icon")
|
||||
assert result.startswith("https://console.example.com")
|
||||
|
||||
# Verify URL structure (accounting for URL encoding)
|
||||
# The actual result will have URL-encoded spaces (%20), so we need to compare accordingly
|
||||
expected_url = (
|
||||
f"https://console.example.com/console/api/workspaces/current/tool-provider/builtin/{provider_name}/icon"
|
||||
)
|
||||
# Convert expected URL to match the actual URL encoding
|
||||
expected_encoded = expected_url.replace(" ", "%20")
|
||||
assert result == expected_encoded
|
||||
|
||||
def test_get_tool_provider_icon_url_api_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful tool provider icon URL generation for API providers.
|
||||
|
||||
This test verifies:
|
||||
- Proper icon handling for API tool providers
|
||||
- JSON string parsing for icon data
|
||||
- Fallback icon when parsing fails
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
provider_type = ToolProviderType.API.value
|
||||
provider_name = fake.company()
|
||||
icon = '{"background": "#FF6B6B", "content": "🔧"}'
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_tool_provider_icon_url(provider_type, provider_name, icon)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, dict)
|
||||
assert result["background"] == "#FF6B6B"
|
||||
assert result["content"] == "🔧"
|
||||
|
||||
def test_get_tool_provider_icon_url_api_invalid_json(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test tool provider icon URL generation for API providers with invalid JSON.
|
||||
|
||||
This test verifies:
|
||||
- Proper fallback when JSON parsing fails
|
||||
- Default icon structure when exception occurs
|
||||
"""
|
||||
# Arrange: Setup test data with invalid JSON
|
||||
fake = Faker()
|
||||
provider_type = ToolProviderType.API.value
|
||||
provider_name = fake.company()
|
||||
icon = '{"invalid": json}'
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_tool_provider_icon_url(provider_type, provider_name, icon)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, dict)
|
||||
assert result["background"] == "#252525"
|
||||
# Note: emoji characters may be represented as Unicode escape sequences
|
||||
assert result["content"] == "😁" or result["content"] == "\ud83d\ude01"
|
||||
|
||||
def test_get_tool_provider_icon_url_workflow_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful tool provider icon URL generation for workflow providers.
|
||||
|
||||
This test verifies:
|
||||
- Proper icon handling for workflow tool providers
|
||||
- Direct icon return for workflow type
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
provider_type = ToolProviderType.WORKFLOW.value
|
||||
provider_name = fake.company()
|
||||
icon = {"background": "#FF6B6B", "content": "🔧"}
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_tool_provider_icon_url(provider_type, provider_name, icon)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, dict)
|
||||
assert result["background"] == "#FF6B6B"
|
||||
assert result["content"] == "🔧"
|
||||
|
||||
def test_get_tool_provider_icon_url_mcp_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful tool provider icon URL generation for MCP providers.
|
||||
|
||||
This test verifies:
|
||||
- Direct icon return for MCP type
|
||||
- No URL transformation for MCP providers
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
provider_type = ToolProviderType.MCP.value
|
||||
provider_name = fake.company()
|
||||
icon = {"background": "#FF6B6B", "content": "🔧"}
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_tool_provider_icon_url(provider_type, provider_name, icon)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert isinstance(result, dict)
|
||||
assert result["background"] == "#FF6B6B"
|
||||
assert result["content"] == "🔧"
|
||||
|
||||
def test_get_tool_provider_icon_url_unknown_type(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test tool provider icon URL generation for unknown provider types.
|
||||
|
||||
This test verifies:
|
||||
- Empty string return for unknown provider types
|
||||
- Proper handling of unsupported types
|
||||
"""
|
||||
# Arrange: Setup test data with unknown type
|
||||
fake = Faker()
|
||||
provider_type = "unknown_type"
|
||||
provider_name = fake.company()
|
||||
icon = "🔧"
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.get_tool_provider_icon_url(provider_type, provider_name, icon)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result == ""
|
||||
|
||||
def test_repack_provider_dict_success(self, db_session_with_containers, mock_external_service_dependencies):
|
||||
"""
|
||||
Test successful provider repacking with dictionary input.
|
||||
|
||||
This test verifies:
|
||||
- Proper icon URL generation for dictionary providers
|
||||
- Correct provider type handling
|
||||
- Icon transformation for different provider types
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
tenant_id = fake.uuid4()
|
||||
provider = {"type": ToolProviderType.BUILT_IN.value, "name": fake.company(), "icon": "🔧"}
|
||||
|
||||
# Act: Execute the method under test
|
||||
ToolTransformService.repack_provider(tenant_id, provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert "icon" in provider
|
||||
assert isinstance(provider["icon"], str)
|
||||
assert "console/api/workspaces/current/tool-provider/builtin" in provider["icon"]
|
||||
# Note: provider name may contain spaces that get URL encoded
|
||||
assert provider["name"].replace(" ", "%20") in provider["icon"] or provider["name"] in provider["icon"]
|
||||
|
||||
def test_repack_provider_entity_success(self, db_session_with_containers, mock_external_service_dependencies):
|
||||
"""
|
||||
Test successful provider repacking with ToolProviderApiEntity input.
|
||||
|
||||
This test verifies:
|
||||
- Proper icon URL generation for entity providers
|
||||
- Plugin icon handling when plugin_id is present
|
||||
- Regular icon handling when plugin_id is not present
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
tenant_id = fake.uuid4()
|
||||
|
||||
# Create provider entity with plugin_id
|
||||
provider = ToolProviderApiEntity(
|
||||
id=fake.uuid4(),
|
||||
author=fake.name(),
|
||||
name=fake.company(),
|
||||
description=I18nObject(en_US=fake.text(max_nb_chars=100)),
|
||||
icon="test_icon.png",
|
||||
icon_dark="test_icon_dark.png",
|
||||
label=I18nObject(en_US=fake.company()),
|
||||
type=ToolProviderType.API,
|
||||
masked_credentials={},
|
||||
is_team_authorization=True,
|
||||
plugin_id="test_plugin_id",
|
||||
tools=[],
|
||||
labels=[],
|
||||
)
|
||||
|
||||
# Act: Execute the method under test
|
||||
ToolTransformService.repack_provider(tenant_id, provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert provider.icon is not None
|
||||
assert isinstance(provider.icon, str)
|
||||
assert "console/api/workspaces/current/plugin/icon" in provider.icon
|
||||
assert tenant_id in provider.icon
|
||||
assert "test_icon.png" in provider.icon
|
||||
|
||||
# Verify dark icon handling
|
||||
assert provider.icon_dark is not None
|
||||
assert isinstance(provider.icon_dark, str)
|
||||
assert "console/api/workspaces/current/plugin/icon" in provider.icon_dark
|
||||
assert tenant_id in provider.icon_dark
|
||||
assert "test_icon_dark.png" in provider.icon_dark
|
||||
|
||||
def test_repack_provider_entity_no_plugin_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful provider repacking with ToolProviderApiEntity input without plugin_id.
|
||||
|
||||
This test verifies:
|
||||
- Proper icon URL generation for non-plugin providers
|
||||
- Regular tool provider icon handling
|
||||
- Dark icon handling when present
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
tenant_id = fake.uuid4()
|
||||
|
||||
# Create provider entity without plugin_id
|
||||
provider = ToolProviderApiEntity(
|
||||
id=fake.uuid4(),
|
||||
author=fake.name(),
|
||||
name=fake.company(),
|
||||
description=I18nObject(en_US=fake.text(max_nb_chars=100)),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
icon_dark='{"background": "#252525", "content": "🔧"}',
|
||||
label=I18nObject(en_US=fake.company()),
|
||||
type=ToolProviderType.API,
|
||||
masked_credentials={},
|
||||
is_team_authorization=True,
|
||||
plugin_id=None,
|
||||
tools=[],
|
||||
labels=[],
|
||||
)
|
||||
|
||||
# Act: Execute the method under test
|
||||
ToolTransformService.repack_provider(tenant_id, provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert provider.icon is not None
|
||||
assert isinstance(provider.icon, dict)
|
||||
assert provider.icon["background"] == "#FF6B6B"
|
||||
assert provider.icon["content"] == "🔧"
|
||||
|
||||
# Verify dark icon handling
|
||||
assert provider.icon_dark is not None
|
||||
assert isinstance(provider.icon_dark, dict)
|
||||
assert provider.icon_dark["background"] == "#252525"
|
||||
assert provider.icon_dark["content"] == "🔧"
|
||||
|
||||
def test_repack_provider_entity_no_dark_icon(self, db_session_with_containers, mock_external_service_dependencies):
|
||||
"""
|
||||
Test provider repacking with ToolProviderApiEntity input without dark icon.
|
||||
|
||||
This test verifies:
|
||||
- Proper handling when icon_dark is None or empty
|
||||
- No errors when dark icon is not present
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
tenant_id = fake.uuid4()
|
||||
|
||||
# Create provider entity without dark icon
|
||||
provider = ToolProviderApiEntity(
|
||||
id=fake.uuid4(),
|
||||
author=fake.name(),
|
||||
name=fake.company(),
|
||||
description=I18nObject(en_US=fake.text(max_nb_chars=100)),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
icon_dark=None,
|
||||
label=I18nObject(en_US=fake.company()),
|
||||
type=ToolProviderType.API,
|
||||
masked_credentials={},
|
||||
is_team_authorization=True,
|
||||
plugin_id=None,
|
||||
tools=[],
|
||||
labels=[],
|
||||
)
|
||||
|
||||
# Act: Execute the method under test
|
||||
ToolTransformService.repack_provider(tenant_id, provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert provider.icon is not None
|
||||
assert isinstance(provider.icon, dict)
|
||||
assert provider.icon["background"] == "#FF6B6B"
|
||||
assert provider.icon["content"] == "🔧"
|
||||
|
||||
# Verify dark icon remains None
|
||||
assert provider.icon_dark is None
|
||||
|
||||
def test_builtin_provider_to_user_provider_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful conversion of builtin provider to user provider.
|
||||
|
||||
This test verifies:
|
||||
- Proper entity creation with all required fields
|
||||
- Credentials schema handling
|
||||
- Team authorization setup
|
||||
- Plugin ID handling
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create mock provider controller
|
||||
mock_controller = Mock()
|
||||
mock_controller.entity.identity.name = fake.company()
|
||||
mock_controller.entity.identity.author = fake.name()
|
||||
mock_controller.entity.identity.description = I18nObject(en_US=fake.text(max_nb_chars=100))
|
||||
mock_controller.entity.identity.icon = "🔧"
|
||||
mock_controller.entity.identity.icon_dark = "🔧"
|
||||
mock_controller.entity.identity.label = I18nObject(en_US=fake.company())
|
||||
mock_controller.plugin_id = None
|
||||
mock_controller.plugin_unique_identifier = None
|
||||
mock_controller.tool_labels = ["label1", "label2"]
|
||||
mock_controller.need_credentials = True
|
||||
|
||||
# Mock credentials schema
|
||||
mock_credential = Mock()
|
||||
mock_credential.to_basic_provider_config.return_value.name = "api_key"
|
||||
mock_controller.get_credentials_schema_by_type.return_value = [mock_credential]
|
||||
|
||||
# Create mock database provider
|
||||
mock_db_provider = Mock()
|
||||
mock_db_provider.credential_type = "api-key"
|
||||
mock_db_provider.tenant_id = fake.uuid4()
|
||||
mock_db_provider.credentials = {"api_key": "encrypted_key"}
|
||||
|
||||
# Mock encryption
|
||||
with patch("services.tools.tools_transform_service.create_provider_encrypter") as mock_encrypter:
|
||||
mock_encrypter_instance = Mock()
|
||||
mock_encrypter_instance.decrypt.return_value = {"api_key": "decrypted_key"}
|
||||
mock_encrypter_instance.mask_tool_credentials.return_value = {"api_key": ""}
|
||||
mock_encrypter.return_value = (mock_encrypter_instance, None)
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.builtin_provider_to_user_provider(
|
||||
mock_controller, mock_db_provider, decrypt_credentials=True
|
||||
)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert result.id == mock_controller.entity.identity.name
|
||||
assert result.author == mock_controller.entity.identity.author
|
||||
assert result.name == mock_controller.entity.identity.name
|
||||
assert result.description == mock_controller.entity.identity.description
|
||||
assert result.icon == mock_controller.entity.identity.icon
|
||||
assert result.icon_dark == mock_controller.entity.identity.icon_dark
|
||||
assert result.label == mock_controller.entity.identity.label
|
||||
assert result.type == ToolProviderType.BUILT_IN
|
||||
assert result.is_team_authorization is True
|
||||
assert result.plugin_id is None
|
||||
assert result.tools == []
|
||||
assert result.labels == ["label1", "label2"]
|
||||
assert result.masked_credentials == {"api_key": ""}
|
||||
assert result.original_credentials == {"api_key": "decrypted_key"}
|
||||
|
||||
def test_builtin_provider_to_user_provider_plugin_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful conversion of builtin provider to user provider with plugin.
|
||||
|
||||
This test verifies:
|
||||
- Plugin ID and unique identifier handling
|
||||
- Proper entity creation for plugin providers
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create mock provider controller with plugin
|
||||
mock_controller = Mock()
|
||||
mock_controller.entity.identity.name = fake.company()
|
||||
mock_controller.entity.identity.author = fake.name()
|
||||
mock_controller.entity.identity.description = I18nObject(en_US=fake.text(max_nb_chars=100))
|
||||
mock_controller.entity.identity.icon = "🔧"
|
||||
mock_controller.entity.identity.icon_dark = "🔧"
|
||||
mock_controller.entity.identity.label = I18nObject(en_US=fake.company())
|
||||
mock_controller.plugin_id = "test_plugin_id"
|
||||
mock_controller.plugin_unique_identifier = "test_unique_id"
|
||||
mock_controller.tool_labels = ["label1"]
|
||||
mock_controller.need_credentials = False
|
||||
|
||||
# Mock credentials schema
|
||||
mock_credential = Mock()
|
||||
mock_credential.to_basic_provider_config.return_value.name = "api_key"
|
||||
mock_controller.get_credentials_schema_by_type.return_value = [mock_credential]
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.builtin_provider_to_user_provider(
|
||||
mock_controller, None, decrypt_credentials=False
|
||||
)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
# Note: The method checks isinstance(provider_controller, PluginToolProviderController)
|
||||
# Since we're using a Mock, this check will fail, so plugin_id will remain None
|
||||
# In a real test with actual PluginToolProviderController, this would work
|
||||
assert result.is_team_authorization is True
|
||||
assert result.allow_delete is False
|
||||
|
||||
def test_builtin_provider_to_user_provider_no_credentials(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test conversion of builtin provider to user provider without credentials.
|
||||
|
||||
This test verifies:
|
||||
- Proper handling when no credentials are needed
|
||||
- Team authorization setup for no-credentials providers
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create mock provider controller
|
||||
mock_controller = Mock()
|
||||
mock_controller.entity.identity.name = fake.company()
|
||||
mock_controller.entity.identity.author = fake.name()
|
||||
mock_controller.entity.identity.description = I18nObject(en_US=fake.text(max_nb_chars=100))
|
||||
mock_controller.entity.identity.icon = "🔧"
|
||||
mock_controller.entity.identity.icon_dark = "🔧"
|
||||
mock_controller.entity.identity.label = I18nObject(en_US=fake.company())
|
||||
mock_controller.plugin_id = None
|
||||
mock_controller.plugin_unique_identifier = None
|
||||
mock_controller.tool_labels = []
|
||||
mock_controller.need_credentials = False
|
||||
|
||||
# Mock credentials schema
|
||||
mock_credential = Mock()
|
||||
mock_credential.to_basic_provider_config.return_value.name = "api_key"
|
||||
mock_controller.get_credentials_schema_by_type.return_value = [mock_credential]
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.builtin_provider_to_user_provider(
|
||||
mock_controller, None, decrypt_credentials=False
|
||||
)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert result.is_team_authorization is True
|
||||
assert result.allow_delete is False
|
||||
assert result.masked_credentials == {}
|
||||
|
||||
def test_api_provider_to_controller_success(self, db_session_with_containers, mock_external_service_dependencies):
|
||||
"""
|
||||
Test successful conversion of API provider to controller.
|
||||
|
||||
This test verifies:
|
||||
- Proper controller creation from database provider
|
||||
- Auth type handling for different credential types
|
||||
- Backward compatibility for auth types
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create API tool provider with api_key_header auth
|
||||
provider = ApiToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
tenant_id=fake.uuid4(),
|
||||
user_id=fake.uuid4(),
|
||||
credentials_str='{"auth_type": "api_key_header", "api_key": "test_key"}',
|
||||
schema="{}",
|
||||
schema_type_str="openapi",
|
||||
tools_str="[]",
|
||||
)
|
||||
|
||||
from extensions.ext_database import db
|
||||
|
||||
db.session.add(provider)
|
||||
db.session.commit()
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.api_provider_to_controller(provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert hasattr(result, "from_db")
|
||||
# Additional assertions would depend on the actual controller implementation
|
||||
|
||||
def test_api_provider_to_controller_api_key_query(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test conversion of API provider to controller with api_key_query auth type.
|
||||
|
||||
This test verifies:
|
||||
- Proper auth type handling for query parameter authentication
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create API tool provider with api_key_query auth
|
||||
provider = ApiToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
tenant_id=fake.uuid4(),
|
||||
user_id=fake.uuid4(),
|
||||
credentials_str='{"auth_type": "api_key_query", "api_key": "test_key"}',
|
||||
schema="{}",
|
||||
schema_type_str="openapi",
|
||||
tools_str="[]",
|
||||
)
|
||||
|
||||
from extensions.ext_database import db
|
||||
|
||||
db.session.add(provider)
|
||||
db.session.commit()
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.api_provider_to_controller(provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert hasattr(result, "from_db")
|
||||
|
||||
def test_api_provider_to_controller_backward_compatibility(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test conversion of API provider to controller with backward compatibility auth types.
|
||||
|
||||
This test verifies:
|
||||
- Proper handling of legacy auth type values
|
||||
- Backward compatibility for api_key and api_key_header
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create API tool provider with legacy auth type
|
||||
provider = ApiToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
tenant_id=fake.uuid4(),
|
||||
user_id=fake.uuid4(),
|
||||
credentials_str='{"auth_type": "api_key", "api_key": "test_key"}',
|
||||
schema="{}",
|
||||
schema_type_str="openapi",
|
||||
tools_str="[]",
|
||||
)
|
||||
|
||||
from extensions.ext_database import db
|
||||
|
||||
db.session.add(provider)
|
||||
db.session.commit()
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.api_provider_to_controller(provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert hasattr(result, "from_db")
|
||||
|
||||
def test_workflow_provider_to_controller_success(
|
||||
self, db_session_with_containers, mock_external_service_dependencies
|
||||
):
|
||||
"""
|
||||
Test successful conversion of workflow provider to controller.
|
||||
|
||||
This test verifies:
|
||||
- Proper controller creation from workflow provider
|
||||
- Workflow-specific controller handling
|
||||
"""
|
||||
# Arrange: Setup test data
|
||||
fake = Faker()
|
||||
|
||||
# Create workflow tool provider
|
||||
provider = WorkflowToolProvider(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
icon='{"background": "#FF6B6B", "content": "🔧"}',
|
||||
tenant_id=fake.uuid4(),
|
||||
user_id=fake.uuid4(),
|
||||
app_id=fake.uuid4(),
|
||||
label="Test Workflow",
|
||||
version="1.0.0",
|
||||
parameter_configuration="[]",
|
||||
)
|
||||
|
||||
from extensions.ext_database import db
|
||||
|
||||
db.session.add(provider)
|
||||
db.session.commit()
|
||||
|
||||
# Mock the WorkflowToolProviderController.from_db method to avoid app dependency
|
||||
with patch("services.tools.tools_transform_service.WorkflowToolProviderController.from_db") as mock_from_db:
|
||||
mock_controller = Mock()
|
||||
mock_from_db.return_value = mock_controller
|
||||
|
||||
# Act: Execute the method under test
|
||||
result = ToolTransformService.workflow_provider_to_controller(provider)
|
||||
|
||||
# Assert: Verify the expected outcomes
|
||||
assert result is not None
|
||||
assert result == mock_controller
|
||||
mock_from_db.assert_called_once_with(provider)
|
Reference in New Issue
Block a user