Files
Jellyfish/backend/tests/test_script_division.py
T

109 lines
3.8 KiB
Python

from __future__ import annotations
import pytest
from fastapi import HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from app.core.db import Base
from app.models.studio import (
CameraAngle,
CameraMovement,
CameraShotType,
Chapter,
Project,
ProjectStyle,
ProjectVisualStyle,
Shot,
ShotDetail,
VFXType,
)
from app.schemas.skills.script_processing import ScriptDivisionResult, ShotDivision
from app.services.studio.script_division import write_division_result_to_chapter
async def _build_session() -> tuple[AsyncSession, object]:
engine = create_async_engine("sqlite+aiosqlite:///:memory:", future=True)
session_local = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
return session_local(), engine
def _division_result() -> ScriptDivisionResult:
return ScriptDivisionResult(
shots=[
ShotDivision(
index=1,
start_line=1,
end_line=3,
script_excerpt="主角走进房间。",
shot_name="进入房间",
),
ShotDivision(
index=2,
start_line=4,
end_line=6,
script_excerpt="镜头切到窗边。",
shot_name="窗边对话",
),
],
total_shots=2,
notes="test",
)
@pytest.mark.asyncio
async def test_write_division_result_to_empty_chapter_creates_shots_and_details() -> None:
db, engine = await _build_session()
async with db:
project = Project(
id="p1",
name="项目一",
description="",
style=ProjectStyle.real_people_city,
visual_style=ProjectVisualStyle.live_action,
)
chapter = Chapter(id="c1", project_id="p1", index=1, title="第一章")
db.add_all([project, chapter])
await db.commit()
await write_division_result_to_chapter(db, chapter_id="c1", result=_division_result())
shots = (await db.execute(select(Shot).order_by(Shot.index.asc()))).scalars().all()
details = (await db.execute(select(ShotDetail).order_by(ShotDetail.id.asc()))).scalars().all()
assert [shot.title for shot in shots] == ["进入房间", "窗边对话"]
assert [shot.index for shot in shots] == [1, 2]
assert len(details) == 2
assert all(detail.camera_shot == CameraShotType.ms for detail in details)
assert all(detail.angle == CameraAngle.eye_level for detail in details)
assert all(detail.movement == CameraMovement.static for detail in details)
assert all(detail.duration == 4 for detail in details)
assert all(detail.vfx_type == VFXType.none for detail in details)
await engine.dispose()
@pytest.mark.asyncio
async def test_write_division_result_refuses_when_chapter_already_has_shots() -> None:
db, engine = await _build_session()
async with db:
project = Project(
id="p1",
name="项目一",
description="",
style=ProjectStyle.real_people_city,
visual_style=ProjectVisualStyle.live_action,
)
chapter = Chapter(id="c1", project_id="p1", index=1, title="第一章")
existing_shot = Shot(id="s1", chapter_id="c1", index=1, title="已有镜头")
db.add_all([project, chapter, existing_shot])
await db.commit()
with pytest.raises(HTTPException) as exc_info:
await write_division_result_to_chapter(db, chapter_id="c1", result=_division_result())
assert exc_info.value.status_code == 400
assert "already has shots" in exc_info.value.detail
await engine.dispose()