diff --git a/alembic/versions/077_merge_title_library_into_scripts.py b/alembic/versions/077_merge_title_library_into_scripts.py index e5e6f706c..4ba5f0a91 100644 --- a/alembic/versions/077_merge_title_library_into_scripts.py +++ b/alembic/versions/077_merge_title_library_into_scripts.py @@ -6,6 +6,7 @@ Create Date: 2026-09-15 """ import sqlalchemy as sa + from alembic import op revision = "077_merge_title_library_into_scripts" @@ -29,9 +30,7 @@ def upgrade() -> None: # 从 title_libraries 迁移活跃数据到 scripts(若 title_libraries 表存在) conn = op.get_bind() - exists = conn.execute( - sa.text("SELECT to_regclass('public.title_libraries') IS NOT NULL") - ).scalar() + exists = conn.execute(sa.text("SELECT to_regclass('public.title_libraries') IS NOT NULL")).scalar() if exists: conn.execute(sa.text(""" INSERT INTO scripts (id, user_id, title, content, segments, tags, title_text, title_category, title_config, created_at, updated_at) diff --git a/tests/unit/test_script_title_integration.py b/tests/unit/test_script_title_integration.py index 672097549..3cf64aac6 100644 --- a/tests/unit/test_script_title_integration.py +++ b/tests/unit/test_script_title_integration.py @@ -16,12 +16,11 @@ from unittest.mock import MagicMock, patch import pytest from fastapi.testclient import TestClient - from main import app - # ── helpers ────────────────────────────────────────────────────────────── + def _make_script(**overrides): """构造一个模拟 ScriptModel 对象.""" defaults = dict( @@ -33,7 +32,13 @@ def _make_script(**overrides): tags=["测试"], title_text="开场大标题", title_category="片头", - title_config={"text": "开场大标题", "font": "思源黑体", "font_size": 48, "font_color": "#FFFFFF", "position": "top"}, + title_config={ + "text": "开场大标题", + "font": "思源黑体", + "font_size": 48, + "font_color": "#FFFFFF", + "position": "top", + }, created_at=datetime(2026, 9, 1, tzinfo=timezone.utc), updated_at=datetime(2026, 9, 1, tzinfo=timezone.utc), ) @@ -43,11 +48,13 @@ def _make_script(**overrides): # ── TestScriptModelNewFields ───────────────────────────────────────────── + class TestScriptModelNewFields: """验证 ScriptModel 新增字段的定义.""" def test_model_has_title_text_column(self): from packages.adapters.sqlalchemy_impl.models import ScriptModel + assert hasattr(ScriptModel, "title_text") col = ScriptModel.__table__.columns["title_text"] assert col is not None @@ -55,6 +62,7 @@ class TestScriptModelNewFields: def test_model_has_title_category_column(self): from packages.adapters.sqlalchemy_impl.models import ScriptModel + assert hasattr(ScriptModel, "title_category") col = ScriptModel.__table__.columns["title_category"] assert col is not None @@ -62,6 +70,7 @@ class TestScriptModelNewFields: def test_model_has_title_config_column(self): from packages.adapters.sqlalchemy_impl.models import ScriptModel + assert hasattr(ScriptModel, "title_config") col = ScriptModel.__table__.columns["title_config"] assert col is not None @@ -69,6 +78,7 @@ class TestScriptModelNewFields: def test_model_defaults(self): """新字段默认值为空字符串/空 dict.""" from packages.adapters.sqlalchemy_impl.models import ScriptModel + s = ScriptModel(id="x", user_id="u", title="t") # 检查 default 值 assert ScriptModel.__table__.columns["title_text"].default.arg == "" @@ -77,6 +87,7 @@ class TestScriptModelNewFields: # ── TestScriptServiceTitleConfig ───────────────────────────────────────── + class TestScriptServiceTitleConfig: """验证 ScriptService 新方法 get_title_config_for_script.""" @@ -137,6 +148,7 @@ class TestScriptServiceTitleConfig: # ── TestScriptServiceCreateWithNewFields ───────────────────────────────── + class TestScriptServiceCreateWithNewFields: """验证 create_script 和 update_script 支持新字段.""" @@ -184,6 +196,7 @@ class TestScriptServiceCreateWithNewFields: # ── TestScriptsRoutesNewFields ─────────────────────────────────────────── + class TestScriptsRoutesNewFields: """验证 scripts API 路由正确处理新字段.""" @@ -196,12 +209,15 @@ class TestScriptsRoutesNewFields: mock_svc = MagicMock() mock_svc.create_script.return_value = mock_script - from app.auth import get_current_user from app.api.routes.scripts import _get_service + from app.auth import get_current_user + async def _fake_user(): return MagicMock(user=MagicMock(id="user-001")) + def _fake_svc(): return mock_svc + app.dependency_overrides[get_current_user] = _fake_user app.dependency_overrides[_get_service] = _fake_svc try: @@ -235,12 +251,15 @@ class TestScriptsRoutesNewFields: mock_svc = MagicMock() mock_svc.get_script.return_value = mock_script - from app.auth import get_current_user from app.api.routes.scripts import _get_service + from app.auth import get_current_user + async def _fake_user(): return MagicMock(user=MagicMock(id="user-001")) + def _fake_svc(): return mock_svc + app.dependency_overrides[get_current_user] = _fake_user app.dependency_overrides[_get_service] = _fake_svc try: @@ -258,6 +277,7 @@ class TestScriptsRoutesNewFields: # ── TestTitleLibraryDeprecated ─────────────────────────────────────────── + class TestTitleLibraryDeprecated: """验证 title_libraries API 返回 deprecated Warning header.""" @@ -265,12 +285,15 @@ class TestTitleLibraryDeprecated: mock_repo = MagicMock() mock_repo.count_by_user.return_value = 0 - from app.auth import get_current_user from app.api.routes.titles import _get_title_repository + from app.auth import get_current_user + async def _fake_user(): return MagicMock(user=MagicMock(id="user-001")) + def _fake_repo(): return mock_repo + app.dependency_overrides[get_current_user] = _fake_user app.dependency_overrides[_get_title_repository] = _fake_repo try: @@ -284,20 +307,31 @@ class TestTitleLibraryDeprecated: def test_get_title_has_warning_header(self): from packages.domain.title_library import TitleLibraryItem + mock_item = TitleLibraryItem( - id="t1", user_id="user-001", name="测试", text="标题文字", - category="通用", description="", tags=[], usage_count=0, - is_active=True, created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), + id="t1", + user_id="user-001", + name="测试", + text="标题文字", + category="通用", + description="", + tags=[], + usage_count=0, + is_active=True, + created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc), ) mock_repo = MagicMock() - from app.auth import get_current_user from app.api.routes.titles import _get_title_repository + from app.auth import get_current_user + async def _fake_user(): return MagicMock(user=MagicMock(id="user-001")) + def _fake_repo(): return mock_repo + app.dependency_overrides[get_current_user] = _fake_user app.dependency_overrides[_get_title_repository] = _fake_repo try: