220 lines
7.6 KiB
Python
220 lines
7.6 KiB
Python
"""
|
|
Unit tests for Video model
|
|
"""
|
|
|
|
from youtube_tui.models.video import Video
|
|
|
|
|
|
class TestVideoModel:
|
|
"""Tests for the Video dataclass"""
|
|
|
|
def test_video_creation(self, sample_video_data):
|
|
"""Test creating a Video object from data"""
|
|
video = Video(**sample_video_data)
|
|
|
|
assert video.video_id == "dQw4w9WgXcQ"
|
|
assert video.title == "Rick Astley - Never Gonna Give You Up"
|
|
assert video.channel == "RickAstleyVEVO"
|
|
assert video.duration == "3:33"
|
|
assert video.view_count == "1000000"
|
|
assert video.upload_date == "20091025"
|
|
assert video.is_short is False
|
|
|
|
def test_video_url_generation(self, sample_video_data):
|
|
"""Test URL is generated from video_id"""
|
|
video = Video(**sample_video_data)
|
|
|
|
assert video.url == "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
|
|
def test_video_short_detection(self, sample_video_data):
|
|
"""Test short video detection"""
|
|
# Test normal video
|
|
video = Video(**sample_video_data)
|
|
assert video.is_short is False
|
|
|
|
# Test short video via URL
|
|
short_data = sample_video_data.copy()
|
|
short_data["url"] = "https://www.youtube.com/shorts/dQw4w9WgXcQ"
|
|
short_data["is_short"] = False # Reset to test detection
|
|
video = Video(**short_data)
|
|
assert video.is_short is True
|
|
|
|
def test_video_short_detection_duration(self, sample_video_data):
|
|
"""Test short video detection via duration"""
|
|
short_data = sample_video_data.copy()
|
|
short_data["duration"] = "0:00" # Shorts have 0:00 duration
|
|
video = Video(**short_data)
|
|
assert video.is_short is True
|
|
|
|
def test_display_title_with_short(self, sample_video_data):
|
|
"""Test display title for short videos"""
|
|
short_data = sample_video_data.copy()
|
|
short_data["is_short"] = True
|
|
video = Video(**short_data)
|
|
|
|
assert (
|
|
video.display_title
|
|
== "(short) Rick Astley - Never Gonna Give You Up"
|
|
)
|
|
|
|
def test_display_title_without_short(self, sample_video_data):
|
|
"""Test display title for normal videos"""
|
|
video = Video(**sample_video_data)
|
|
|
|
assert video.display_title == "Rick Astley - Never Gonna Give You Up"
|
|
|
|
def test_display_duration_short(self, sample_video_data):
|
|
"""Test display duration for short videos"""
|
|
short_data = sample_video_data.copy()
|
|
short_data["is_short"] = True
|
|
video = Video(**short_data)
|
|
|
|
assert video.display_duration == "Short"
|
|
|
|
def test_display_duration_normal(self, sample_video_data):
|
|
"""Test display duration for normal videos"""
|
|
video = Video(**sample_video_data)
|
|
|
|
assert video.display_duration == "3:33"
|
|
|
|
def test_to_dict(self, sample_video_data):
|
|
"""Test Video to_dict conversion"""
|
|
video = Video(**sample_video_data)
|
|
result = video.to_dict()
|
|
|
|
assert result["video_id"] == "dQw4w9WgXcQ"
|
|
assert result["title"] == "Rick Astley - Never Gonna Give You Up"
|
|
assert result["is_short"] is False
|
|
assert result["url"] == "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
|
|
def test_to_dict_default_thumbnail(self, sample_video_data):
|
|
"""Test to_dict with None thumbnail"""
|
|
video = Video(**sample_video_data)
|
|
video.thumbnail_url = None
|
|
result = video.to_dict()
|
|
|
|
assert result["thumbnail_url"] is None
|
|
|
|
def test_from_dict(self, sample_video_data):
|
|
"""Test Video from_dict creation"""
|
|
video_dict = {
|
|
"video_id": "abc123",
|
|
"title": "Test Video",
|
|
"channel": "Test Channel",
|
|
"channel_id": "channel123",
|
|
"duration": "5:00",
|
|
"view_count": "1000",
|
|
"upload_date": "20240101",
|
|
"description": "Test description",
|
|
"thumbnail_url": "https://example.com/thumb.jpg",
|
|
"url": "https://www.youtube.com/watch?v=abc123",
|
|
}
|
|
|
|
video = Video.from_dict(video_dict)
|
|
|
|
assert video.video_id == "abc123"
|
|
assert video.title == "Test Video"
|
|
assert video.channel == "Test Channel"
|
|
assert video.description == "Test description"
|
|
|
|
def test_from_dict_optional_fields(self, sample_video_data):
|
|
"""Test from_dict with optional fields"""
|
|
video_dict = {
|
|
"video_id": "abc123",
|
|
"title": "Test Video",
|
|
"channel": "Test Channel",
|
|
"channel_id": "channel123",
|
|
"duration": "5:00",
|
|
"view_count": "1000",
|
|
"upload_date": "20240101",
|
|
# description is optional
|
|
}
|
|
|
|
video = Video.from_dict(video_dict)
|
|
|
|
assert video.description == ""
|
|
assert video.thumbnail_url is None
|
|
|
|
def test_video_equality(self, sample_video_data):
|
|
"""Test Video equality comparison"""
|
|
video1 = Video(**sample_video_data)
|
|
video2 = Video(**sample_video_data)
|
|
video3 = Video(**{**sample_video_data, "title": "Different Title"})
|
|
|
|
# Dataclass should have automatic equality
|
|
assert video1 == video2
|
|
assert video1 != video3
|
|
|
|
def test_video_repr(self, sample_video_data):
|
|
"""Test Video string representation"""
|
|
video = Video(**sample_video_data)
|
|
repr_str = repr(video)
|
|
|
|
assert "Video" in repr_str
|
|
assert "dQw4w9WgXcQ" in repr_str
|
|
|
|
def test_video_hash(self, sample_video_data):
|
|
"""Test Video hash (for set usage)"""
|
|
video = Video(**sample_video_data)
|
|
|
|
# Dataclass should be hashable (unless frozen=True, then not)
|
|
try:
|
|
video_hash = hash(video)
|
|
assert isinstance(video_hash, int)
|
|
except TypeError:
|
|
# If not hashable, that's also acceptable for mutable dataclasses
|
|
pass
|
|
|
|
def test_video_with_custom_url(self, sample_video_data):
|
|
"""Test Video with custom URL"""
|
|
custom_url = "https://youtu.be/dQw4w9WgXcQ"
|
|
video_data = sample_video_data.copy()
|
|
video_data["url"] = custom_url
|
|
|
|
video = Video(**video_data)
|
|
|
|
assert video.url == custom_url
|
|
# is_short should be detected from URL
|
|
assert video.is_short is False # youtu.be doesn't have /shorts/
|
|
|
|
def test_video_short_youtu_be(self, sample_video_data):
|
|
"""Test short detection with youtu.be URL"""
|
|
short_url = "https://youtu.be/dQw4w9WgXcQ?t=0"
|
|
video_data = sample_video_data.copy()
|
|
video_data["url"] = short_url
|
|
video_data["is_short"] = False # Reset to test detection
|
|
|
|
# Note: Our detection only checks for /shorts/ in URL, not youtu.be shorts
|
|
video = Video(**video_data)
|
|
# This should be False since we don't detect youtu.be shorts URLs
|
|
assert video.is_short is False
|
|
|
|
def test_video_empty_description(self, sample_video_data):
|
|
"""Test Video with empty description"""
|
|
video_data = sample_video_data.copy()
|
|
video_data["description"] = ""
|
|
|
|
video = Video(**video_data)
|
|
|
|
assert video.description == ""
|
|
|
|
def test_video_none_values(self, sample_video_data):
|
|
"""Test Video with None values"""
|
|
video_data = {
|
|
"video_id": "test123",
|
|
"title": "Test",
|
|
"channel": "Channel",
|
|
"channel_id": "channel123",
|
|
"duration": "1:00",
|
|
"view_count": "0",
|
|
"upload_date": "20240101",
|
|
"description": "",
|
|
"thumbnail_url": None,
|
|
}
|
|
|
|
video = Video(**video_data)
|
|
|
|
assert video.thumbnail_url is None
|
|
assert video.description == ""
|
|
assert video.url == "https://www.youtube.com/watch?v=test123"
|