mirror of
https://github.com/langgenius/dify.git
synced 2026-09-24 23:22:26 +08:00
refactor(api): migrate service api workflow responses from marshal_with to BaseModel (#35195)
Co-authored-by: ai-hpc <ai-hpc@users.noreply.github.com>
This commit is contained in:
@@ -15,6 +15,7 @@ Focus on:
|
||||
|
||||
import sys
|
||||
import uuid
|
||||
from datetime import UTC, datetime
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
@@ -43,6 +44,22 @@ from services.errors.llm import InvokeRateLimitError
|
||||
from services.workflow_app_service import WorkflowAppService
|
||||
|
||||
|
||||
def _make_mock_workflow_run(run_id: str = "run-1"):
|
||||
run = Mock()
|
||||
run.id = run_id
|
||||
run.workflow_id = "wf-1"
|
||||
run.status = WorkflowExecutionStatus.SUCCEEDED
|
||||
run.inputs = {"input": "value"}
|
||||
run.outputs_dict = {"output": "value"}
|
||||
run.error = None
|
||||
run.total_steps = 1
|
||||
run.total_tokens = 10
|
||||
run.created_at = datetime(2026, 1, 1, tzinfo=UTC)
|
||||
run.finished_at = datetime(2026, 1, 1, tzinfo=UTC)
|
||||
run.elapsed_time = 0.1
|
||||
return run
|
||||
|
||||
|
||||
class TestWorkflowRunPayload:
|
||||
"""Test suite for WorkflowRunPayload Pydantic model."""
|
||||
|
||||
@@ -359,7 +376,7 @@ class TestWorkflowRunDetailApi:
|
||||
handler(api, app_model=app_model, workflow_run_id="run")
|
||||
|
||||
def test_success(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
run = SimpleNamespace(id="run")
|
||||
run = _make_mock_workflow_run(run_id="run")
|
||||
repo = SimpleNamespace(get_workflow_run_by_id=lambda **_kwargs: run)
|
||||
workflow_module = sys.modules["controllers.service_api.app.workflow"]
|
||||
monkeypatch.setattr(workflow_module, "db", SimpleNamespace(engine=object()))
|
||||
@@ -373,7 +390,10 @@ class TestWorkflowRunDetailApi:
|
||||
handler = _unwrap(api.get)
|
||||
app_model = SimpleNamespace(mode=AppMode.WORKFLOW.value, tenant_id="t1", id="a1")
|
||||
|
||||
assert handler(api, app_model=app_model, workflow_run_id="run") == run
|
||||
result = handler(api, app_model=app_model, workflow_run_id="run")
|
||||
assert result["id"] == "run"
|
||||
assert result["workflow_id"] == "wf-1"
|
||||
assert result["status"] == "succeeded"
|
||||
|
||||
|
||||
class TestWorkflowRunApi:
|
||||
@@ -490,7 +510,7 @@ class TestWorkflowAppLogApi:
|
||||
monkeypatch.setattr(
|
||||
WorkflowAppService,
|
||||
"get_paginate_workflow_app_logs",
|
||||
lambda *_args, **_kwargs: {"items": [], "total": 0},
|
||||
lambda *_args, **_kwargs: {"page": 1, "limit": 20, "total": 0, "has_more": False, "data": []},
|
||||
)
|
||||
|
||||
api = WorkflowAppLogApi()
|
||||
@@ -500,7 +520,7 @@ class TestWorkflowAppLogApi:
|
||||
with app.test_request_context("/workflows/logs", method="GET"):
|
||||
response = handler(api, app_model=app_model)
|
||||
|
||||
assert response == {"items": [], "total": 0}
|
||||
assert response == {"page": 1, "limit": 20, "total": 0, "has_more": False, "data": []}
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -527,9 +547,8 @@ def mock_workflow_app():
|
||||
class TestWorkflowRunDetailApiGet:
|
||||
"""Test suite for WorkflowRunDetailApi.get() endpoint.
|
||||
|
||||
``get`` is wrapped by ``@validate_app_token`` (preserves ``__wrapped__``)
|
||||
and ``@service_api_ns.marshal_with``. We call the unwrapped method
|
||||
directly; ``marshal_with`` is a no-op when calling directly.
|
||||
``get`` is wrapped by ``@validate_app_token`` (preserves ``__wrapped__``),
|
||||
and we call the unwrapped method directly in tests.
|
||||
"""
|
||||
|
||||
@patch("controllers.service_api.app.workflow.DifyAPIRepositoryFactory")
|
||||
@@ -542,9 +561,7 @@ class TestWorkflowRunDetailApiGet:
|
||||
mock_workflow_app,
|
||||
):
|
||||
"""Test successful workflow run detail retrieval."""
|
||||
mock_run = Mock()
|
||||
mock_run.id = "run-1"
|
||||
mock_run.status = "succeeded"
|
||||
mock_run = _make_mock_workflow_run(run_id="run-1")
|
||||
mock_repo = Mock()
|
||||
mock_repo.get_workflow_run_by_id.return_value = mock_run
|
||||
mock_repo_factory.create_api_workflow_run_repository.return_value = mock_repo
|
||||
@@ -558,7 +575,8 @@ class TestWorkflowRunDetailApiGet:
|
||||
api = WorkflowRunDetailApi()
|
||||
result = _unwrap(api.get)(api, app_model=mock_workflow_app, workflow_run_id=mock_run.id)
|
||||
|
||||
assert result == mock_run
|
||||
assert result["id"] == mock_run.id
|
||||
assert result["status"] == "succeeded"
|
||||
|
||||
@patch("controllers.service_api.app.workflow.db")
|
||||
def test_get_workflow_run_wrong_app_mode(self, mock_db, app):
|
||||
@@ -622,8 +640,7 @@ class TestWorkflowTaskStopApiPost:
|
||||
class TestWorkflowAppLogApiGet:
|
||||
"""Test suite for WorkflowAppLogApi.get() endpoint.
|
||||
|
||||
``get`` is wrapped by ``@validate_app_token`` and
|
||||
``@service_api_ns.marshal_with``.
|
||||
``get`` is wrapped by ``@validate_app_token``.
|
||||
"""
|
||||
|
||||
@patch("controllers.service_api.app.workflow.WorkflowAppService")
|
||||
@@ -637,6 +654,10 @@ class TestWorkflowAppLogApiGet:
|
||||
):
|
||||
"""Test successful workflow log retrieval."""
|
||||
mock_pagination = Mock()
|
||||
mock_pagination.page = 1
|
||||
mock_pagination.limit = 20
|
||||
mock_pagination.total = 0
|
||||
mock_pagination.has_more = False
|
||||
mock_pagination.data = []
|
||||
mock_svc_instance = Mock()
|
||||
mock_svc_instance.get_paginate_workflow_app_logs.return_value = mock_pagination
|
||||
@@ -661,4 +682,4 @@ class TestWorkflowAppLogApiGet:
|
||||
api = WorkflowAppLogApi()
|
||||
result = _unwrap(api.get)(api, app_model=mock_workflow_app)
|
||||
|
||||
assert result == mock_pagination
|
||||
assert result == {"page": 1, "limit": 20, "total": 0, "has_more": False, "data": []}
|
||||
|
||||
Reference in New Issue
Block a user