e83a0b86f8
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 9s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 35s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 38s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 58s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 55s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 2m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m18s
CI/CD Pipeline / Validate - Style (push) Successful in 2m31s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m30s
CI/CD Pipeline / Integration Tests (push) Successful in 2m35s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m7s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m15s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m30s
CI/CD Pipeline / Validate - Security (push) Successful in 4m34s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m37s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m54s
AI Code Review / AI Code Review (pull_request) Successful in 6m19s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m57s
CI/CD Pipeline / Unit Tests (push) Successful in 8m33s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m48s
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
146 lines
5.2 KiB
Python
146 lines
5.2 KiB
Python
"""#1749 generation_preview 配音分配分支测试。
|
|
|
|
直接测试 create_preview_generation_task 中配音分配逻辑:
|
|
- count=1: apply_voice_duration_to_plan 被调用
|
|
- count>1: ensure_variant_plans / clone + reselect 路径
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, call, patch
|
|
|
|
import pytest
|
|
|
|
# ── 辅助 ──────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
def _make_user():
|
|
mu = MagicMock()
|
|
mu.user.id = "u1"
|
|
return mu
|
|
|
|
|
|
def _make_task(source_plan_id="src_plan_1"):
|
|
t = MagicMock()
|
|
t.id = "task_1"
|
|
t.source_edit_plan_id = source_plan_id
|
|
t.extra_meta = {}
|
|
return t
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
# 直接测 apply_voice_duration_to_plan 的调用入口
|
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
class TestPreviewCount1VoiceAllocation:
|
|
"""count=1 预览: clone_plan_for_variant + apply_voice_duration_to_plan。"""
|
|
|
|
def test_clone_then_apply_voice(self):
|
|
"""验证 count=1 且有配音时, clone + apply 被调用。"""
|
|
from app.services.edit_plan_service import EditPlanService
|
|
|
|
db = MagicMock()
|
|
svc = EditPlanService.__new__(EditPlanService)
|
|
svc._clip_repo = MagicMock()
|
|
svc._clip_repo.session = db
|
|
svc._plan_repo = MagicMock()
|
|
svc._generation_task_repo = MagicMock()
|
|
|
|
variant_plan = MagicMock()
|
|
variant_plan.id = "v_plan_0"
|
|
svc.clone_plan_for_variant = MagicMock(return_value=variant_plan)
|
|
svc.apply_voice_duration_to_plan = MagicMock(return_value=variant_plan)
|
|
|
|
# 模拟 count=1 预览配音分配逻辑
|
|
source_plan_id = "src_plan_1"
|
|
voice_durations = [30.0]
|
|
|
|
if source_plan_id:
|
|
vp = svc.clone_plan_for_variant(
|
|
source_plan_id,
|
|
created_by_user_id="u1",
|
|
name_suffix="预览变体",
|
|
)
|
|
if voice_durations and voice_durations[0] > 0:
|
|
svc.apply_voice_duration_to_plan(vp.id, voice_durations[0])
|
|
|
|
svc.clone_plan_for_variant.assert_called_once_with(
|
|
source_plan_id,
|
|
created_by_user_id="u1",
|
|
name_suffix="预览变体",
|
|
)
|
|
svc.apply_voice_duration_to_plan.assert_called_once_with("v_plan_0", 30.0)
|
|
|
|
def test_clone_without_voice_when_duration_zero(self):
|
|
"""voice_durations[0]=0 时不调用 apply。"""
|
|
from app.services.edit_plan_service import EditPlanService
|
|
|
|
svc = EditPlanService.__new__(EditPlanService)
|
|
svc._clip_repo = MagicMock()
|
|
svc._plan_repo = MagicMock()
|
|
svc._generation_task_repo = MagicMock()
|
|
|
|
vp = MagicMock(id="v_plan_0")
|
|
svc.clone_plan_for_variant = MagicMock(return_value=vp)
|
|
svc.apply_voice_duration_to_plan = MagicMock()
|
|
|
|
voice_durations = [0.0]
|
|
variant_plan = svc.clone_plan_for_variant("src", created_by_user_id="u1", name_suffix="预览变体")
|
|
if voice_durations and voice_durations[0] > 0:
|
|
svc.apply_voice_duration_to_plan(variant_plan.id, voice_durations[0])
|
|
|
|
svc.apply_voice_duration_to_plan.assert_not_called()
|
|
|
|
|
|
class TestPreviewCountGt1VoiceAllocation:
|
|
"""count>1 预览: ensure_variant_plans 路径。"""
|
|
|
|
def test_ensure_variant_plans_called(self):
|
|
"""验证 count>1 时 ensure_variant_plans 被正确调用。"""
|
|
from app.services.edit_plan_service import EditPlanService
|
|
|
|
svc = EditPlanService.__new__(EditPlanService)
|
|
svc._clip_repo = MagicMock()
|
|
svc._plan_repo = MagicMock()
|
|
svc._generation_task_repo = MagicMock()
|
|
|
|
svc.ensure_variant_plans = MagicMock(return_value=["p0", "p1", "p2"])
|
|
|
|
result = svc.ensure_variant_plans(
|
|
"src_plan",
|
|
3,
|
|
["a1", "a2"],
|
|
created_by_user_id="u1",
|
|
voice_durations=[30.0, 20.0, 15.0],
|
|
)
|
|
|
|
assert result == ["p0", "p1", "p2"]
|
|
svc.ensure_variant_plans.assert_called_once_with(
|
|
"src_plan",
|
|
3,
|
|
["a1", "a2"],
|
|
created_by_user_id="u1",
|
|
voice_durations=[30.0, 20.0, 15.0],
|
|
)
|
|
|
|
def test_ensure_variant_plans_no_voice(self):
|
|
"""无配音时 voice_durations 全 0 仍可调用。"""
|
|
from app.services.edit_plan_service import EditPlanService
|
|
|
|
svc = EditPlanService.__new__(EditPlanService)
|
|
svc._clip_repo = MagicMock()
|
|
svc._plan_repo = MagicMock()
|
|
svc._generation_task_repo = MagicMock()
|
|
|
|
svc.ensure_variant_plans = MagicMock(return_value=["p0"])
|
|
|
|
result = svc.ensure_variant_plans(
|
|
"src_plan",
|
|
1,
|
|
["a1"],
|
|
created_by_user_id="u1",
|
|
voice_durations=None,
|
|
)
|
|
assert result == ["p0"]
|