test: use SQLite sessions in services workflow (#39116)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Asuka Minato 2026-07-21 12:40:02 +09:00 committed by GitHub
parent 97e6a14c13
commit d333aa31ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,9 +1,11 @@
"""Tests for human-input delivery with a persisted draft workflow."""
import json
import uuid import uuid
from types import SimpleNamespace
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import Session, sessionmaker
from core.workflow.human_input_adapter import ( from core.workflow.human_input_adapter import (
EmailDeliveryConfig, EmailDeliveryConfig,
@ -14,12 +16,42 @@ from core.workflow.human_input_adapter import (
) )
from core.workflow.nodes.human_input.entities import HumanInputNodeData from core.workflow.nodes.human_input.entities import HumanInputNodeData
from graphon.enums import BuiltinNodeTypes from graphon.enums import BuiltinNodeTypes
from models import Account
from models.enums import AppStatus
from models.model import App, AppMode
from models.workflow import Workflow, WorkflowType
from services import workflow_service as workflow_service_module from services import workflow_service as workflow_service_module
from services.workflow_service import WorkflowService from services.workflow_service import WorkflowService
TENANT_ID = "11111111-1111-1111-1111-111111111111"
APP_ID = "22222222-2222-2222-2222-222222222222"
ACCOUNT_ID = "33333333-3333-3333-3333-333333333333"
def _make_service() -> WorkflowService:
return WorkflowService(session_maker=sessionmaker()) def _make_service(sqlite_session: Session) -> WorkflowService:
return WorkflowService(
session_maker=sessionmaker(bind=sqlite_session.get_bind(), expire_on_commit=False),
)
def _app() -> App:
return App(
id=APP_ID,
tenant_id=TENANT_ID,
name="Test App",
description="",
mode=AppMode.WORKFLOW,
status=AppStatus.NORMAL,
enable_site=False,
enable_api=False,
max_active_requests=None,
)
def _account() -> Account:
account = Account(name="Test User", email="test@example.com")
account.id = ACCOUNT_ID
return account
def _build_node_config(delivery_methods: list[EmailDeliveryMethod]) -> dict[str, object]: def _build_node_config(delivery_methods: list[EmailDeliveryMethod]) -> dict[str, object]:
@ -36,6 +68,37 @@ def _build_node_config(delivery_methods: list[EmailDeliveryMethod]) -> dict[str,
} }
def _persist_workflow(sqlite_session: Session, delivery_methods: list[EmailDeliveryMethod]) -> None:
node_config = _build_node_config(delivery_methods)
node_data = node_config["data"]
assert isinstance(node_data, HumanInputNodeData)
workflow = Workflow.new(
tenant_id=TENANT_ID,
app_id=APP_ID,
type=WorkflowType.WORKFLOW,
version=Workflow.VERSION_DRAFT,
graph=json.dumps(
{
"nodes": [
{
"id": node_config["id"],
"data": node_data.model_dump(mode="json"),
}
],
"edges": [],
}
),
features="{}",
created_by=ACCOUNT_ID,
environment_variables=[],
conversation_variables=[],
rag_pipeline_variables=[],
)
sqlite_session.add(workflow)
sqlite_session.commit()
sqlite_session.expunge_all()
def _make_email_method(enabled: bool = True, debug_mode: bool = False) -> EmailDeliveryMethod: def _make_email_method(enabled: bool = True, debug_mode: bool = False) -> EmailDeliveryMethod:
return EmailDeliveryMethod( return EmailDeliveryMethod(
id=uuid.uuid4(), id=uuid.uuid4(),
@ -52,11 +115,11 @@ def _make_email_method(enabled: bool = True, debug_mode: bool = False) -> EmailD
) )
def test_human_input_delivery_requires_draft_workflow(): @pytest.mark.parametrize("sqlite_session", [(Workflow,)], indirect=True)
service = _make_service() def test_human_input_delivery_requires_draft_workflow(sqlite_session: Session):
service.get_draft_workflow = MagicMock(return_value=None) # type: ignore[method-assign] service = _make_service(sqlite_session)
app_model = SimpleNamespace(tenant_id="tenant-1", id="app-1") app_model = _app()
account = SimpleNamespace(id="account-1") account = _account()
with pytest.raises(ValueError, match="Workflow not initialized"): with pytest.raises(ValueError, match="Workflow not initialized"):
service.test_human_input_delivery( service.test_human_input_delivery(
@ -64,17 +127,19 @@ def test_human_input_delivery_requires_draft_workflow():
account=account, account=account,
node_id="node-1", node_id="node-1",
delivery_method_id="delivery-1", delivery_method_id="delivery-1",
session=MagicMock(), session=sqlite_session,
) )
assert sqlite_session.in_transaction()
def test_human_input_delivery_allows_disabled_method(monkeypatch: pytest.MonkeyPatch): @pytest.mark.parametrize("sqlite_session", [(Workflow,)], indirect=True)
service = _make_service() def test_human_input_delivery_allows_disabled_method(
monkeypatch: pytest.MonkeyPatch,
sqlite_session: Session,
):
service = _make_service(sqlite_session)
delivery_method = _make_email_method(enabled=False) delivery_method = _make_email_method(enabled=False)
node_config = _build_node_config([delivery_method]) _persist_workflow(sqlite_session, [delivery_method])
workflow = MagicMock()
workflow.get_node_config_by_id.return_value = node_config
service.get_draft_workflow = MagicMock(return_value=workflow) # type: ignore[method-assign]
service._build_human_input_variable_pool = MagicMock(return_value=MagicMock()) # type: ignore[attr-defined] service._build_human_input_variable_pool = MagicMock(return_value=MagicMock()) # type: ignore[attr-defined]
node_stub = MagicMock() node_stub = MagicMock()
node_stub.render_form_content_before_submission.return_value = "rendered" node_stub.render_form_content_before_submission.return_value = "rendered"
@ -91,27 +156,29 @@ def test_human_input_delivery_allows_disabled_method(monkeypatch: pytest.MonkeyP
MagicMock(return_value=test_service_instance), MagicMock(return_value=test_service_instance),
) )
app_model = SimpleNamespace(tenant_id="tenant-1", id="app-1") app_model = _app()
account = SimpleNamespace(id="account-1") account = _account()
service.test_human_input_delivery( service.test_human_input_delivery(
app_model=app_model, app_model=app_model,
account=account, account=account,
node_id="node-1", node_id="node-1",
delivery_method_id=str(delivery_method.id), delivery_method_id=str(delivery_method.id),
session=MagicMock(), session=sqlite_session,
) )
test_service_instance.send_test.assert_called_once() test_service_instance.send_test.assert_called_once()
assert sqlite_session.in_transaction()
def test_human_input_delivery_dispatches_to_test_service(monkeypatch: pytest.MonkeyPatch): @pytest.mark.parametrize("sqlite_session", [(Workflow,)], indirect=True)
service = _make_service() def test_human_input_delivery_dispatches_to_test_service(
monkeypatch: pytest.MonkeyPatch,
sqlite_session: Session,
):
service = _make_service(sqlite_session)
delivery_method = _make_email_method(enabled=True) delivery_method = _make_email_method(enabled=True)
node_config = _build_node_config([delivery_method]) _persist_workflow(sqlite_session, [delivery_method])
workflow = MagicMock()
workflow.get_node_config_by_id.return_value = node_config
service.get_draft_workflow = MagicMock(return_value=workflow) # type: ignore[method-assign]
service._build_human_input_variable_pool = MagicMock(return_value=MagicMock()) # type: ignore[attr-defined] service._build_human_input_variable_pool = MagicMock(return_value=MagicMock()) # type: ignore[attr-defined]
node_stub = MagicMock() node_stub = MagicMock()
node_stub.render_form_content_before_submission.return_value = "rendered" node_stub.render_form_content_before_submission.return_value = "rendered"
@ -128,8 +195,8 @@ def test_human_input_delivery_dispatches_to_test_service(monkeypatch: pytest.Mon
MagicMock(return_value=test_service_instance), MagicMock(return_value=test_service_instance),
) )
app_model = SimpleNamespace(tenant_id="tenant-1", id="app-1") app_model = _app()
account = SimpleNamespace(id="account-1") account = _account()
service.test_human_input_delivery( service.test_human_input_delivery(
app_model=app_model, app_model=app_model,
@ -137,21 +204,23 @@ def test_human_input_delivery_dispatches_to_test_service(monkeypatch: pytest.Mon
node_id="node-1", node_id="node-1",
delivery_method_id=str(delivery_method.id), delivery_method_id=str(delivery_method.id),
inputs={"#node-1.output#": "value"}, inputs={"#node-1.output#": "value"},
session=MagicMock(), session=sqlite_session,
) )
pool_args = service._build_human_input_variable_pool.call_args.kwargs pool_args = service._build_human_input_variable_pool.call_args.kwargs
assert pool_args["manual_inputs"] == {"#node-1.output#": "value"} assert pool_args["manual_inputs"] == {"#node-1.output#": "value"}
test_service_instance.send_test.assert_called_once() test_service_instance.send_test.assert_called_once()
assert sqlite_session.in_transaction()
def test_human_input_delivery_debug_mode_overrides_recipients(monkeypatch: pytest.MonkeyPatch): @pytest.mark.parametrize("sqlite_session", [(Workflow,)], indirect=True)
service = _make_service() def test_human_input_delivery_debug_mode_overrides_recipients(
monkeypatch: pytest.MonkeyPatch,
sqlite_session: Session,
):
service = _make_service(sqlite_session)
delivery_method = _make_email_method(enabled=True, debug_mode=True) delivery_method = _make_email_method(enabled=True, debug_mode=True)
node_config = _build_node_config([delivery_method]) _persist_workflow(sqlite_session, [delivery_method])
workflow = MagicMock()
workflow.get_node_config_by_id.return_value = node_config
service.get_draft_workflow = MagicMock(return_value=workflow) # type: ignore[method-assign]
service._build_human_input_variable_pool = MagicMock(return_value=MagicMock()) # type: ignore[attr-defined] service._build_human_input_variable_pool = MagicMock(return_value=MagicMock()) # type: ignore[attr-defined]
node_stub = MagicMock() node_stub = MagicMock()
node_stub.render_form_content_before_submission.return_value = "rendered" node_stub.render_form_content_before_submission.return_value = "rendered"
@ -168,15 +237,15 @@ def test_human_input_delivery_debug_mode_overrides_recipients(monkeypatch: pytes
MagicMock(return_value=test_service_instance), MagicMock(return_value=test_service_instance),
) )
app_model = SimpleNamespace(tenant_id="tenant-1", id="app-1") app_model = _app()
account = SimpleNamespace(id="account-1") account = _account()
service.test_human_input_delivery( service.test_human_input_delivery(
app_model=app_model, app_model=app_model,
account=account, account=account,
node_id="node-1", node_id="node-1",
delivery_method_id=str(delivery_method.id), delivery_method_id=str(delivery_method.id),
session=MagicMock(), session=sqlite_session,
) )
test_service_instance.send_test.assert_called_once() test_service_instance.send_test.assert_called_once()
@ -188,3 +257,4 @@ def test_human_input_delivery_debug_mode_overrides_recipients(monkeypatch: pytes
recipient = sent_method.config.recipients.items[0] recipient = sent_method.config.recipients.items[0]
assert isinstance(recipient, MemberRecipient) assert isinstance(recipient, MemberRecipient)
assert recipient.reference_id == account.id assert recipient.reference_id == account.id
assert sqlite_session.in_transaction()