fix: address ui review follow-ups
This commit is contained in:
160
tests/test_project_metadata_e2e.py
Normal file
160
tests/test_project_metadata_e2e.py
Normal file
@@ -0,0 +1,160 @@
|
||||
"""Project list metadata uses real DB state for activity and pending review counts."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from collections.abc import AsyncIterator
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||
from ww_core.domain.project_repo import SqlProjectRepo
|
||||
from ww_db import get_sessionmaker
|
||||
from ww_db.models import Chapter, ChapterReview, Project, User
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def sm() -> AsyncIterator[async_sessionmaker[AsyncSession]]:
|
||||
get_sessionmaker.cache_clear()
|
||||
maker = get_sessionmaker()
|
||||
try:
|
||||
async with maker() as probe:
|
||||
await probe.execute(select(1))
|
||||
except Exception:
|
||||
pytest.skip("postgres not reachable")
|
||||
yield maker
|
||||
await maker.kw["bind"].dispose()
|
||||
get_sessionmaker.cache_clear()
|
||||
|
||||
|
||||
async def _cleanup(
|
||||
sm: async_sessionmaker[AsyncSession], owner_id: uuid.UUID, project_id: uuid.UUID
|
||||
) -> None:
|
||||
async with sm() as session:
|
||||
await session.execute(delete(ChapterReview).where(ChapterReview.project_id == project_id))
|
||||
await session.execute(delete(Chapter).where(Chapter.project_id == project_id))
|
||||
await session.execute(delete(Project).where(Project.id == project_id))
|
||||
await session.execute(delete(User).where(User.id == owner_id))
|
||||
await session.commit()
|
||||
|
||||
|
||||
async def _project_view(
|
||||
sm: async_sessionmaker[AsyncSession], owner_id: uuid.UUID, project_id: uuid.UUID
|
||||
):
|
||||
async with sm() as session:
|
||||
view = await SqlProjectRepo(session).get(owner_id, project_id)
|
||||
assert view is not None
|
||||
listed = await SqlProjectRepo(session).list_for_owner(owner_id)
|
||||
listed_view = next((item for item in listed if item.id == project_id), None)
|
||||
assert listed_view is not None
|
||||
assert listed_view.pending_review_count == view.pending_review_count
|
||||
assert listed_view.updated_at == view.updated_at
|
||||
return view
|
||||
|
||||
|
||||
async def test_project_metadata_tracks_review_and_acceptance_state(
|
||||
sm: async_sessionmaker[AsyncSession],
|
||||
) -> None:
|
||||
owner_id = uuid.uuid4()
|
||||
project_id = uuid.uuid4()
|
||||
base = datetime(2026, 6, 1, tzinfo=UTC)
|
||||
|
||||
await _cleanup(sm, owner_id, project_id)
|
||||
try:
|
||||
async with sm() as session:
|
||||
session.add(
|
||||
User(
|
||||
id=owner_id,
|
||||
email=f"{owner_id}@example.test",
|
||||
display_name="metadata test",
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
async with sm() as session:
|
||||
session.add(
|
||||
Project(
|
||||
id=project_id,
|
||||
owner_id=owner_id,
|
||||
title="元数据测试",
|
||||
created_at=base,
|
||||
updated_at=base,
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
async with sm() as session:
|
||||
session.add(
|
||||
Chapter(
|
||||
project_id=project_id,
|
||||
volume=1,
|
||||
chapter_no=1,
|
||||
content="草稿一",
|
||||
status="draft",
|
||||
version=1,
|
||||
created_at=base + timedelta(hours=1),
|
||||
updated_at=base + timedelta(hours=1),
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
view = await _project_view(sm, owner_id, project_id)
|
||||
assert view.pending_review_count == 1
|
||||
assert view.updated_at == base + timedelta(hours=1)
|
||||
|
||||
async with sm() as session:
|
||||
session.add(
|
||||
ChapterReview(
|
||||
project_id=project_id,
|
||||
chapter_no=1,
|
||||
chapter_version=1,
|
||||
conflicts=[],
|
||||
foreshadow_sug=[],
|
||||
created_at=base + timedelta(hours=2),
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
view = await _project_view(sm, owner_id, project_id)
|
||||
assert view.pending_review_count == 0
|
||||
assert view.updated_at == base + timedelta(hours=2)
|
||||
|
||||
async with sm() as session:
|
||||
session.add(
|
||||
Chapter(
|
||||
project_id=project_id,
|
||||
volume=1,
|
||||
chapter_no=1,
|
||||
content="终稿一",
|
||||
status="accepted",
|
||||
version=2,
|
||||
created_at=base + timedelta(hours=3),
|
||||
updated_at=base + timedelta(hours=3),
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
view = await _project_view(sm, owner_id, project_id)
|
||||
assert view.pending_review_count == 0
|
||||
assert view.updated_at == base + timedelta(hours=3)
|
||||
|
||||
async with sm() as session:
|
||||
draft = (
|
||||
await session.execute(
|
||||
select(Chapter).where(
|
||||
Chapter.project_id == project_id,
|
||||
Chapter.chapter_no == 1,
|
||||
Chapter.version == 1,
|
||||
)
|
||||
)
|
||||
).scalar_one()
|
||||
draft.content = "验收后再改草稿"
|
||||
draft.updated_at = base + timedelta(hours=4)
|
||||
await session.commit()
|
||||
|
||||
view = await _project_view(sm, owner_id, project_id)
|
||||
assert view.pending_review_count == 1
|
||||
assert view.updated_at == base + timedelta(hours=4)
|
||||
finally:
|
||||
await _cleanup(sm, owner_id, project_id)
|
||||
Reference in New Issue
Block a user