Files
xiaoxia-saas/tests/unit/test_phase8_edit_models.py
2026-07-15 13:20:55 +08:00

214 lines
7.3 KiB
Python

"""Unit tests for Phase 8 EditTemplate and EditPlan domain entities + repositories."""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "apps" / "api"))
import logging
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from packages.adapters.sqlalchemy_impl.edit_plan_repository import (
SQLAlchemyEditPlanRepository,
)
from packages.adapters.sqlalchemy_impl.edit_template_repository import (
SQLAlchemyEditTemplateRepository,
)
from packages.adapters.sqlalchemy_impl.models import Base
from packages.domain.edit_plan import EditPlan, EditPlanStatus
from packages.domain.edit_template import EditTemplate, EditTemplateStatus
logger = logging.getLogger(__name__)
# ── EditTemplate 领域实体测试 ──────────────────────────────────────────
class TestEditTemplate:
def test_create_success(self):
t = EditTemplate.create("vlog模板", description="日常vlog", template_type="vlog")
assert t.name == "vlog模板"
assert t.description == "日常vlog"
assert t.template_type == "vlog"
assert t.status == EditTemplateStatus.ACTIVE
assert t.config == {}
assert t.sort_weight == 0
assert t.id # 自动生成
def test_create_strips_whitespace(self):
t = EditTemplate.create(" 模板 ")
assert t.name == "模板"
def test_create_empty_name_raises(self):
try:
EditTemplate.create(" ")
raise AssertionError("应该抛出 ValueError")
except ValueError as e:
assert "模板名称不能为空" in str(e)
def test_activate_deactivate(self):
t = EditTemplate.create("test")
assert t.is_active is True
t.deactivate()
assert t.is_active is False
assert t.status == EditTemplateStatus.INACTIVE
t.activate()
assert t.is_active is True
assert t.status == EditTemplateStatus.ACTIVE
# ── EditPlan 领域实体测试 ──────────────────────────────────────────────
class TestEditPlan:
def test_create_success(self):
p = EditPlan.create("tpl-1", "我的计划", config={"bgm": "happy"})
assert p.template_id == "tpl-1"
assert p.name == "我的计划"
assert p.status == EditPlanStatus.DRAFT
assert p.config == {"bgm": "happy"}
assert p.total_duration == 0.0
def test_create_empty_name_raises(self):
try:
EditPlan.create("tpl-1", " ")
raise AssertionError("应该抛出 ValueError")
except ValueError as e:
assert "计划名称不能为空" in str(e)
def test_create_empty_template_id_raises(self):
try:
EditPlan.create(" ", "test")
raise AssertionError("应该抛出 ValueError")
except ValueError as e:
assert "template_id 不能为空" in str(e)
def test_status_transitions_happy_path(self):
p = EditPlan.create("tpl-1", "test")
assert p.status == EditPlanStatus.DRAFT
p.start_editing()
assert p.status == EditPlanStatus.EDITING
p.start_rendering()
assert p.status == EditPlanStatus.RENDERING
p.mark_completed()
assert p.status == EditPlanStatus.COMPLETED
def test_status_transitions_failure_path(self):
p = EditPlan.create("tpl-1", "test")
p.start_editing()
p.start_rendering()
p.mark_failed()
assert p.status == EditPlanStatus.FAILED
p.reset_to_draft()
assert p.status == EditPlanStatus.DRAFT
def test_invalid_transition_raises(self):
p = EditPlan.create("tpl-1", "test")
try:
p.start_rendering() # draft → rendering 不合法
raise AssertionError("应该抛出 ValueError")
except ValueError as e:
logger.warning(f"Operation failed in tests/unit/test_phase8_edit_models.py: {e}", exc_info=True)
def test_mark_completed_from_non_rendering_raises(self):
p = EditPlan.create("tpl-1", "test")
try:
p.mark_completed() # draft → completed 不合法
raise AssertionError("应该抛出 ValueError")
except ValueError as e:
logger.warning(f"Operation failed in tests/unit/test_phase8_edit_models.py: {e}", exc_info=True)
def test_reset_from_non_failed_raises(self):
p = EditPlan.create("tpl-1", "test")
try:
p.reset_to_draft() # draft → draft 不合法
raise AssertionError("应该抛出 ValueError")
except ValueError as e:
logger.warning(f"Operation failed in tests/unit/test_phase8_edit_models.py: {e}", exc_info=True)
# ── Repository 集成测试(内存 SQLite) ─────────────────────────────────
class TestRepositories:
def _make_session(self):
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
SessionLocal = sessionmaker(bind=engine)
return SessionLocal()
def test_edit_template_repository_crud(self):
session = self._make_session()
try:
repo = SQLAlchemyEditTemplateRepository(session)
t = EditTemplate.create("模板A", description="测试模板")
repo.create(t)
fetched = repo.get(t.id)
assert fetched is not None
assert fetched.name == "模板A"
assert fetched.description == "测试模板"
# list
active = repo.list_active()
assert len(active) == 1
assert active[0].id == t.id
# update
fetched.deactivate()
repo.update(fetched)
assert repo.get(t.id).status == EditTemplateStatus.INACTIVE
assert len(repo.list_active()) == 0
# count
assert repo.count() == 1
# delete
assert repo.delete(t.id) is True
assert repo.get(t.id) is None
assert repo.count() == 0
finally:
session.close()
def test_edit_plan_repository_crud(self):
session = self._make_session()
try:
repo = SQLAlchemyEditPlanRepository(session)
p = EditPlan.create("tpl-1", "计划A", config={"key": "val"})
repo.create(p)
fetched = repo.get(p.id)
assert fetched is not None
assert fetched.name == "计划A"
assert fetched.config == {"key": "val"}
assert fetched.status == EditPlanStatus.DRAFT
# list_by_template
plans = repo.list_by_template("tpl-1")
assert len(plans) == 1
# update status
fetched.start_editing()
repo.update(fetched)
editing = repo.list_by_template("tpl-1", status=EditPlanStatus.EDITING)
assert len(editing) == 1
# count
assert repo.count() == 1
assert repo.count(status=EditPlanStatus.EDITING) == 1
assert repo.count(status=EditPlanStatus.DRAFT) == 0
# delete
assert repo.delete(p.id) is True
assert repo.get(p.id) is None
finally:
session.close()