"""转场引擎单元测试 - 配置解析等纯逻辑.""" from __future__ import annotations import pytest from video_processing.transition_engine import ( CUT_TRANSITION, DEFAULT_TRANSITION_DURATION, MAX_TRANSITION_DURATION, MIN_TRANSITION_DURATION, TransitionConfig, TransitionType, ) class TestTransitionConstants: """常量测试.""" def test_duration_ranges(self): """时长范围合理.""" assert MIN_TRANSITION_DURATION == 0.3 assert MAX_TRANSITION_DURATION == 2.0 assert DEFAULT_TRANSITION_DURATION == 0.5 assert MIN_TRANSITION_DURATION < DEFAULT_TRANSITION_DURATION < MAX_TRANSITION_DURATION def test_cut_transition_value(self): """cut转场值.""" assert CUT_TRANSITION == "cut" class TestTransitionType: """TransitionType 枚举测试.""" def test_supports_fade(self): """支持fade.""" assert TransitionType.is_supported("fade") is True def test_supports_cut(self): """cut也在TransitionType枚举中.""" assert "cut" in [t.value for t in TransitionType] def test_unsupported_effect(self): """不支持的效果.""" assert TransitionType.is_supported("nonexistent_effect_xyz") is False def test_is_supported_case_insensitive(self): """是否大小写不敏感(看实现).""" # 直接测试几个已知的 assert TransitionType.is_supported("fade") is True assert TransitionType.is_supported("dissolve") is True def test_all_types_have_value(self): """所有枚举都有有效值.""" for t in TransitionType: assert isinstance(t.value, str) assert len(t.value) > 0 class TestTransitionConfigParse: """TransitionConfig.parse 解析测试.""" def test_no_args_default(self): """无参数默认配置.""" config = TransitionConfig.parse() assert config.effect == CUT_TRANSITION assert config.duration == DEFAULT_TRANSITION_DURATION def test_none_effect_default(self): """None effect默认为cut.""" config = TransitionConfig.parse(effect=None) assert config.effect == CUT_TRANSITION def test_empty_effect_default(self): """空字符串effect默认为cut.""" config = TransitionConfig.parse(effect="") assert config.effect == CUT_TRANSITION def test_whitespace_effect_default(self): """空白effect默认为cut.""" config = TransitionConfig.parse(effect=" ") assert config.effect == CUT_TRANSITION def test_fade_effect(self): """fade效果.""" config = TransitionConfig.parse(effect="fade") assert config.effect == "fade" def test_unsupported_effect_falls_back_to_cut(self): """不支持的效果降级到cut.""" config = TransitionConfig.parse(effect="super_cool_effect") assert config.effect == CUT_TRANSITION def test_cut_effect(self): """显式cut效果.""" config = TransitionConfig.parse(effect="cut") assert config.effect == CUT_TRANSITION def test_custom_duration(self): """自定义时长.""" config = TransitionConfig.parse(duration=1.0) assert config.duration == 1.0 def test_duration_below_min_clamped(self): """时长低于最小值钳制.""" config = TransitionConfig.parse(duration=0.1) assert config.duration == MIN_TRANSITION_DURATION def test_duration_above_max_clamped(self): """时长高于最大值钳制.""" config = TransitionConfig.parse(duration=5.0) assert config.duration == MAX_TRANSITION_DURATION def test_duration_at_min(self): """时长边界最小值.""" config = TransitionConfig.parse(duration=MIN_TRANSITION_DURATION) assert config.duration == MIN_TRANSITION_DURATION def test_duration_at_max(self): """时长边界最大值.""" config = TransitionConfig.parse(duration=MAX_TRANSITION_DURATION) assert config.duration == MAX_TRANSITION_DURATION def test_invalid_duration_falls_back(self): """无效时长回退到默认.""" config = TransitionConfig.parse(duration="not_a_number") assert config.duration == DEFAULT_TRANSITION_DURATION def test_none_duration_default(self): """None时长用默认值.""" config = TransitionConfig.parse(duration=None) assert config.duration == DEFAULT_TRANSITION_DURATION def test_effect_and_duration(self): """同时指定效果和时长.""" config = TransitionConfig.parse(effect="fade", duration=1.0) assert config.effect == "fade" assert config.duration == 1.0 class TestIsCut: """is_cut 属性测试.""" def test_cut_is_cut(self): """cut是硬切.""" config = TransitionConfig(effect=CUT_TRANSITION, duration=0.5) assert config.is_cut is True def test_fade_not_cut(self): """fade不是硬切.""" config = TransitionConfig(effect="fade", duration=0.5) assert config.is_cut is False class TestFfmpegTransition: """ffmpeg_transition 属性测试.""" def test_cut_returns_empty(self): """cut返回空字符串.""" config = TransitionConfig(effect=CUT_TRANSITION, duration=0.5) assert config.ffmpeg_transition == "" def test_fade_returns_fade(self): """fade返回fade.""" config = TransitionConfig(effect="fade", duration=0.5) result = config.ffmpeg_transition assert isinstance(result, str) assert len(result) > 0 def test_valid_effect_has_ffmpeg_name(self): """所有非cut的支持效果都有对应的ffmpeg名称.""" for t in TransitionType: if t.value == CUT_TRANSITION: continue # cut返回空是正常的 config = TransitionConfig(effect=t.value, duration=0.5) assert config.ffmpeg_transition != ""