109 lines
3.8 KiB
Python
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()
|