7a72cfd709
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m9s
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 / Validate - Type Check (mypy) (push) Successful in 2m19s
CI/CD Pipeline / Validate - Code Quality (push) Failing after 3m10s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m7s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m7s
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 1m17s
CI/CD Pipeline / Frontend Lint (push) Successful in 3m37s
CI/CD Pipeline / Integration Tests (push) Successful in 2m18s
CI/CD Pipeline / Unit Tests (push) Failing after 4m59s
CI/CD Pipeline / Build Staging API Image (push) Successful in 8m39s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m25s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 42s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 27m2s
CI/CD Pipeline / Staging API Integration Tests (push) Failing after 30m15s
309 lines
9.2 KiB
Python
Executable File
309 lines
9.2 KiB
Python
Executable File
"""片头片尾引擎单元测试 - 配置解析等纯逻辑."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from video_processing.intro_outro_engine import IntroOutroConfig
|
|
|
|
|
|
class TestIntroOutroConfigDefaults:
|
|
"""默认配置测试."""
|
|
|
|
def test_default_values(self):
|
|
"""默认值正确."""
|
|
config = IntroOutroConfig()
|
|
assert config.enabled is False
|
|
assert config.intro_type == "none"
|
|
assert config.outro_type == "none"
|
|
assert config.intro_duration == 3.0
|
|
assert config.outro_duration == 3.0
|
|
assert config.transition_effect == "fade"
|
|
assert config.transition_duration == 0.5
|
|
|
|
|
|
class TestIntroOutroConfigFromDict:
|
|
"""from_dict 配置解析测试."""
|
|
|
|
def test_none_returns_default(self):
|
|
"""None 返回默认配置."""
|
|
config = IntroOutroConfig.from_dict(None)
|
|
assert config.enabled is False
|
|
|
|
def test_empty_dict_returns_default(self):
|
|
"""空 dict 返回默认."""
|
|
config = IntroOutroConfig.from_dict({})
|
|
assert config.enabled is False
|
|
|
|
def test_disabled_returns_default(self):
|
|
"""enabled=False 返回默认."""
|
|
config = IntroOutroConfig.from_dict({"enabled": False})
|
|
assert config.enabled is False
|
|
|
|
def test_enabled_defaults(self):
|
|
"""启用时默认值正确."""
|
|
config = IntroOutroConfig.from_dict({"enabled": True})
|
|
assert config.enabled is True
|
|
assert config.intro_type == "none"
|
|
assert config.outro_type == "none"
|
|
|
|
def test_text_intro(self):
|
|
"""文字片头配置."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"intro": {
|
|
"type": "text",
|
|
"title": "我的片头",
|
|
"subtitle": "欢迎收看",
|
|
},
|
|
})
|
|
assert config.intro_type == "text"
|
|
assert config.intro_title == "我的片头"
|
|
assert config.intro_subtitle == "欢迎收看"
|
|
|
|
def test_video_intro(self):
|
|
"""视频片头配置."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"intro": {
|
|
"type": "video",
|
|
"video_path": "/videos/intro.mp4",
|
|
"duration": 5.0,
|
|
},
|
|
})
|
|
assert config.intro_type == "video"
|
|
assert config.intro_video_path == "/videos/intro.mp4"
|
|
assert config.intro_duration == 5.0
|
|
|
|
def test_video_intro_video_alias(self):
|
|
"""video 字段作为 video_path 别名."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"intro": {
|
|
"type": "video",
|
|
"video": "/videos/intro.mp4",
|
|
},
|
|
})
|
|
assert config.intro_video_path == "/videos/intro.mp4"
|
|
|
|
def test_text_outro(self):
|
|
"""文字片尾配置."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"outro": {
|
|
"type": "text",
|
|
"title": "感谢观看",
|
|
"subtitle": "点赞关注",
|
|
},
|
|
})
|
|
assert config.outro_type == "text"
|
|
assert config.outro_title == "感谢观看"
|
|
assert config.outro_subtitle == "点赞关注"
|
|
|
|
def test_outro_default_title(self):
|
|
"""片尾默认标题."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"outro": {"type": "text"},
|
|
})
|
|
assert config.outro_title == "感谢观看"
|
|
assert config.outro_subtitle == "点赞关注不迷路"
|
|
|
|
def test_text_intro_styling(self):
|
|
"""文字片头样式配置."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"intro": {
|
|
"type": "text",
|
|
"title": "测试",
|
|
"background": "#FF0000",
|
|
"title_color": "yellow",
|
|
"title_size": 64,
|
|
"subtitle_color": "white",
|
|
"subtitle_size": 32,
|
|
},
|
|
})
|
|
assert config.intro_background == "#FF0000"
|
|
assert config.intro_title_color == "yellow"
|
|
assert config.intro_title_size == 64
|
|
assert config.intro_subtitle_color == "white"
|
|
assert config.intro_subtitle_size == 32
|
|
|
|
def test_transition_config(self):
|
|
"""转场配置."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"transition": "dissolve",
|
|
"transition_duration": 1.0,
|
|
})
|
|
assert config.transition_effect == "dissolve"
|
|
assert config.transition_duration == 1.0
|
|
|
|
def test_empty_intro_dict(self):
|
|
"""空 intro dict."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"intro": {},
|
|
})
|
|
assert config.intro_type == "none"
|
|
|
|
def test_none_intro(self):
|
|
"""None intro 值."""
|
|
config = IntroOutroConfig.from_dict({
|
|
"enabled": True,
|
|
"intro": None,
|
|
})
|
|
assert config.intro_type == "none"
|
|
|
|
|
|
class TestHasIntroOutro:
|
|
"""has_intro / has_outro 属性测试."""
|
|
|
|
def test_no_intro_when_disabled(self):
|
|
"""禁用时无片头."""
|
|
config = IntroOutroConfig()
|
|
assert config.has_intro is False
|
|
assert config.has_outro is False
|
|
|
|
def test_video_intro_has_intro(self):
|
|
"""视频片头有has_intro."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
intro_type="video",
|
|
intro_video_path="/a.mp4",
|
|
)
|
|
assert config.has_intro is True
|
|
|
|
def test_text_intro_has_intro(self):
|
|
"""文字片头有has_intro."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
intro_type="text",
|
|
intro_title="test",
|
|
)
|
|
assert config.has_intro is True
|
|
|
|
def test_none_intro_no_intro(self):
|
|
"""none类型无片头."""
|
|
config = IntroOutroConfig(enabled=True, intro_type="none")
|
|
assert config.has_intro is False
|
|
|
|
def test_video_outro_has_outro(self):
|
|
"""视频片尾有has_outro."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
outro_type="video",
|
|
outro_video_path="/a.mp4",
|
|
)
|
|
assert config.has_outro is True
|
|
|
|
def test_text_outro_has_outro(self):
|
|
"""文字片尾有has_outro."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
outro_type="text",
|
|
outro_title="test",
|
|
)
|
|
assert config.has_outro is True
|
|
|
|
def test_follow_outro_has_outro(self):
|
|
"""follow类型片尾有has_outro."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
outro_type="follow",
|
|
outro_title="test",
|
|
)
|
|
assert config.has_outro is True
|
|
|
|
|
|
class TestValidate:
|
|
"""validate 配置校验测试."""
|
|
|
|
def test_disabled_valid(self):
|
|
"""禁用配置合法."""
|
|
config = IntroOutroConfig()
|
|
ok, msg = config.validate()
|
|
assert ok is True
|
|
assert msg == ""
|
|
|
|
def test_video_intro_missing_path(self):
|
|
"""视频片头缺少路径."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
intro_type="video",
|
|
intro_video_path="",
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is False
|
|
assert "video_path" in msg
|
|
|
|
def test_text_intro_missing_title(self):
|
|
"""文字片头缺少标题."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
intro_type="text",
|
|
intro_title="",
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is False
|
|
assert "title" in msg
|
|
|
|
def test_video_outro_missing_path(self):
|
|
"""视频片尾缺少路径."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
outro_type="video",
|
|
outro_video_path="",
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is False
|
|
assert "video_path" in msg
|
|
|
|
def test_text_outro_missing_title(self):
|
|
"""文字片尾缺少标题."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
outro_type="text",
|
|
outro_title="",
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is False
|
|
assert "title" in msg
|
|
|
|
def test_zero_intro_duration_invalid(self):
|
|
"""片头时长为0无效."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
intro_type="text",
|
|
intro_title="test",
|
|
intro_duration=0,
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is False
|
|
assert "时长" in msg
|
|
|
|
def test_negative_outro_duration_invalid(self):
|
|
"""片尾时长为负无效."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
outro_type="text",
|
|
outro_title="test",
|
|
outro_duration=-1.0,
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is False
|
|
assert "时长" in msg
|
|
|
|
def test_valid_text_both(self):
|
|
"""文字片头片尾都合法."""
|
|
config = IntroOutroConfig(
|
|
enabled=True,
|
|
intro_type="text",
|
|
intro_title="片头",
|
|
intro_duration=3.0,
|
|
outro_type="text",
|
|
outro_title="片尾",
|
|
outro_duration=3.0,
|
|
)
|
|
ok, msg = config.validate()
|
|
assert ok is True
|