diff --git a/tests/integration/test_generation_api.py b/tests/integration/test_generation_api.py index 17256c7ef..e516dd0d4 100755 --- a/tests/integration/test_generation_api.py +++ b/tests/integration/test_generation_api.py @@ -138,6 +138,70 @@ class StubGenerationTaskRepository: def list_by_source_edit_plan(self, plan_id: str) -> list[GenerationTask]: return [t for t in self._tasks.values() if getattr(t, "source_edit_plan_id", "") == plan_id] + def list_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按用户+状态筛选任务列表(stub实现)。""" + items = [t for t in self._tasks.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + ) -> int: + """按用户+状态筛选计数(stub实现)。""" + items = [t for t in self._tasks.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + + def list_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按项目+状态筛选任务列表(stub实现)。""" + items = [t for t in self._tasks.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + ) -> int: + """按项目+状态筛选计数(stub实现)。""" + items = [t for t in self._tasks.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + class StubGeneratedVideoRepository: def __init__(self, videos: dict[str, GeneratedVideo] | None = None): diff --git a/tests/integration/test_task_center_api.py b/tests/integration/test_task_center_api.py index a55f5b2ee..67c7dc516 100755 --- a/tests/integration/test_task_center_api.py +++ b/tests/integration/test_task_center_api.py @@ -103,6 +103,70 @@ class StubGenerationTaskRepository: def list_by_source_edit_plan(self, plan_id: str) -> list[GenerationTask]: return [t for t in self._tasks.values() if getattr(t, "source_edit_plan_id", "") == plan_id] + def list_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按用户+状态筛选任务列表(stub实现)。""" + items = [t for t in self._tasks.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + ) -> int: + """按用户+状态筛选计数(stub实现)。""" + items = [t for t in self._tasks.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + + def list_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按项目+状态筛选任务列表(stub实现)。""" + items = [t for t in self._tasks.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + ) -> int: + """按项目+状态筛选计数(stub实现)。""" + items = [t for t in self._tasks.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + class StubIngestJobRepository: def __init__(self, jobs: dict[str, IngestJob] | None = None): @@ -470,8 +534,8 @@ class TestRetryProjectTask: assert data["task_type"] == "generation" assert data["status"] == "pending" assert "current_step" in data - # 验证新任务的 ID 不同于原任务 - assert data["source_id"] != "gen-failed-1" + # 原地重试:source_id 保持不变(复用同一个任务) + assert data["source_id"] == "gen-failed-1" # 验证 Celery 任务被发送 assert mock_celery.send_task.called @@ -630,11 +694,13 @@ class TestTaskCenterCrossEndpoint: retry_resp = tc.post("/tasks/gen-fail-cross/retry") assert retry_resp.status_code == 200 - # 3. 再次列出,应有2个任务(旧的failed + 新的pending) + # 3. 再次列出:原地重试,任务数不变(仍是1个),但状态变为 pending list_resp2 = tc.get("/tasks") assert list_resp2.status_code == 200 items2 = list_resp2.json()["items"] - assert len(items2) == 2 + assert len(items2) == 1 + assert items2[0]["status"] == "pending" + assert items2[0]["source_id"] == "gen-fail-cross" test_app.dependency_overrides.clear() diff --git a/tests/unit/test_edit_plan_generation_api.py b/tests/unit/test_edit_plan_generation_api.py index 1479514d9..85a1b3e03 100644 --- a/tests/unit/test_edit_plan_generation_api.py +++ b/tests/unit/test_edit_plan_generation_api.py @@ -193,6 +193,70 @@ class StubGenerationTaskRepository: items.sort(key=lambda t: t.created_at, reverse=True) return items[:limit] + def list_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按用户+状态筛选任务列表(stub实现)。""" + items = [t for t in self._store.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + ) -> int: + """按用户+状态筛选计数(stub实现)。""" + items = [t for t in self._store.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + + def list_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按项目+状态筛选任务列表(stub实现)。""" + items = [t for t in self._store.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + ) -> int: + """按项目+状态筛选计数(stub实现)。""" + items = [t for t in self._store.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + # ── Fixtures ────────────────────────────────────────────────────────────────── diff --git a/tests/unit/test_edit_plan_service.py b/tests/unit/test_edit_plan_service.py index eb9be6c2c..f67335642 100755 --- a/tests/unit/test_edit_plan_service.py +++ b/tests/unit/test_edit_plan_service.py @@ -200,6 +200,70 @@ class StubGenerationTaskRepository: def count_pending_total(self) -> int: return 0 + def list_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按用户+状态筛选任务列表(stub实现)。""" + items = [t for t in self._tasks.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_user_filtered( + self, + user_id: str, + *, + status: str | None = None, + ) -> int: + """按用户+状态筛选计数(stub实现)。""" + items = [t for t in self._tasks.values() if t.created_by_user_id == user_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + + def list_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + limit: int | None = None, + offset: int = 0, + ) -> list: + """按项目+状态筛选任务列表(stub实现)。""" + items = [t for t in self._tasks.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + # 按创建时间倒序 + items.sort(key=lambda t: t.created_at or "", reverse=True) + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_project_filtered( + self, + project_id: str, + *, + status: str | None = None, + ) -> int: + """按项目+状态筛选计数(stub实现)。""" + items = [t for t in self._tasks.values() if t.project_id == project_id] + if status: + items = [t for t in items if str(t.status) == status] + return len(items) + # --------------------------------------------------------------------------- # Service factory diff --git a/tests/unit/test_generation_presigned_url.py b/tests/unit/test_generation_presigned_url.py index d22088206..e4453cbf1 100755 --- a/tests/unit/test_generation_presigned_url.py +++ b/tests/unit/test_generation_presigned_url.py @@ -64,6 +64,38 @@ class StubGenerationTaskRepository: def count_pending_total(self): return 0 + def list_by_user_filtered(self, user_id, *, status=None, limit=None, offset=0): + items = [t for t in self._tasks.values() if getattr(t, "created_by_user_id", None) == user_id] + if status: + items = [t for t in items if getattr(t, "status", None) == status] + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_user_filtered(self, user_id, *, status=None): + items = [t for t in self._tasks.values() if getattr(t, "created_by_user_id", None) == user_id] + if status: + items = [t for t in items if getattr(t, "status", None) == status] + return len(items) + + def list_by_project_filtered(self, project_id, *, status=None, limit=None, offset=0): + items = [t for t in self._tasks.values() if getattr(t, "project_id", None) == project_id] + if status: + items = [t for t in items if getattr(t, "status", None) == status] + if offset: + items = items[offset:] + if limit is not None: + items = items[:limit] + return items + + def count_by_project_filtered(self, project_id, *, status=None): + items = [t for t in self._tasks.values() if getattr(t, "project_id", None) == project_id] + if status: + items = [t for t in items if getattr(t, "status", None) == status] + return len(items) + class StubGeneratedVideoRepository: def __init__(self, videos=None):