""" Template 模板领域模型单元测试 """ from domain.template import Template, TemplateCategory, TemplateSegment class TestTemplateSegment: """TemplateSegment 测试""" def test_create_segment(self): seg = TemplateSegment( id="seg-1", template_id="tpl-1", segment_order=1, duration_min=3.0, duration_max=5.0, ) assert seg.id == "seg-1" assert seg.template_id == "tpl-1" assert seg.segment_order == 1 assert seg.duration_min == 3.0 assert seg.duration_max == 5.0 assert seg.material_type is None def test_segment_with_material_type(self): seg = TemplateSegment( id="seg-1", template_id="tpl-1", segment_order=0, duration_min=2.0, duration_max=4.0, material_type="人物", ) assert seg.material_type == "人物" def test_segment_has_timestamps(self): seg = TemplateSegment( id="seg-1", template_id="tpl-1", segment_order=1, duration_min=1.0, duration_max=2.0, ) assert seg.created_at is not None assert seg.updated_at is not None class TestTemplate: """Template 测试""" def test_create_template_minimal(self): t = Template( id="tpl-1", user_id="user-1", name="测试模板", mode="one_take", ) assert t.id == "tpl-1" assert t.user_id == "user-1" assert t.name == "测试模板" assert t.mode == "one_take" def test_default_values(self): t = Template(id="tpl-1", user_id="u1", name="n", mode="one_take") assert t.category == "" assert t.tags == [] assert t.title_config == {} assert t.subtitle_config == {} assert t.bgm_config == {} assert t.estimated_duration == 0.0 assert t.segments == [] assert t.is_active is True def test_with_segments(self): segs = [ TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=2, duration_max=4), TemplateSegment(id="s2", template_id="t1", segment_order=1, duration_min=3, duration_max=5), ] t = Template( id="tpl-1", user_id="u1", name="n", mode="voice_over", segments=segs, ) assert len(t.segments) == 2 assert t.segments[0].segment_order == 0 assert t.segments[1].segment_order == 1 def test_all_modes(self): for mode in ["pip", "voice_pip", "one_take", "voice_over"]: t = Template(id="t1", user_id="u1", name="n", mode=mode) assert t.mode == mode def test_with_configs(self): t = Template( id="t1", user_id="u1", name="n", mode="one_take", title_config={"font_size": 24, "color": "#ffffff"}, subtitle_config={"style": "bottom"}, bgm_config={"volume": 0.5}, ) assert t.title_config["font_size"] == 24 assert t.subtitle_config["style"] == "bottom" assert t.bgm_config["volume"] == 0.5 def test_estimated_duration(self): t = Template( id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=30.5, ) assert t.estimated_duration == 30.5 def test_is_active_false(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", is_active=False) assert t.is_active is False def test_has_timestamps(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take") assert t.created_at is not None assert t.updated_at is not None def test_tags_list(self): t = Template( id="t1", user_id="u1", name="n", mode="one_take", tags=["风景", "vlog"], ) assert "风景" in t.tags assert "vlog" in t.tags assert len(t.tags) == 2 class TestTemplateCategory: """TemplateCategory 测试""" def test_create_category(self): cat = TemplateCategory(id="cat-1", user_id="u1", name="风景") assert cat.id == "cat-1" assert cat.user_id == "u1" assert cat.name == "风景" def test_category_has_timestamp(self): cat = TemplateCategory(id="cat-1", user_id="u1", name="风景") assert cat.created_at is not None class TestTemplateExtended: """Template 深度补充测试""" def test_tags_independence(self): """不同模板的 tags 列表互不影响""" t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take") t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take") t1.tags.append("新标签") assert "新标签" not in t2.tags assert len(t2.tags) == 0 def test_title_config_independence(self): t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take") t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take") t1.title_config["key"] = "val" assert "key" not in t2.title_config def test_subtitle_config_independence(self): t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take") t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take") t1.subtitle_config["key"] = "val" assert "key" not in t2.subtitle_config def test_bgm_config_independence(self): t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take") t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take") t1.bgm_config["key"] = "val" assert "key" not in t2.bgm_config def test_segments_independence(self): segs = [ TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=2), ] t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take", segments=segs) t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take") assert len(t2.segments) == 0 def test_empty_segments(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", segments=[]) assert t.segments == [] def test_many_segments(self): segs = [ TemplateSegment(id=f"s{i}", template_id="t1", segment_order=i, duration_min=1, duration_max=3) for i in range(30) ] t = Template(id="t1", user_id="u1", name="n", mode="one_take", segments=segs) assert len(t.segments) == 30 assert t.segments[0].segment_order == 0 assert t.segments[29].segment_order == 29 def test_zero_estimated_duration(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=0.0) assert t.estimated_duration == 0.0 def test_negative_estimated_duration(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=-1.0) assert t.estimated_duration == -1.0 def test_large_estimated_duration(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=9999.9) assert t.estimated_duration == 9999.9 def test_empty_category(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", category="") assert t.category == "" def test_custom_category(self): t = Template(id="t1", user_id="u1", name="n", mode="one_take", category="美食探店") assert t.category == "美食探店" def test_empty_name(self): t = Template(id="t1", user_id="u1", name="", mode="one_take") assert t.name == "" def test_unicode_name(self): t = Template(id="t1", user_id="u1", name="🎬 美食探店 · Vlog模板", mode="one_take") assert "🎬" in t.name assert "美食探店" in t.name def test_special_characters_in_name(self): special = "模!@#$%板" t = Template(id="t1", user_id="u1", name=special, mode="one_take") assert t.name == special def test_long_name(self): long_name = "模板" * 100 t = Template(id="t1", user_id="u1", name=long_name, mode="one_take") assert t.name == long_name assert len(t.name) == 200 class TestTemplateSegmentExtended: """TemplateSegment 深度补充测试""" def test_zero_duration(self): seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=0, duration_max=0) assert seg.duration_min == 0 assert seg.duration_max == 0 def test_negative_duration_min(self): seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=-1, duration_max=5) assert seg.duration_min == -1 def test_negative_duration_max(self): seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=-5) assert seg.duration_max == -5 def test_large_duration(self): seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=0, duration_max=9999.9) assert seg.duration_max == 9999.9 def test_negative_order(self): seg = TemplateSegment(id="s1", template_id="t1", segment_order=-5, duration_min=1, duration_max=3) assert seg.segment_order == -5 def test_large_order(self): seg = TemplateSegment(id="s1", template_id="t1", segment_order=999, duration_min=1, duration_max=3) assert seg.segment_order == 999 def test_material_type_none(self): seg = TemplateSegment( id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=3, material_type=None ) assert seg.material_type is None def test_material_type_empty_string(self): seg = TemplateSegment( id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=3, material_type="" ) assert seg.material_type == "" def test_material_type_unicode(self): seg = TemplateSegment( id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=3, material_type="风景" ) assert seg.material_type == "风景"