159 lines
6.6 KiB
Python
159 lines
6.6 KiB
Python
import pytest
|
|
from backend.services.video_service import VideoService
|
|
from backend.core.exceptions import ValidationError, UnsupportedFormatError, ErrorCode
|
|
|
|
|
|
class TestVideoService:
|
|
|
|
@pytest.fixture
|
|
def video_service(self):
|
|
return VideoService()
|
|
|
|
def test_extract_video_id_standard_url(self, video_service):
|
|
"""Test extraction from standard YouTube watch URLs."""
|
|
test_cases = [
|
|
("https://youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("http://youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("https://youtube.com/watch?v=dQw4w9WgXcQ&t=30s", "dQw4w9WgXcQ"),
|
|
("https://youtube.com/watch?v=dQw4w9WgXcQ&feature=share", "dQw4w9WgXcQ"),
|
|
]
|
|
|
|
for url, expected_id in test_cases:
|
|
result = video_service.extract_video_id(url)
|
|
assert result == expected_id, f"Failed for URL: {url}"
|
|
|
|
def test_extract_video_id_short_url(self, video_service):
|
|
"""Test extraction from youtu.be short URLs."""
|
|
test_cases = [
|
|
("https://youtu.be/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("http://youtu.be/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("youtu.be/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("https://youtu.be/dQw4w9WgXcQ?t=30", "dQw4w9WgXcQ"),
|
|
]
|
|
|
|
for url, expected_id in test_cases:
|
|
result = video_service.extract_video_id(url)
|
|
assert result == expected_id, f"Failed for URL: {url}"
|
|
|
|
def test_extract_video_id_embed_url(self, video_service):
|
|
"""Test extraction from embed URLs."""
|
|
test_cases = [
|
|
("https://youtube.com/embed/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("https://www.youtube.com/embed/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("http://youtube.com/embed/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("youtube.com/embed/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
]
|
|
|
|
for url, expected_id in test_cases:
|
|
result = video_service.extract_video_id(url)
|
|
assert result == expected_id, f"Failed for URL: {url}"
|
|
|
|
def test_extract_video_id_mobile_url(self, video_service):
|
|
"""Test extraction from mobile YouTube URLs."""
|
|
test_cases = [
|
|
("https://m.youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("http://m.youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
("m.youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
|
|
]
|
|
|
|
for url, expected_id in test_cases:
|
|
result = video_service.extract_video_id(url)
|
|
assert result == expected_id, f"Failed for URL: {url}"
|
|
|
|
def test_extract_video_id_invalid_url(self, video_service):
|
|
"""Test that invalid URLs raise ValidationError."""
|
|
invalid_urls = [
|
|
"https://vimeo.com/123456789",
|
|
"https://dailymotion.com/video/x123456",
|
|
"not-a-url-at-all",
|
|
"https://example.com",
|
|
"https://youtube.com/",
|
|
"https://youtube.com/channel/UCxxxxx",
|
|
]
|
|
|
|
for url in invalid_urls:
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
video_service.extract_video_id(url)
|
|
assert exc_info.value.error_code == ErrorCode.INVALID_URL
|
|
|
|
def test_extract_video_id_invalid_video_id_length(self, video_service):
|
|
"""Test that video IDs with incorrect length are rejected."""
|
|
invalid_urls = [
|
|
"https://youtube.com/watch?v=short", # Too short
|
|
"https://youtube.com/watch?v=thisistoolong123", # Too long
|
|
"https://youtu.be/abc", # Too short
|
|
]
|
|
|
|
for url in invalid_urls:
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
video_service.extract_video_id(url)
|
|
assert exc_info.value.error_code == ErrorCode.INVALID_URL
|
|
|
|
def test_extract_video_id_playlist_url(self, video_service):
|
|
"""Test that playlist URLs raise UnsupportedFormatError."""
|
|
playlist_urls = [
|
|
"https://youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf",
|
|
"https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf",
|
|
"https://youtube.com/watch?v=dQw4w9WgXcQ&list=PLxxxxx&index=2",
|
|
]
|
|
|
|
for url in playlist_urls:
|
|
with pytest.raises(UnsupportedFormatError) as exc_info:
|
|
video_service.extract_video_id(url)
|
|
assert exc_info.value.error_code == ErrorCode.UNSUPPORTED_FORMAT
|
|
assert "playlist" in exc_info.value.message.lower()
|
|
|
|
def test_extract_video_id_empty_url(self, video_service):
|
|
"""Test that empty URL raises ValidationError."""
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
video_service.extract_video_id("")
|
|
assert exc_info.value.error_code == ErrorCode.INVALID_URL
|
|
assert "empty" in exc_info.value.message.lower()
|
|
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
video_service.extract_video_id(None)
|
|
assert exc_info.value.error_code == ErrorCode.INVALID_URL
|
|
|
|
def test_validate_video_id(self, video_service):
|
|
"""Test video ID validation logic."""
|
|
# Valid IDs
|
|
valid_ids = [
|
|
"dQw4w9WgXcQ",
|
|
"aB3-567_890",
|
|
"___________", # All underscores
|
|
"-----------", # All hyphens
|
|
"ABCDEFGHIJK", # All uppercase
|
|
"abcdefghijk", # All lowercase
|
|
"12345678901", # All numbers
|
|
]
|
|
|
|
for video_id in valid_ids:
|
|
assert video_service._validate_video_id(video_id) is True
|
|
|
|
# Invalid IDs
|
|
invalid_ids = [
|
|
"short", # Too short
|
|
"thisistoolong", # Too long
|
|
"has space11", # Contains space
|
|
"has@special", # Contains special char
|
|
"", # Empty
|
|
None, # None
|
|
]
|
|
|
|
for video_id in invalid_ids:
|
|
assert video_service._validate_video_id(video_id) is False
|
|
|
|
def test_normalize_url(self, video_service):
|
|
"""Test URL normalization."""
|
|
video_id = "dQw4w9WgXcQ"
|
|
expected = "https://youtube.com/watch?v=dQw4w9WgXcQ"
|
|
assert video_service.normalize_url(video_id) == expected
|
|
|
|
def test_get_supported_formats(self, video_service):
|
|
"""Test getting supported formats list."""
|
|
formats = video_service.get_supported_formats()
|
|
assert isinstance(formats, list)
|
|
assert len(formats) > 0
|
|
assert all("VIDEO_ID" in fmt for fmt in formats) |