from dataclasses import FrozenInstanceError """transition_presets 领域层单元测试 - 转场预设库""" import pytest from packages.domain.transition_presets import ( TRANSITION_PRESET_LIBRARY, TransitionPreset, get_default_transition, get_transition_preset, list_transition_presets, ) class TestTransitionPreset: """TransitionPreset 数据类测试""" def test_create_minimal(self): preset = TransitionPreset(id="test", name="测试", category="basic", transition="fade") assert preset.id == "test" assert preset.name == "测试" assert preset.category == "basic" assert preset.transition == "fade" assert preset.description == "" assert preset.tags == [] assert preset.default_duration == 0.5 assert preset.min_duration == 0.1 assert preset.max_duration == 3.0 assert preset.has_custom_params is False def test_create_with_all_params(self): preset = TransitionPreset( id="custom", name="自定义转场", category="special", description="炫酷特效", tags=["炫酷", "特效"], transition="custom", default_duration=1.0, min_duration=0.5, max_duration=5.0, has_custom_params=True, ) assert preset.description == "炫酷特效" assert preset.tags == ["炫酷", "特效"] assert preset.default_duration == 1.0 assert preset.min_duration == 0.5 assert preset.max_duration == 5.0 assert preset.has_custom_params is True def test_frozen_immutable(self): """frozen dataclass 不可修改""" preset = TransitionPreset(id="test", name="测试", category="basic") with pytest.raises(FrozenInstanceError): preset.name = "改名" def test_tags_default_empty_list(self): preset = TransitionPreset(id="t1", name="t1", category="basic") preset2 = TransitionPreset(id="t2", name="t2", category="basic") assert preset.tags == [] assert preset.tags is not preset2.tags def test_default_transition_is_fade(self): preset = TransitionPreset(id="test", name="测试", category="basic") assert preset.transition == "fade" class TestTransitionPresetLibrary: """TRANSITION_PRESET_LIBRARY 预设库测试""" def test_library_not_empty(self): assert len(TRANSITION_PRESET_LIBRARY) > 0 def test_all_presets_have_unique_ids(self): """所有预设 ID 唯一""" ids = [p.id for p in TRANSITION_PRESET_LIBRARY] assert len(ids) == len(set(ids)) def test_all_presets_have_required_fields(self): """所有预设都有必填字段""" for preset in TRANSITION_PRESET_LIBRARY: assert preset.id, "missing id" assert preset.name, f"{preset.id} missing name" assert preset.category, f"{preset.id} missing category" assert preset.transition, f"{preset.id} missing transition" def test_transition_none_exists(self): """无转场预设存在""" none_preset = next((p for p in TRANSITION_PRESET_LIBRARY if p.id == "transition_none"), None) assert none_preset is not None assert none_preset.name == "无转场" assert none_preset.transition == "none" def test_transition_random_exists(self): """随机转场预设存在""" random_preset = next((p for p in TRANSITION_PRESET_LIBRARY if p.id == "transition_random"), None) assert random_preset is not None assert random_preset.name == "随机" def test_fade_category_exists(self): """淡入淡出分类有预设""" fade_presets = [p for p in TRANSITION_PRESET_LIBRARY if p.category == "fade"] assert len(fade_presets) >= 2 def test_duration_constraints_valid(self): """时长约束:min <= default <= max""" for preset in TRANSITION_PRESET_LIBRARY: assert preset.min_duration <= preset.default_duration, f"{preset.id}: min > default" assert preset.default_duration <= preset.max_duration, f"{preset.id}: default > max" assert preset.min_duration >= 0, f"{preset.id}: min < 0" def test_known_categories_exist(self): """已知分类都有预设""" categories = {p.category for p in TRANSITION_PRESET_LIBRARY} assert "basic" in categories assert "fade" in categories class TestGetTransitionPreset: """get_transition_preset 函数测试""" def test_get_existing_preset(self): preset = get_transition_preset("transition_none") assert preset is not None assert preset.id == "transition_none" def test_get_fade_preset(self): preset = get_transition_preset("transition_fade") assert preset is not None assert preset.transition == "fade" def test_get_nonexistent_preset(self): assert get_transition_preset("nonexistent_transition") is None def test_returns_transitionpreset_type(self): preset = get_transition_preset("transition_fade") assert isinstance(preset, TransitionPreset) class TestListTransitionPresets: """list_transition_presets 函数测试""" def test_list_all(self): """不带参数返回所有预设""" all_presets = list_transition_presets() assert len(all_presets) == len(TRANSITION_PRESET_LIBRARY) def test_filter_by_category(self): """按分类筛选""" fade_presets = list_transition_presets(category="fade") assert len(fade_presets) > 0 assert all(p.category == "fade" for p in fade_presets) def test_filter_by_basic_category(self): basic_presets = list_transition_presets(category="basic") assert len(basic_presets) >= 2 def test_filter_by_nonexistent_category(self): result = list_transition_presets(category="nonexistent") assert result == [] def test_search_by_name(self): """按名称搜索""" result = list_transition_presets(keyword="淡入") assert len(result) >= 1 assert any("淡入" in p.name for p in result) def test_search_by_tag(self): """按标签搜索""" tagged = [p for p in TRANSITION_PRESET_LIBRARY if p.tags] if tagged: tag = tagged[0].tags[0] result = list_transition_presets(keyword=tag) assert len(result) >= 1 def test_search_empty_returns_all(self): result = list_transition_presets(keyword="") assert len(result) == len(TRANSITION_PRESET_LIBRARY) def test_combined_category_and_search(self): result = list_transition_presets(category="fade", keyword="淡入") assert all(p.category == "fade" for p in result) def test_returns_list_of_transitionpreset(self): result = list_transition_presets() assert all(isinstance(p, TransitionPreset) for p in result) class TestGetDefaultTransition: """get_default_transition 函数测试""" def test_returns_preset(self): preset = get_default_transition() assert preset is not None assert isinstance(preset, TransitionPreset) def test_default_is_none(self): """默认转场是无转场(硬切)""" preset = get_default_transition() assert preset.id == "transition_none" assert preset.transition == "none" def test_default_has_zero_duration(self): """无转场默认时长为 0""" preset = get_default_transition() assert preset.default_duration == 0.0 assert preset.min_duration == 0.0 assert preset.max_duration == 0.0