From f91ea4941481622e1ef15e9238069eeba13e8b63 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Wed, 22 Jul 2026 18:43:30 +0900 Subject: [PATCH] test: use sqlite3 session in test_app_import_api (#38674) Co-authored-by: Byron Wang --- .../console/app/test_app_import_api.py | 125 ++++++++++++------ 1 file changed, 86 insertions(+), 39 deletions(-) diff --git a/api/tests/unit_tests/controllers/console/app/test_app_import_api.py b/api/tests/unit_tests/controllers/console/app/test_app_import_api.py index 1933ed41732..3b675600539 100644 --- a/api/tests/unit_tests/controllers/console/app/test_app_import_api.py +++ b/api/tests/unit_tests/controllers/console/app/test_app_import_api.py @@ -9,13 +9,14 @@ from unittest.mock import MagicMock import pytest from flask import Flask -from sqlalchemy import event +from sqlalchemy import Engine, event from sqlalchemy.orm import Session from controllers.console.app import app_import as app_import_module from models.account import Account +from models.base import TypeBase from models.engine import db -from models.model import App +from models.model import App, AppMode from services.app_dsl_service import ImportStatus from services.entities.dsl_entities import CheckDependenciesResult from services.feature_service import SystemFeatureModel, WebAppAuthModel @@ -66,6 +67,13 @@ def app() -> Iterator[Flask]: yield app +@pytest.fixture +def sqlite_app_engine(app: Flask) -> Engine: + engine = db.engine + TypeBase.metadata.create_all(engine, tables=[TypeBase.metadata.tables[App.__tablename__]]) + return engine + + @dataclass class TransactionEvents: commits: int = 0 @@ -93,11 +101,34 @@ def transaction_events() -> TransactionEvents: event.remove(Session, "after_rollback", record_rollback) -def _failed_result_after_starting_transaction( - service: app_import_module.AppDslService, *, app_id: str | None = None -) -> _Result: - service._session.begin() - return _Result(ImportStatus.FAILED, app_id=app_id) +def _install_persisting_service_result( + monkeypatch: pytest.MonkeyPatch, + *, + method_name: str, + result: _Result, +) -> str: + app_id = result.app_id or "rolled-back-app" + + def _return_result(import_service: app_import_module.AppDslService, *_args, **_kwargs): + import_service._session.add( + App( + id=app_id, + tenant_id="tenant-1", + name="Imported App", + mode=AppMode.WORKFLOW, + enable_site=True, + enable_api=True, + ) + ) + return result + + monkeypatch.setattr(app_import_module.AppDslService, method_name, _return_result) + return app_id + + +def _assert_app_persistence(sqlite_app_engine: Engine, app_id: str, *, persisted: bool) -> None: + with Session(sqlite_app_engine) as session: + assert (session.get(App, app_id) is not None) is persisted class TestAppImportApi: @@ -110,15 +141,16 @@ class TestAppImportApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = unwrap(api.post) _install_features(monkeypatch, enabled=False) - monkeypatch.setattr( - app_import_module.AppDslService, - "import_app", - lambda service, *_args, **_kwargs: _failed_result_after_starting_transaction(service, app_id=None), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="import_app", + result=_Result(ImportStatus.FAILED, app_id=None), ) with app.test_request_context("/console/api/apps/imports", method="POST", json={"mode": "yaml-content"}): @@ -126,6 +158,7 @@ class TestAppImportApi: assert transaction_events.rollbacks == 1 assert transaction_events.commits == 0 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=False) assert status == 400 assert response["status"] == ImportStatus.FAILED @@ -134,15 +167,16 @@ class TestAppImportApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = unwrap(api.post) _install_features(monkeypatch, enabled=False) - monkeypatch.setattr( - app_import_module.AppDslService, - "import_app", - lambda *_args, **_kwargs: _Result(ImportStatus.PENDING), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="import_app", + result=_Result(ImportStatus.PENDING), ) with app.test_request_context("/console/api/apps/imports", method="POST", json={"mode": "yaml-content"}): @@ -150,6 +184,7 @@ class TestAppImportApi: assert transaction_events.commits == 1 assert transaction_events.rollbacks == 0 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=True) assert status == 202 assert response["status"] == ImportStatus.PENDING @@ -158,15 +193,16 @@ class TestAppImportApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = unwrap(api.post) _install_features(monkeypatch, enabled=True) - monkeypatch.setattr( - app_import_module.AppDslService, - "import_app", - lambda *_args, **_kwargs: _Result(ImportStatus.COMPLETED, app_id="app-123"), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="import_app", + result=_Result(ImportStatus.COMPLETED, app_id="app-123"), ) update_access = MagicMock() monkeypatch.setattr(app_import_module.EnterpriseService.WebAppAuth, "update_app_access_mode", update_access) @@ -176,6 +212,7 @@ class TestAppImportApi: assert transaction_events.commits == 1 assert transaction_events.rollbacks == 0 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=True) update_access.assert_called_once_with("app-123", "private") assert status == 200 assert response["status"] == ImportStatus.COMPLETED @@ -185,6 +222,7 @@ class TestAppImportApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = _unwrap(api.post) @@ -196,10 +234,10 @@ class TestAppImportApi: lambda: (_make_account(), "tenant-1"), ) monkeypatch.setattr(app_import_module.dify_config, "RBAC_ENABLED", True) - monkeypatch.setattr( - app_import_module.AppDslService, - "import_app", - lambda *_args, **_kwargs: _Result(ImportStatus.COMPLETED, app_id="app-123"), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="import_app", + result=_Result(ImportStatus.COMPLETED, app_id="app-123"), ) monkeypatch.setattr( app_import_module, @@ -211,6 +249,7 @@ class TestAppImportApi: response, status = method() assert transaction_events.commits == 1 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=True) assert status == 200 assert response["permission_keys"] == ["app.acl.view_layout", "app.acl.edit"] @@ -219,6 +258,7 @@ class TestAppImportApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = _unwrap(api.post) @@ -230,10 +270,10 @@ class TestAppImportApi: lambda: (_make_account(), "tenant-1"), ) monkeypatch.setattr(app_import_module.dify_config, "RBAC_ENABLED", True) - monkeypatch.setattr( - app_import_module.AppDslService, - "import_app", - lambda *_args, **_kwargs: _Result(ImportStatus.COMPLETED, app_id="app-123"), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="import_app", + result=_Result(ImportStatus.COMPLETED, app_id="app-123"), ) monkeypatch.setattr( app_import_module, @@ -249,6 +289,7 @@ class TestAppImportApi: response, status = method() assert transaction_events.commits == 1 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=True) assert status == 200 assert response["permission_keys"] == [] @@ -263,14 +304,15 @@ class TestAppImportConfirmApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = unwrap(api.post) - monkeypatch.setattr( - app_import_module.AppDslService, - "confirm_import", - lambda service, *_args, **_kwargs: _failed_result_after_starting_transaction(service), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="confirm_import", + result=_Result(ImportStatus.FAILED), ) with app.test_request_context("/console/api/apps/imports/import-1/confirm", method="POST"): @@ -278,6 +320,7 @@ class TestAppImportConfirmApi: assert transaction_events.rollbacks == 1 assert transaction_events.commits == 0 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=False) assert status == 400 assert response["status"] == ImportStatus.FAILED @@ -286,6 +329,7 @@ class TestAppImportConfirmApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = _unwrap(api.post) @@ -304,10 +348,10 @@ class TestAppImportConfirmApi: ), ) monkeypatch.setattr(app_import_module.dify_config, "RBAC_ENABLED", True) - monkeypatch.setattr( - app_import_module.AppDslService, - "confirm_import", - lambda *_args, **_kwargs: _Result(ImportStatus.COMPLETED, app_id="app-456"), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="confirm_import", + result=_Result(ImportStatus.COMPLETED, app_id="app-456"), ) monkeypatch.setattr( app_import_module, @@ -319,6 +363,7 @@ class TestAppImportConfirmApi: response, status = method(import_id="import-1") assert transaction_events.commits == 1 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=True) assert status == 200 assert response["permission_keys"] == ["app.acl.view_layout", "app.acl.edit"] @@ -327,6 +372,7 @@ class TestAppImportConfirmApi: api, app: Flask, monkeypatch: pytest.MonkeyPatch, + sqlite_app_engine: Engine, transaction_events: TransactionEvents, ) -> None: method = _unwrap(api.post) @@ -345,10 +391,10 @@ class TestAppImportConfirmApi: ), ) monkeypatch.setattr(app_import_module.dify_config, "RBAC_ENABLED", True) - monkeypatch.setattr( - app_import_module.AppDslService, - "confirm_import", - lambda *_args, **_kwargs: _Result(ImportStatus.COMPLETED, app_id="app-456"), + app_id = _install_persisting_service_result( + monkeypatch, + method_name="confirm_import", + result=_Result(ImportStatus.COMPLETED, app_id="app-456"), ) monkeypatch.setattr( app_import_module, @@ -360,6 +406,7 @@ class TestAppImportConfirmApi: response, status = method(import_id="import-1") assert transaction_events.commits == 1 + _assert_app_persistence(sqlite_app_engine, app_id, persisted=True) assert status == 200 assert response["permission_keys"] == []