test: migrate tools transform service tests to testcontainers (#34035)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Desel72
2026-03-24 23:41:38 -05:00
committed by GitHub
parent ad3899f864
commit a9f2fb86a3
2 changed files with 203 additions and 454 deletions

View File

@ -1,12 +1,24 @@
from __future__ import annotations
from unittest.mock import Mock, patch
import pytest
from faker import Faker
from sqlalchemy.orm import Session
from core.tools.entities.api_entities import ToolProviderApiEntity
from core.tools.__base.tool import Tool
from core.tools.entities.api_entities import ToolApiEntity, ToolProviderApiEntity
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_entities import ApiProviderSchemaType, ToolProviderType
from core.tools.entities.tool_entities import (
ApiProviderSchemaType,
ToolDescription,
ToolEntity,
ToolIdentity,
ToolParameter,
ToolProviderEntity,
ToolProviderIdentity,
ToolProviderType,
)
from models.tools import ApiToolProvider, BuiltinToolProvider, MCPToolProvider, WorkflowToolProvider
from services.plugin.plugin_service import PluginService
from services.tools.tools_transform_service import ToolTransformService
@ -786,3 +798,192 @@ class TestToolTransformService:
assert result is not None
assert result == mock_controller
mock_from_db.assert_called_once_with(provider)
def _mock_tool(*, base_params, runtime_params):
"""Helper to build a Mock tool with real entity objects.
Tool is abstract and requires runtime behaviour (fork_tool_runtime,
get_runtime_parameters), so it stays as a Mock. Everything else uses
real Pydantic instances.
"""
entity = ToolEntity(
identity=ToolIdentity(
author="test_author",
name="test_tool",
label=I18nObject(en_US="Test Tool"),
provider="test_provider",
),
parameters=base_params or [],
description=ToolDescription(
human=I18nObject(en_US="Test description"),
llm="Test description for LLM",
),
output_schema={},
)
mock_tool = Mock(spec=Tool)
mock_tool.entity = entity
mock_tool.get_runtime_parameters.return_value = runtime_params
mock_tool.fork_tool_runtime.return_value = mock_tool
return mock_tool
def _param(name, *, form=ToolParameter.ToolParameterForm.FORM, label=None):
return ToolParameter(
name=name,
label=I18nObject(en_US=label or name),
human_description=I18nObject(en_US=name),
type=ToolParameter.ToolParameterType.STRING,
form=form,
)
class TestConvertToolEntityToApiEntity:
"""Tests for ToolTransformService.convert_tool_entity_to_api_entity."""
def test_parameter_override(self):
base = [_param("param1", label="Base 1"), _param("param2", label="Base 2")]
runtime = [_param("param1", label="Runtime 1")]
tool = _mock_tool(base_params=base, runtime_params=runtime)
result = ToolTransformService.convert_tool_entity_to_api_entity(tool, "t", None)
assert isinstance(result, ToolApiEntity)
assert len(result.parameters) == 2
assert next(p for p in result.parameters if p.name == "param1").label.en_US == "Runtime 1"
assert next(p for p in result.parameters if p.name == "param2").label.en_US == "Base 2"
def test_additional_runtime_parameters(self):
base = [_param("param1", label="Base 1")]
runtime = [_param("param1", label="Runtime 1"), _param("runtime_only", label="Runtime Only")]
tool = _mock_tool(base_params=base, runtime_params=runtime)
result = ToolTransformService.convert_tool_entity_to_api_entity(tool, "t", None)
assert len(result.parameters) == 2
names = [p.name for p in result.parameters]
assert "param1" in names
assert "runtime_only" in names
def test_non_form_runtime_parameters_excluded(self):
base = [_param("param1")]
runtime = [
_param("param1", label="Runtime 1"),
_param("llm_param", form=ToolParameter.ToolParameterForm.LLM),
]
tool = _mock_tool(base_params=base, runtime_params=runtime)
result = ToolTransformService.convert_tool_entity_to_api_entity(tool, "t", None)
assert len(result.parameters) == 1
assert result.parameters[0].name == "param1"
def test_empty_parameters(self):
tool = _mock_tool(base_params=[], runtime_params=[])
result = ToolTransformService.convert_tool_entity_to_api_entity(tool, "t", None)
assert isinstance(result, ToolApiEntity)
assert len(result.parameters) == 0
def test_none_parameters(self):
tool = _mock_tool(base_params=None, runtime_params=[])
result = ToolTransformService.convert_tool_entity_to_api_entity(tool, "t", None)
assert isinstance(result, ToolApiEntity)
assert len(result.parameters) == 0
def test_parameter_order_preserved(self):
base = [_param("p1", label="B1"), _param("p2", label="B2"), _param("p3", label="B3")]
runtime = [_param("p2", label="R2"), _param("p4", label="R4")]
tool = _mock_tool(base_params=base, runtime_params=runtime)
result = ToolTransformService.convert_tool_entity_to_api_entity(tool, "t", None)
assert [p.name for p in result.parameters] == ["p1", "p2", "p3", "p4"]
assert result.parameters[1].label.en_US == "R2"
class TestWorkflowProviderToUserProvider:
"""Tests for ToolTransformService.workflow_provider_to_user_provider."""
@staticmethod
def _make_controller(provider_id="provider_123", **identity_overrides):
from core.tools.workflow_as_tool.provider import WorkflowToolProviderController
defaults = {
"author": "test_author",
"name": "test_workflow_tool",
"description": I18nObject(en_US="Test description"),
"icon": '{"type": "emoji", "content": "🔧"}',
"icon_dark": None,
"label": I18nObject(en_US="Test Workflow Tool"),
}
defaults.update(identity_overrides)
identity = ToolProviderIdentity(**defaults)
entity = ToolProviderEntity(identity=identity)
return WorkflowToolProviderController(entity=entity, provider_id=provider_id)
def test_with_workflow_app_id(self):
ctrl = self._make_controller()
result = ToolTransformService.workflow_provider_to_user_provider(
provider_controller=ctrl,
labels=["l1", "l2"],
workflow_app_id="app_123",
)
assert isinstance(result, ToolProviderApiEntity)
assert result.id == "provider_123"
assert result.type == ToolProviderType.WORKFLOW
assert result.workflow_app_id == "app_123"
assert result.labels == ["l1", "l2"]
assert result.is_team_authorization is True
def test_without_workflow_app_id(self):
ctrl = self._make_controller()
result = ToolTransformService.workflow_provider_to_user_provider(
provider_controller=ctrl,
labels=["l1"],
)
assert result.workflow_app_id is None
def test_workflow_app_id_none_explicit(self):
ctrl = self._make_controller()
result = ToolTransformService.workflow_provider_to_user_provider(
provider_controller=ctrl,
labels=None,
workflow_app_id=None,
)
assert result.workflow_app_id is None
assert result.labels == []
def test_preserves_other_fields(self):
ctrl = self._make_controller(
"provider_456",
author="another_author",
name="another_workflow_tool",
description=I18nObject(en_US="Another desc", zh_Hans="Another desc"),
icon='{"type": "emoji", "content": "⚙️"}',
icon_dark='{"type": "emoji", "content": "🔧"}',
label=I18nObject(en_US="Another Tool", zh_Hans="Another Tool"),
)
result = ToolTransformService.workflow_provider_to_user_provider(
provider_controller=ctrl,
labels=["automation"],
workflow_app_id="app_456",
)
assert result.id == "provider_456"
assert result.author == "another_author"
assert result.name == "another_workflow_tool"
assert result.type == ToolProviderType.WORKFLOW
assert result.workflow_app_id == "app_456"
assert result.is_team_authorization is True
assert result.allow_delete is True