test: use SQLite sessions in controllers console app (#39097)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Asuka Minato 2026-07-30 12:17:48 +09:00 committed by GitHub
parent 9e8733413a
commit 7c9a0ce93b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 104 additions and 49 deletions

View File

@ -6,6 +6,7 @@ from unittest.mock import MagicMock, PropertyMock, patch
import pytest
from flask import Flask
from sqlalchemy.orm import Session
from werkzeug.exceptions import Forbidden
from controllers.common import wraps as common_wraps
@ -15,6 +16,7 @@ from controllers.console.app import ops_trace as ops_trace_module
from controllers.console.app import wraps as app_wraps
from libs import login as login_lib
from models.account import Account, AccountStatus, TenantAccountRole
from models.model import App, AppMode, IconType
def _make_account(role: TenantAccountRole) -> Account:
@ -137,11 +139,33 @@ def test_trace_config_mutations_require_rbac_permission(
payload: dict[str, object] | None,
service_method_name: str,
service_result: object,
sqlite_session: Session,
) -> None:
app.config.setdefault("RESTX_MASK_HEADER", "X-Fields")
account = _make_account(TenantAccountRole.NORMAL)
_patch_console_guards(monkeypatch, account, _make_app(), rbac_enabled=True)
monkeypatch.setattr(common_wraps.db, "session", SimpleNamespace(scalar=lambda _stmt: "other-account"))
owned_app = App()
owned_app.id = "app-123"
owned_app.tenant_id = "tenant-123"
owned_app.name = "Trace app"
owned_app.description = ""
owned_app.mode = AppMode.CHAT
owned_app.icon_type = IconType.EMOJI
owned_app.icon = "robot"
owned_app.icon_background = "#ffffff"
owned_app.enable_site = False
owned_app.enable_api = False
owned_app.api_rpm = 0
owned_app.api_rph = 0
owned_app.is_demo = False
owned_app.is_public = False
owned_app.is_universal = False
owned_app.max_active_requests = None
owned_app.maintainer = "other-account"
owned_app.use_icon_as_answer_icon = False
sqlite_session.add(owned_app)
sqlite_session.commit()
monkeypatch.setattr(common_wraps.db, "session", sqlite_session)
monkeypatch.setattr(common_wraps.RBACService.CheckAccess, "check", MagicMock(return_value=False))
service_mock = MagicMock(return_value=service_result)
monkeypatch.setattr(ops_trace_module.OpsService, service_method_name, service_mock)

View File

@ -1,14 +1,64 @@
from __future__ import annotations
import inspect
import uuid
from datetime import UTC, datetime
from types import SimpleNamespace
from unittest.mock import MagicMock, PropertyMock, patch
from unittest.mock import PropertyMock, patch
import pytest
from flask import Flask
from sqlalchemy import Engine
from sqlalchemy.orm import Session
from controllers.console import console_ns
from controllers.console.app import workflow_trigger as workflow_trigger_module
from models.base import TypeBase
from models.enums import AppTriggerStatus, AppTriggerType
from models.model import App, AppMode, IconType
from models.trigger import AppTrigger
@pytest.fixture
def database_session(sqlite_engine: Engine, monkeypatch: pytest.MonkeyPatch):
models = (App, AppTrigger)
tables = [model.metadata.tables[model.__tablename__] for model in models]
TypeBase.metadata.create_all(sqlite_engine, tables=tables)
monkeypatch.setattr(workflow_trigger_module, "db", SimpleNamespace(engine=sqlite_engine))
with Session(sqlite_engine, expire_on_commit=False) as session:
yield session
def _persist_app_trigger(
session: Session,
*,
tenant_id: str | None = None,
status: AppTriggerStatus = AppTriggerStatus.ENABLED,
) -> tuple[App, AppTrigger]:
tenant_id = tenant_id or str(uuid.uuid4())
app_model = App(
id=str(uuid.uuid4()),
tenant_id=tenant_id,
name="Workflow App",
mode=AppMode.WORKFLOW,
icon_type=IconType.EMOJI,
icon="workflow",
icon_background="#FFFFFF",
enable_site=False,
enable_api=True,
)
trigger = AppTrigger(
tenant_id=tenant_id,
app_id=app_model.id,
node_id="node-1",
trigger_type=AppTriggerType.TRIGGER_PLUGIN,
title="Trigger",
provider_name="provider",
status=status,
)
session.add_all([app_model, trigger])
session.commit()
return app_model, trigger
def test_parser_models_validate():
@ -23,22 +73,20 @@ def test_parser_models_validate():
def test_workflow_trigger_response_serializes_datetime():
created_at = datetime(2026, 1, 2, 3, 4, 5, tzinfo=UTC)
trigger = SimpleNamespace(
id="trigger-1",
trigger_type="trigger-plugin",
response = workflow_trigger_module.WorkflowTriggerResponse(
id=str(uuid.uuid4()),
trigger_type=AppTriggerType.TRIGGER_PLUGIN,
title="Trigger",
node_id="node-1",
provider_name="provider",
icon="https://example.com/icon",
status="enabled",
status=AppTriggerStatus.ENABLED,
created_at=created_at,
updated_at=created_at,
)
payload = workflow_trigger_module.WorkflowTriggerResponse.model_validate(trigger, from_attributes=True).model_dump(
mode="json"
)
assert payload["id"] == "trigger-1"
payload = response.model_dump(mode="json")
assert payload["id"] == response.id
assert payload["created_at"] == "2026-01-02T03:04:05Z"
assert payload["updated_at"] == "2026-01-02T03:04:05Z"
@ -59,51 +107,33 @@ def test_webhook_trigger_response_serializes_datetime():
assert payload["created_at"] == "2026-01-02T03:04:05Z"
def test_app_triggers_get_uses_injected_tenant_id(app: Flask) -> None:
trigger = SimpleNamespace(
id="trigger-1",
trigger_type="trigger-plugin",
title="Trigger",
def test_app_triggers_get_uses_injected_tenant_id(app: Flask, database_session: Session) -> None:
app_model, trigger = _persist_app_trigger(database_session)
other_tenant_trigger = AppTrigger(
tenant_id=str(uuid.uuid4()),
app_id=app_model.id,
node_id="node-1",
trigger_type=AppTriggerType.TRIGGER_PLUGIN,
title="Other Tenant Trigger",
provider_name="provider",
icon="",
status="enabled",
created_at=None,
updated_at=None,
status=AppTriggerStatus.ENABLED,
)
session = MagicMock()
session.execute.return_value.scalars.return_value.all.return_value = [trigger]
database_session.add(other_tenant_trigger)
database_session.commit()
api = workflow_trigger_module.AppTriggersApi()
method = inspect.unwrap(api.get)
with (
app.test_request_context("/"),
patch.object(type(workflow_trigger_module.db), "engine", new_callable=PropertyMock, return_value=MagicMock()),
patch("controllers.console.app.workflow_trigger.sessionmaker") as sessionmaker_mock,
):
sessionmaker_mock.return_value.begin.return_value.__enter__.return_value = session
response = method(api, "tenant-1", SimpleNamespace(id="app-1"))
with app.test_request_context("/"):
response = method(api, app_model.tenant_id, app_model)
assert response["data"][0]["id"] == "trigger-1"
assert [item["id"] for item in response["data"]] == [trigger.id]
assert response["data"][0]["icon"].endswith("/provider/icon")
def test_app_trigger_enable_uses_injected_tenant_id(app: Flask) -> None:
trigger = SimpleNamespace(
id="trigger-1",
trigger_type="trigger-plugin",
title="Trigger",
node_id="node-1",
provider_name="provider",
icon="",
status="disabled",
created_at=None,
updated_at=None,
)
session = MagicMock()
session.execute.return_value.scalar_one_or_none.return_value = trigger
payload = {"trigger_id": "trigger-1", "enable_trigger": True}
def test_app_trigger_enable_uses_injected_tenant_id(app: Flask, database_session: Session) -> None:
app_model, trigger = _persist_app_trigger(database_session, status=AppTriggerStatus.DISABLED)
payload = {"trigger_id": trigger.id, "enable_trigger": True}
api = workflow_trigger_module.AppTriggerEnableApi()
method = inspect.unwrap(api.post)
@ -111,11 +141,12 @@ def test_app_trigger_enable_uses_injected_tenant_id(app: Flask) -> None:
with (
app.test_request_context("/", json=payload),
patch.object(type(console_ns), "payload", new_callable=PropertyMock, return_value=payload),
patch.object(type(workflow_trigger_module.db), "engine", new_callable=PropertyMock, return_value=MagicMock()),
patch("controllers.console.app.workflow_trigger.sessionmaker") as sessionmaker_mock,
):
sessionmaker_mock.return_value.begin.return_value.__enter__.return_value = session
response = method(api, "tenant-1", SimpleNamespace(id="app-1"))
response = method(api, app_model.tenant_id, app_model)
assert response["id"] == "trigger-1"
assert response["id"] == trigger.id
assert response["status"] == "enabled"
database_session.expire_all()
persisted_trigger = database_session.get(AppTrigger, trigger.id)
assert persisted_trigger is not None
assert persisted_trigger.status == AppTriggerStatus.ENABLED