youtube-cli/tests/unit/test_models.py
Jarian Cottingham 06877fb2fc feat: add TUI (Textual User Interface) with download queue system
- New TUI using Textual framework with responsive interface
- Search, results, download, and queue screens for YouTube video management
- Download queue system with sequential background downloads
- Status bar with queue count and download progress indicators
- Comprehensive test suite (97 tests) with 100% pass rate
- Modern Python packaging with pyproject.toml and uv support
- Added requirements-tui.txt for TUI-specific dependencies
- Updated setup.py and install.sh for TUI integration
- Enhanced README.md with TUI usage documentation
2026-02-25 15:59:15 -06:00

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"