"""generated_video 领域模型单元测试.""" import pytest from domain.generated_video import GeneratedVideo class TestGeneratedVideoCreate: """GeneratedVideo.create 工厂方法测试.""" def test_create_with_required_fields(self): video = GeneratedVideo.create( project_id="proj_001", generation_task_id="task_001", name="测试视频", file_url="https://example.com/out.mp4", ) assert video.id assert len(video.id) == 32 assert video.project_id == "proj_001" assert video.generation_task_id == "task_001" assert video.name == "测试视频" assert video.file_url == "https://example.com/out.mp4" # 默认值 assert video.user_id == "" assert video.file_size == 0 assert video.duration == 0.0 assert video.width == 0 assert video.height == 0 assert video.fps == 0.0 assert video.thumbnail_url is None assert video.status == "completed" assert video.review_status == "pending_review" assert video.generation_params == {} assert video.video_fingerprint is None assert video.is_duplicate is False assert video.duplicate_of is None assert video.generated_at is not None assert video.created_at is not None def test_create_with_all_fields(self): video = GeneratedVideo.create( project_id="proj_002", generation_task_id="task_002", name="完整视频", file_url="https://example.com/full.mp4", user_id="user_001", file_size=1024000, duration=30.5, width=1920, height=1080, fps=30.0, thumbnail_url="https://example.com/thumb.jpg", generation_params={"quality": "high"}, ) assert video.user_id == "user_001" assert video.file_size == 1024000 assert video.duration == 30.5 assert video.width == 1920 assert video.height == 1080 assert video.fps == 30.0 assert video.thumbnail_url == "https://example.com/thumb.jpg" assert video.generation_params == {"quality": "high"} def test_create_strips_strings(self): video = GeneratedVideo.create( project_id=" proj_003 ", generation_task_id=" task_003 ", name=" 测试视频 ", file_url=" https://example.com/out.mp4 ", user_id=" user_003 ", ) assert video.project_id == "proj_003" assert video.generation_task_id == "task_003" assert video.name == "测试视频" assert video.file_url == "https://example.com/out.mp4" assert video.user_id == "user_003" def test_create_empty_project_id_raises(self): with pytest.raises(ValueError, match="project_id"): GeneratedVideo.create( project_id="", generation_task_id="t", name="n", file_url="u", ) def test_create_whitespace_project_id_raises(self): with pytest.raises(ValueError, match="project_id"): GeneratedVideo.create( project_id=" ", generation_task_id="t", name="n", file_url="u", ) def test_create_empty_generation_task_id_raises(self): with pytest.raises(ValueError, match="generation_task_id"): GeneratedVideo.create( project_id="p", generation_task_id="", name="n", file_url="u", ) def test_create_empty_name_raises(self): with pytest.raises(ValueError, match="name"): GeneratedVideo.create( project_id="p", generation_task_id="t", name="", file_url="u", ) def test_create_empty_file_url_raises(self): with pytest.raises(ValueError, match="file_url"): GeneratedVideo.create( project_id="p", generation_task_id="t", name="n", file_url="", ) def test_create_none_generation_params_defaults_to_empty_dict(self): video = GeneratedVideo.create( project_id="p", generation_task_id="t", name="n", file_url="u", generation_params=None, ) assert video.generation_params == {} def test_create_ids_are_unique(self): v1 = GeneratedVideo.create(project_id="p", generation_task_id="t1", name="n1", file_url="u1") v2 = GeneratedVideo.create(project_id="p", generation_task_id="t2", name="n2", file_url="u2") assert v1.id != v2.id def test_create_timestamps_are_utc(self): video = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u") assert video.created_at.tzinfo is not None assert video.generated_at.tzinfo is not None class TestGeneratedVideoProperties: """GeneratedVideo 属性测试""" def test_default_status_completed(self): gv = GeneratedVideo.create( project_id="proj-1", generation_task_id="task-1", name="测试视频", file_url="https://example.com/video.mp4", ) assert gv.status == "completed" def test_default_review_status(self): gv = GeneratedVideo.create( project_id="proj-1", generation_task_id="task-1", name="测试视频", file_url="https://example.com/video.mp4", ) assert gv.review_status == "pending_review" def test_set_status(self): gv = GeneratedVideo.create( project_id="proj-1", generation_task_id="task-1", name="测试视频", file_url="https://example.com/video.mp4", ) gv.status = "failed" assert gv.status == "failed" def test_mark_as_duplicate(self): gv = GeneratedVideo.create( project_id="proj-1", generation_task_id="task-1", name="测试视频", file_url="https://example.com/video.mp4", ) gv.is_duplicate = True gv.duplicate_of = "video-original" assert gv.is_duplicate is True assert gv.duplicate_of == "video-original" def test_set_fingerprint(self): gv = GeneratedVideo.create( project_id="proj-1", generation_task_id="task-1", name="测试视频", file_url="https://example.com/video.mp4", ) fingerprint = {"phash": "abc123", "md5": "def456"} gv.video_fingerprint = fingerprint assert gv.video_fingerprint == fingerprint class TestGeneratedVideoExtended: """GeneratedVideo 深度补充测试""" def test_id_is_hex(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u") int(v.id, 16) def test_zero_file_size(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", file_size=0) assert v.file_size == 0 def test_large_file_size(self): large = 1024 * 1024 * 1024 # 1GB v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", file_size=large) assert v.file_size == large def test_zero_duration(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", duration=0.0) assert v.duration == 0.0 def test_large_duration(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", duration=9999.99) assert v.duration == 9999.99 def test_zero_dimensions(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", width=0, height=0) assert v.width == 0 assert v.height == 0 def test_4k_dimensions(self): v = GeneratedVideo.create( project_id="p", generation_task_id="t", name="n", file_url="u", width=3840, height=2160 ) assert v.width == 3840 assert v.height == 2160 def test_zero_fps(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", fps=0.0) assert v.fps == 0.0 def test_high_fps(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", fps=120.0) assert v.fps == 120.0 def test_empty_user_id(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", user_id="") assert v.user_id == "" def test_long_name(self): long_name = "视频" * 100 v = GeneratedVideo.create(project_id="p", generation_task_id="t", name=long_name, file_url="u") assert v.name == long_name assert len(v.name) == 200 def test_unicode_name(self): v = GeneratedVideo.create( project_id="p", generation_task_id="t", name="🎬 我的精彩视频 · 旅行vlog", file_url="u" ) assert "🎬" in v.name assert "旅行vlog" in v.name def test_special_characters_name(self): special = "视!@#$%^&*()频" v = GeneratedVideo.create(project_id="p", generation_task_id="t", name=special, file_url="u") assert v.name == special def test_thumbnail_url_none(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", thumbnail_url=None) assert v.thumbnail_url is None def test_generation_params_complex(self): params = { "mode": "voice_over", "quality": "high", "resolution": {"width": 1920, "height": 1080}, "effects": ["filter", "transition"], } v = GeneratedVideo.create( project_id="p", generation_task_id="t", name="n", file_url="u", generation_params=params ) assert v.generation_params["mode"] == "voice_over" assert v.generation_params["resolution"]["width"] == 1920 assert len(v.generation_params["effects"]) == 2 def test_generation_params_independence(self): v1 = GeneratedVideo.create(project_id="p", generation_task_id="t1", name="n1", file_url="u1") v2 = GeneratedVideo.create(project_id="p", generation_task_id="t2", name="n2", file_url="u2") v1.generation_params["key"] = "val" assert "key" not in v2.generation_params def test_status_failed(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u") v.status = "failed" assert v.status == "failed" def test_review_status_approved(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u") v.review_status = "approved" assert v.review_status == "approved" def test_is_duplicate_default_false(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u") assert v.is_duplicate is False assert v.duplicate_of is None def test_fingerprint_none_default(self): v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u") assert v.video_fingerprint is None def test_empty_file_url_raises(self): with pytest.raises(ValueError): GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url=" ")