""" EditTemplate 剪辑模板领域模型单元测试 """ import pytest from packages.domain.edit_template import EditTemplate, EditTemplateStatus from packages.domain.editing_mode import EditingMode class TestEditTemplateStatus: """EditTemplateStatus 枚举测试""" def test_status_values(self): assert EditTemplateStatus.ACTIVE == "active" assert EditTemplateStatus.INACTIVE == "inactive" class TestEditTemplateCreate: """create 工厂方法测试""" def test_create_minimal(self): template = EditTemplate.create(name="测试模板") assert template.id is not None assert len(template.id) == 32 assert template.name == "测试模板" assert template.description == "" assert template.template_type == "default" assert template.editing_mode == EditingMode.ONE_TAKE.value assert template.config == {} assert template.preview_url == "" assert template.sort_weight == 0 assert template.status == EditTemplateStatus.ACTIVE assert template.version == 1 assert template.created_at is not None assert template.updated_at is not None def test_create_with_all_fields(self): template = EditTemplate.create( name="口播模板", description="适合口播类视频", template_type="talking_head", editing_mode=EditingMode.VOICE_OVER.value, config={"aspect_ratio": "9:16", "duration": 60}, preview_url="https://example.com/preview.mp4", sort_weight=100, status=EditTemplateStatus.INACTIVE, version=3, ) assert template.name == "口播模板" assert template.description == "适合口播类视频" assert template.template_type == "talking_head" assert template.editing_mode == EditingMode.VOICE_OVER.value assert template.config == {"aspect_ratio": "9:16", "duration": 60} assert template.preview_url == "https://example.com/preview.mp4" assert template.sort_weight == 100 assert template.status == EditTemplateStatus.INACTIVE assert template.version == 3 def test_create_strips_whitespace(self): template = EditTemplate.create( name=" 我的模板 ", description=" 描述 ", template_type=" ", editing_mode=" ", preview_url=" url ", ) assert template.name == "我的模板" assert template.description == "描述" assert template.template_type == "default" # 空字符串回退到default assert template.editing_mode == EditingMode.ONE_TAKE.value # 空回退 assert template.preview_url == "url" def test_create_empty_name_raises(self): with pytest.raises(ValueError, match="模板名称不能为空"): EditTemplate.create(name=" ") def test_create_invalid_editing_mode_raises(self): with pytest.raises(ValueError, match="无效的 editing_mode"): EditTemplate.create(name="测试", editing_mode="invalid_mode") def test_create_config_none(self): template = EditTemplate.create(name="test", config=None) assert template.config == {} # 两个模板不共享同一个 dict t2 = EditTemplate.create(name="test2") assert template.config is not t2.config def test_create_all_editing_modes(self): """所有合法 editing_mode 都能创建""" for mode in EditingMode: template = EditTemplate.create(name=f"test_{mode.value}", editing_mode=mode.value) assert template.editing_mode == mode.value class TestEditTemplateActivateDeactivate: """激活/停用测试""" def test_activate_from_inactive(self): template = EditTemplate.create(name="test", status=EditTemplateStatus.INACTIVE) old_updated = template.updated_at template.activate() assert template.status == EditTemplateStatus.ACTIVE assert template.updated_at >= old_updated def test_activate_from_active(self): template = EditTemplate.create(name="test") template.activate() assert template.status == EditTemplateStatus.ACTIVE def test_deactivate_from_active(self): template = EditTemplate.create(name="test") template.deactivate() assert template.status == EditTemplateStatus.INACTIVE def test_deactivate_from_inactive(self): template = EditTemplate.create(name="test", status=EditTemplateStatus.INACTIVE) template.deactivate() assert template.status == EditTemplateStatus.INACTIVE class TestEditTemplateIsActive: """is_active 属性测试""" def test_is_active_true(self): template = EditTemplate.create(name="test") assert template.is_active is True def test_is_active_false(self): template = EditTemplate.create(name="test", status=EditTemplateStatus.INACTIVE) assert template.is_active is False class TestEditTemplateBumpVersion: """版本号递增测试""" def test_bump_version_increments(self): template = EditTemplate.create(name="test", version=1) old_updated = template.updated_at template.bump_version() assert template.version == 2 assert template.updated_at >= old_updated def test_bump_version_multiple(self): template = EditTemplate.create(name="test", version=5) template.bump_version() template.bump_version() assert template.version == 7 def test_bump_version_updates_timestamp(self): template = EditTemplate.create(name="test") old_updated = template.updated_at template.bump_version() assert template.updated_at > old_updated or template.updated_at == old_updated class TestEditTemplateExtended: """EditTemplate 深度补充测试""" def test_id_is_hex(self): t = EditTemplate.create(name="test") int(t.id, 16) def test_ids_are_unique(self): t1 = EditTemplate.create(name="test1") t2 = EditTemplate.create(name="test2") assert t1.id != t2.id def test_empty_description(self): t = EditTemplate.create(name="test", description="") assert t.description == "" def test_long_description(self): desc = "描述" * 200 t = EditTemplate.create(name="test", description=desc) assert t.description == desc assert len(t.description) == 400 def test_unicode_name(self): t = EditTemplate.create(name="🎬 口播 Vlog 模板") assert "🎬" in t.name assert "口播" in t.name def test_special_characters_name(self): special = "模!@#$%板" t = EditTemplate.create(name=special) assert t.name == special def test_long_name(self): long_name = "模板名称" * 50 t = EditTemplate.create(name=long_name) assert t.name == long_name assert len(t.name) == 200 def test_config_independence(self): t1 = EditTemplate.create(name="test1") t2 = EditTemplate.create(name="test2") t1.config["key"] = "val" assert "key" not in t2.config def test_sort_weight_negative(self): t = EditTemplate.create(name="test", sort_weight=-100) assert t.sort_weight == -100 def test_sort_weight_large(self): t = EditTemplate.create(name="test", sort_weight=99999) assert t.sort_weight == 99999 def test_sort_weight_zero(self): t = EditTemplate.create(name="test", sort_weight=0) assert t.sort_weight == 0 def test_preview_url_empty(self): t = EditTemplate.create(name="test", preview_url="") assert t.preview_url == "" def test_version_zero(self): t = EditTemplate.create(name="test", version=0) assert t.version == 0 def test_version_large(self): t = EditTemplate.create(name="test", version=999) assert t.version == 999 def test_status_is_active_property(self): t = EditTemplate.create(name="test", status=EditTemplateStatus.ACTIVE) assert t.is_active is True t.deactivate() assert t.is_active is False t.activate() assert t.is_active is True def test_bump_version_from_zero(self): t = EditTemplate.create(name="test", version=0) t.bump_version() assert t.version == 1 def test_template_type_custom(self): t = EditTemplate.create(name="test", template_type="custom_type") assert t.template_type == "custom_type" def test_template_type_strips_and_default(self): """空格的 template_type 回退到 default""" t = EditTemplate.create(name="test", template_type=" ") assert t.template_type == "default" def test_create_with_empty_editing_mode_defaults(self): """空字符串 editing_mode 回退到 one_take""" t = EditTemplate.create(name="test", editing_mode="") assert t.editing_mode == "one_take" def test_preview_url_strips_whitespace(self): t = EditTemplate.create(name="test", preview_url=" https://example.com/v.mp4 ") assert t.preview_url == "https://example.com/v.mp4"