From d49c49a1c0719bf6b2595e135e58b2d6d796e478 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 4 Aug 2026 00:45:33 +0800 Subject: [PATCH 1/7] fix: preview resolution auto-infer from template mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When frontend doesn't pass video_ratio, backend infers from template.mode: - pip → 9:16 → 480x854 - standard → 16:9 → 854x480 --- apps/api/app/api/routes/generation_preview.py | 56 +++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/apps/api/app/api/routes/generation_preview.py b/apps/api/app/api/routes/generation_preview.py index f27d26d6e..109b1c781 100755 --- a/apps/api/app/api/routes/generation_preview.py +++ b/apps/api/app/api/routes/generation_preview.py @@ -17,6 +17,7 @@ from app.core.task_enqueue import ( safe_enqueue_generation_task, ) from app.dependencies import ( + get_db_session, get_generated_video_repository, get_generation_task_repository, ) @@ -25,7 +26,11 @@ from app.schemas.generation_task import ( PreviewGenerationTaskResponse, ) from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from packages.adapters.sqlalchemy_impl.template_repository import ( + SQLAlchemyTemplateRepository, +) from packages.application import ( CreateGenerationTaskCommand, CreateGenerationTaskUseCase, @@ -39,6 +44,13 @@ router = APIRouter() PREVIEW_RESOLUTION = "854x480" +# 模板 mode → 视频比例映射 +_TEMPLATE_MODE_TO_RATIO = { + "pip": "9:16", + "standard": "16:9", + "square": "1:1", +} + def _calc_preview_resolution(video_ratio: str = "") -> str: """根据视频比例计算预览分辨率(短边 480,长边按比例)。 @@ -55,6 +67,36 @@ def _calc_preview_resolution(video_ratio: str = "") -> str: return ratio_map.get(video_ratio.strip(), PREVIEW_RESOLUTION) +def _infer_video_ratio_from_template(template_id: str, db: Session) -> str: + """从模板 mode 推断视频比例,前端未传 video_ratio 时使用。 + + Returns: + 视频比例字符串(如 "9:16"),查询失败返回空字符串。 + """ + if not template_id: + return "" + try: + repo = SQLAlchemyTemplateRepository(db) + template = repo.get_by_id(template_id) + if template: + mode = getattr(template, "mode", "") or "" + ratio = _TEMPLATE_MODE_TO_RATIO.get(mode.strip(), "") + if ratio: + logger.info( + "[预览生成] 从模板 mode=%s 推断 video_ratio=%s", + mode, + ratio, + ) + return ratio + except Exception: + logger.warning( + "[预览生成] 查询模板失败,跳过 video_ratio 推断: template_id=%s", + template_id, + exc_info=True, + ) + return "" + + def _mark_task_failed(repo, task, reason: str) -> None: """入队失败时将任务标记为 failed,避免产生僵尸 pending 数据。""" try: @@ -146,6 +188,7 @@ def create_preview_generation_task( request: CreatePreviewGenerationTaskRequest, authenticated_user: AuthenticatedUser = Depends(get_current_user), generation_task_repository=Depends(get_generation_task_repository), + db: Session = Depends(get_db_session), ) -> PreviewGenerationTaskResponse: """创建预览生成任务。 @@ -176,7 +219,7 @@ def create_preview_generation_task( except UserPendingLimitExceeded as e: raise HTTPException( status_code=429, - detail=f"您的待处理任务过多(当前 {e.pending_count - 1}/{e.limit}),请等待完成后再提交", + detail=f"您的待处理任务过多(当前 {e.pending_count - 1}/{e.limit}),请等待后再提交", ) from e except GlobalQueueFull as e: raise HTTPException( @@ -184,6 +227,11 @@ def create_preview_generation_task( detail="系统繁忙,请稍后再试", ) from e + # 确定视频比例:优先前端传入,否则从模板 mode 推断 + video_ratio = request.video_ratio or "" + if not video_ratio and request.template_id: + video_ratio = _infer_video_ratio_from_template(request.template_id, db) + use_case = CreateGenerationTaskUseCase(generation_task_repository) try: @@ -202,7 +250,7 @@ def create_preview_generation_task( asset_select_mode="", batch_id="", video_title=request.video_title, - resolution=_calc_preview_resolution(request.video_ratio), + resolution=_calc_preview_resolution(video_ratio), bgm_config=request.bgm_config or {}, auto_retry_enabled=False, auto_retry_max=0, @@ -214,7 +262,7 @@ def create_preview_generation_task( raise HTTPException(status_code=400, detail=str(e)) from e except Exception as e: logger.error("[预览生成] 创建失败: %s", e, exc_info=True) - raise HTTPException(status_code=500, detail="创建预览生成任务失败,请稍后重试") from e + raise HTTPException(status_code=500, detail="创建预览生成任务失败,请稍后再试") from e # 入队执行;若入队失败则标记任务为 failed 避免僵尸数据 try: @@ -232,7 +280,7 @@ def create_preview_generation_task( _mark_task_failed(generation_task_repository, task, "待处理任务超限") raise HTTPException( status_code=429, - detail="您的待处理任务过多,请等待完成后再提交", + detail=f"您的待处理任务过多(当前 {e.pending_count - 1}/{e.limit}),请等待后再提交", ) from None except GlobalQueueFull: _mark_task_failed(generation_task_repository, task, "系统队列已满") -- 2.54.0 From 1d973554c85879cc21f424baf40038181858d67a Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 4 Aug 2026 00:45:34 +0800 Subject: [PATCH 2/7] test: add template mode inference tests - TestInferVideoRatioFromTemplate: 6 tests - TestPreviewRouteAutoInfersVideoRatio: integration test - Update existing route tests with db mock --- tests/unit/test_generation_preview.py | 164 ++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/tests/unit/test_generation_preview.py b/tests/unit/test_generation_preview.py index de1ad7bec..d3fcd497f 100755 --- a/tests/unit/test_generation_preview.py +++ b/tests/unit/test_generation_preview.py @@ -726,6 +726,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert resp.task_id == "preview_task_001" assert resp.status == "pending" @@ -743,6 +744,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 429 @@ -759,6 +761,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 503 @@ -777,6 +780,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 400 @@ -795,6 +799,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 500 @@ -818,6 +823,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 500 @@ -841,6 +847,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 429 @@ -864,6 +871,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), ) assert exc_info.value.status_code == 503 @@ -885,6 +893,7 @@ class TestGetPreviewRoute: task_id="nonexistent", authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 404 @@ -905,6 +914,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user("test_user_001"), generation_task_repository=repo, + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 403 @@ -925,6 +935,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 404 @@ -941,6 +952,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), generated_video_repository=vid_repo, ) assert resp.status == "pending" @@ -962,6 +974,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 403 @@ -990,6 +1003,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, + db=MagicMock(), generated_video_repository=vid_repo, ) assert resp.video_url == "https://cdn.example.com/preview_final.mp4?sig=abc123" @@ -1152,3 +1166,153 @@ class TestCalcPreviewResolution: from app.api.routes.generation_preview import _calc_preview_resolution assert _calc_preview_resolution("") == "854x480" + + + +class TestInferVideoRatioFromTemplate: + """_infer_video_ratio_from_template 单元测试。""" + + def test_pip_mode_returns_9_16(self): + """模板 mode=pip → 返回 '9:16'""" + from app.api.routes.generation_preview import _infer_video_ratio_from_template + + mock_template = MagicMock() + mock_template.mode = "pip" + mock_db = MagicMock() + + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: + MockRepo.return_value.get_by_id.return_value = mock_template + result = _infer_video_ratio_from_template("tpl_001", mock_db) + assert result == "9:16" + + def test_standard_mode_returns_16_9(self): + """模板 mode=standard → 返回 '16:9'""" + from app.api.routes.generation_preview import _infer_video_ratio_from_template + + mock_template = MagicMock() + mock_template.mode = "standard" + mock_db = MagicMock() + + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: + MockRepo.return_value.get_by_id.return_value = mock_template + result = _infer_video_ratio_from_template("tpl_001", mock_db) + assert result == "16:9" + + def test_unknown_mode_returns_empty(self): + """模板 mode 未知 → 返回空字符串""" + from app.api.routes.generation_preview import _infer_video_ratio_from_template + + mock_template = MagicMock() + mock_template.mode = "unknown_mode" + mock_db = MagicMock() + + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: + MockRepo.return_value.get_by_id.return_value = mock_template + result = _infer_video_ratio_from_template("tpl_001", mock_db) + assert result == "" + + def test_template_not_found_returns_empty(self): + """模板不存在 → 返回空字符串""" + from app.api.routes.generation_preview import _infer_video_ratio_from_template + + mock_db = MagicMock() + + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: + MockRepo.return_value.get_by_id.return_value = None + result = _infer_video_ratio_from_template("nonexistent", mock_db) + assert result == "" + + def test_empty_template_id_returns_empty(self): + """空 template_id → 直接返回空字符串""" + from app.api.routes.generation_preview import _infer_video_ratio_from_template + + mock_db = MagicMock() + result = _infer_video_ratio_from_template("", mock_db) + assert result == "" + + def test_db_exception_returns_empty(self): + """DB 异常 → 返回空字符串,不抛出""" + from app.api.routes.generation_preview import _infer_video_ratio_from_template + + mock_db = MagicMock() + + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: + MockRepo.side_effect = Exception("db connection error") + result = _infer_video_ratio_from_template("tpl_001", mock_db) + assert result == "" + + +class TestPreviewRouteAutoInfersVideoRatio: + """验证预览路由在前端未传 video_ratio 时自动从模板推断。""" + + def test_auto_infer_pip_resolution(self): + """前端传 video_ratio='',模板 mode=pip → resolution=480x854""" + from app.api.routes.generation_preview import create_preview_generation_task + from app.schemas.generation_task import CreatePreviewGenerationTaskRequest + + repo = MagicMock() + repo.count_pending_by_user.return_value = 0 + repo.count_pending_total.return_value = 0 + mock_db = MagicMock() + + mock_template = MagicMock() + mock_template.mode = "pip" + + task = MagicMock() + task.id = "preview_auto_001" + task.status = MagicMock() + task.status.value = "pending" + task.progress = 0.0 + task.is_preview = True + task.resolution = "480x854" + task.error_message = "" + task.extra_meta = {} + task.asset_ids = ["a1"] + task.created_at = "2026-08-04T00:00:00" + task.started_at = None + task.completed_at = None + + request = CreatePreviewGenerationTaskRequest( + template_id="tpl_pip", + asset_ids=["a1"], + title_ids=[], + voice_ids=[], + video_title="test", + duration=0.0, + video_ratio="", + bgm_config={}, + ) + + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: + MockRepo.return_value.get_by_id.return_value = mock_template + with patch( + "app.api.routes.generation_preview.CreateGenerationTaskUseCase" + ) as MockUC: + MockUC.return_value.execute.return_value = task + with patch( + "app.api.routes.generation_preview.safe_enqueue_generation_task", + return_value=True, + ): + resp = create_preview_generation_task( + request, + authenticated_user=_make_user(), + generation_task_repository=repo, + db=mock_db, + ) + + # Verify the resolution passed to CreateGenerationTaskCommand + call_args = MockUC.return_value.execute.call_args + cmd = call_args[0][0] + assert cmd.resolution == "480x854", f"Expected 480x854, got {cmd.resolution}" -- 2.54.0 From 9ceb545f076db6c536e1aaf6b837d0ee59503eef Mon Sep 17 00:00:00 2001 From: CI Bot Date: Mon, 3 Aug 2026 16:47:51 +0000 Subject: [PATCH 3/7] style: auto-format with black + isort + prettier [skip ci-format-check] --- tests/unit/test_generation_preview.py | 51 ++++++++++----------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/tests/unit/test_generation_preview.py b/tests/unit/test_generation_preview.py index d3fcd497f..139faa03e 100755 --- a/tests/unit/test_generation_preview.py +++ b/tests/unit/test_generation_preview.py @@ -726,7 +726,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), ) assert resp.task_id == "preview_task_001" assert resp.status == "pending" @@ -780,7 +780,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), ) assert exc_info.value.status_code == 400 @@ -799,7 +799,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), ) assert exc_info.value.status_code == 500 @@ -823,7 +823,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), ) assert exc_info.value.status_code == 500 @@ -847,7 +847,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), ) assert exc_info.value.status_code == 429 @@ -871,7 +871,7 @@ class TestCreatePreviewRoute: self._make_request(), authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), ) assert exc_info.value.status_code == 503 @@ -893,7 +893,7 @@ class TestGetPreviewRoute: task_id="nonexistent", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 404 @@ -914,7 +914,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user("test_user_001"), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 403 @@ -935,7 +935,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 404 @@ -974,7 +974,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 403 @@ -1003,7 +1003,7 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), + db=MagicMock(), generated_video_repository=vid_repo, ) assert resp.video_url == "https://cdn.example.com/preview_final.mp4?sig=abc123" @@ -1168,7 +1168,6 @@ class TestCalcPreviewResolution: assert _calc_preview_resolution("") == "854x480" - class TestInferVideoRatioFromTemplate: """_infer_video_ratio_from_template 单元测试。""" @@ -1180,9 +1179,7 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "pip" mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "9:16" @@ -1195,9 +1192,7 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "standard" mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "16:9" @@ -1210,9 +1205,7 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "unknown_mode" mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "" @@ -1223,9 +1216,7 @@ class TestInferVideoRatioFromTemplate: mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = None result = _infer_video_ratio_from_template("nonexistent", mock_db) assert result == "" @@ -1244,9 +1235,7 @@ class TestInferVideoRatioFromTemplate: mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.side_effect = Exception("db connection error") result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "" @@ -1293,13 +1282,9 @@ class TestPreviewRouteAutoInfersVideoRatio: bgm_config={}, ) - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template - with patch( - "app.api.routes.generation_preview.CreateGenerationTaskUseCase" - ) as MockUC: + with patch("app.api.routes.generation_preview.CreateGenerationTaskUseCase") as MockUC: MockUC.return_value.execute.return_value = task with patch( "app.api.routes.generation_preview.safe_enqueue_generation_task", -- 2.54.0 From ee50743b8ce37397f11865c261ec6377f78a1140 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 4 Aug 2026 00:54:45 +0800 Subject: [PATCH 4/7] fix: except blocks bind 'as e' for error detail references --- apps/api/app/api/routes/generation_preview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/api/app/api/routes/generation_preview.py b/apps/api/app/api/routes/generation_preview.py index 109b1c781..1a7a3a2a0 100755 --- a/apps/api/app/api/routes/generation_preview.py +++ b/apps/api/app/api/routes/generation_preview.py @@ -276,13 +276,13 @@ def create_preview_generation_task( logger.warning("[预览生成] 任务入队失败: task_id=%s", task.id) _mark_task_failed(generation_task_repository, task, "任务入队失败") raise HTTPException(status_code=500, detail="任务入队失败,请稍后重试") - except UserPendingLimitExceeded: + except UserPendingLimitExceeded as e: _mark_task_failed(generation_task_repository, task, "待处理任务超限") raise HTTPException( status_code=429, detail=f"您的待处理任务过多(当前 {e.pending_count - 1}/{e.limit}),请等待后再提交", ) from None - except GlobalQueueFull: + except GlobalQueueFull as e: _mark_task_failed(generation_task_repository, task, "系统队列已满") raise HTTPException( status_code=503, -- 2.54.0 From 57996909f83c7aba4f67b4892aec940007db77c7 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 4 Aug 2026 00:54:46 +0800 Subject: [PATCH 5/7] fix: only add db mock to create_preview calls, not get_preview + add inference tests --- tests/unit/test_generation_preview.py | 48 ++++++++++++--------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/tests/unit/test_generation_preview.py b/tests/unit/test_generation_preview.py index 139faa03e..33e174aab 100755 --- a/tests/unit/test_generation_preview.py +++ b/tests/unit/test_generation_preview.py @@ -893,7 +893,6 @@ class TestGetPreviewRoute: task_id="nonexistent", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 404 @@ -914,7 +913,6 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user("test_user_001"), generation_task_repository=repo, - db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 403 @@ -935,7 +933,6 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 404 @@ -952,7 +949,6 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), generated_video_repository=vid_repo, ) assert resp.status == "pending" @@ -974,7 +970,6 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), generated_video_repository=vid_repo, ) assert exc_info.value.status_code == 403 @@ -1003,7 +998,6 @@ class TestGetPreviewRoute: task_id="preview_task_001", authenticated_user=_make_user(), generation_task_repository=repo, - db=MagicMock(), generated_video_repository=vid_repo, ) assert resp.video_url == "https://cdn.example.com/preview_final.mp4?sig=abc123" @@ -1179,7 +1173,9 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "pip" mock_db = MagicMock() - with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "9:16" @@ -1192,7 +1188,9 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "standard" mock_db = MagicMock() - with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "16:9" @@ -1205,7 +1203,9 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "unknown_mode" mock_db = MagicMock() - with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "" @@ -1216,7 +1216,9 @@ class TestInferVideoRatioFromTemplate: mock_db = MagicMock() - with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: MockRepo.return_value.get_by_id.return_value = None result = _infer_video_ratio_from_template("nonexistent", mock_db) assert result == "" @@ -1235,7 +1237,9 @@ class TestInferVideoRatioFromTemplate: mock_db = MagicMock() - with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: MockRepo.side_effect = Exception("db connection error") result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "" @@ -1257,19 +1261,7 @@ class TestPreviewRouteAutoInfersVideoRatio: mock_template = MagicMock() mock_template.mode = "pip" - task = MagicMock() - task.id = "preview_auto_001" - task.status = MagicMock() - task.status.value = "pending" - task.progress = 0.0 - task.is_preview = True - task.resolution = "480x854" - task.error_message = "" - task.extra_meta = {} - task.asset_ids = ["a1"] - task.created_at = "2026-08-04T00:00:00" - task.started_at = None - task.completed_at = None + task = _make_task() request = CreatePreviewGenerationTaskRequest( template_id="tpl_pip", @@ -1282,9 +1274,13 @@ class TestPreviewRouteAutoInfersVideoRatio: bgm_config={}, ) - with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: + with patch( + "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" + ) as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template - with patch("app.api.routes.generation_preview.CreateGenerationTaskUseCase") as MockUC: + with patch( + "app.api.routes.generation_preview.CreateGenerationTaskUseCase" + ) as MockUC: MockUC.return_value.execute.return_value = task with patch( "app.api.routes.generation_preview.safe_enqueue_generation_task", -- 2.54.0 From b7c6e4e142612faf0d9dbf88b9b7c067a55005ef Mon Sep 17 00:00:00 2001 From: CI Bot Date: Mon, 3 Aug 2026 16:56:37 +0000 Subject: [PATCH 6/7] style: auto-format with black + isort + prettier [skip ci-format-check] --- tests/unit/test_generation_preview.py | 28 +++++++-------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/tests/unit/test_generation_preview.py b/tests/unit/test_generation_preview.py index 33e174aab..11b584146 100755 --- a/tests/unit/test_generation_preview.py +++ b/tests/unit/test_generation_preview.py @@ -1173,9 +1173,7 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "pip" mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "9:16" @@ -1188,9 +1186,7 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "standard" mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "16:9" @@ -1203,9 +1199,7 @@ class TestInferVideoRatioFromTemplate: mock_template.mode = "unknown_mode" mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "" @@ -1216,9 +1210,7 @@ class TestInferVideoRatioFromTemplate: mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = None result = _infer_video_ratio_from_template("nonexistent", mock_db) assert result == "" @@ -1237,9 +1229,7 @@ class TestInferVideoRatioFromTemplate: mock_db = MagicMock() - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.side_effect = Exception("db connection error") result = _infer_video_ratio_from_template("tpl_001", mock_db) assert result == "" @@ -1274,13 +1264,9 @@ class TestPreviewRouteAutoInfersVideoRatio: bgm_config={}, ) - with patch( - "app.api.routes.generation_preview.SQLAlchemyTemplateRepository" - ) as MockRepo: + with patch("app.api.routes.generation_preview.SQLAlchemyTemplateRepository") as MockRepo: MockRepo.return_value.get_by_id.return_value = mock_template - with patch( - "app.api.routes.generation_preview.CreateGenerationTaskUseCase" - ) as MockUC: + with patch("app.api.routes.generation_preview.CreateGenerationTaskUseCase") as MockUC: MockUC.return_value.execute.return_value = task with patch( "app.api.routes.generation_preview.safe_enqueue_generation_task", -- 2.54.0 From f04943b3528ff1eeada2ad0871956c8da971b48c Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 4 Aug 2026 01:01:54 +0800 Subject: [PATCH 7/7] fix: remove unused variable 'e' from GlobalQueueFull except block --- apps/api/app/api/routes/generation_preview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/app/api/routes/generation_preview.py b/apps/api/app/api/routes/generation_preview.py index 1a7a3a2a0..0ea4d7edf 100755 --- a/apps/api/app/api/routes/generation_preview.py +++ b/apps/api/app/api/routes/generation_preview.py @@ -282,7 +282,7 @@ def create_preview_generation_task( status_code=429, detail=f"您的待处理任务过多(当前 {e.pending_count - 1}/{e.limit}),请等待后再提交", ) from None - except GlobalQueueFull as e: + except GlobalQueueFull: _mark_task_failed(generation_task_repository, task, "系统队列已满") raise HTTPException( status_code=503, -- 2.54.0