File size: 5,426 Bytes
44a2550
 
75d3906
44a2550
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""Unit tests for utility functions."""
import pytest
from app_utils import validate_youtube_url, check_video_availability
from unittest.mock import patch, MagicMock
import yt_dlp


class TestValidateYouTubeURL:
    """Test YouTube URL validation."""

    def test_valid_watch_url(self):
        """Test standard youtube.com/watch URL."""
        is_valid, video_id = validate_youtube_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
        assert is_valid is True
        assert video_id == "dQw4w9WgXcQ"

    def test_valid_short_url(self):
        """Test youtu.be short URL."""
        is_valid, video_id = validate_youtube_url("https://youtu.be/dQw4w9WgXcQ")
        assert is_valid is True
        assert video_id == "dQw4w9WgXcQ"

    def test_valid_mobile_url(self):
        """Test mobile YouTube URL."""
        is_valid, video_id = validate_youtube_url("https://m.youtube.com/watch?v=dQw4w9WgXcQ")
        assert is_valid is True
        assert video_id == "dQw4w9WgXcQ"

    def test_valid_embed_url(self):
        """Test embedded YouTube URL."""
        is_valid, video_id = validate_youtube_url("https://www.youtube.com/embed/dQw4w9WgXcQ")
        assert is_valid is True
        assert video_id == "dQw4w9WgXcQ"

    def test_valid_with_extra_params(self):
        """Test URL with additional query parameters."""
        is_valid, video_id = validate_youtube_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=30s")
        assert is_valid is True
        assert video_id == "dQw4w9WgXcQ"

    def test_invalid_domain(self):
        """Test URL from wrong domain."""
        is_valid, error = validate_youtube_url("https://vimeo.com/12345")
        assert is_valid is False
        assert error == "Invalid YouTube URL format"

    def test_invalid_format(self):
        """Test malformed URL."""
        is_valid, error = validate_youtube_url("not-a-url")
        assert is_valid is False
        assert error == "Invalid YouTube URL format"

    def test_invalid_video_id_length(self):
        """Test URL with incorrect video ID length."""
        is_valid, error = validate_youtube_url("https://www.youtube.com/watch?v=short")
        assert is_valid is False
        assert error == "Invalid YouTube URL format"

    def test_empty_url(self):
        """Test empty URL."""
        is_valid, error = validate_youtube_url("")
        assert is_valid is False
        assert error == "Invalid YouTube URL format"


class TestCheckVideoAvailability:
    """Test video availability checking."""

    @patch('yt_dlp.YoutubeDL')
    def test_available_video(self, mock_ydl_class, mock_yt_dlp_info):
        """Test checking available video."""
        mock_ydl = MagicMock()
        mock_ydl.extract_info.return_value = mock_yt_dlp_info
        mock_ydl_class.return_value.__enter__.return_value = mock_ydl

        result = check_video_availability("dQw4w9WgXcQ")

        assert result['available'] is True
        assert 'info' in result

    @patch('yt_dlp.YoutubeDL')
    def test_video_too_long(self, mock_ydl_class):
        """Test video exceeding duration limit."""
        mock_ydl = MagicMock()
        mock_ydl.extract_info.return_value = {
            'duration': 1200,  # 20 minutes
            'age_limit': 0
        }
        mock_ydl_class.return_value.__enter__.return_value = mock_ydl

        result = check_video_availability("dQw4w9WgXcQ", max_duration=900)

        assert result['available'] is False
        assert 'max 15 minutes' in result['reason']

    @patch('yt_dlp.YoutubeDL')
    def test_age_restricted_video(self, mock_ydl_class):
        """Test age-restricted video."""
        mock_ydl = MagicMock()
        mock_ydl.extract_info.return_value = {
            'duration': 180,
            'age_limit': 18
        }
        mock_ydl_class.return_value.__enter__.return_value = mock_ydl

        result = check_video_availability("dQw4w9WgXcQ")

        assert result['available'] is False
        assert 'Age-restricted' in result['reason']

    @patch('yt_dlp.YoutubeDL')
    def test_download_error(self, mock_ydl_class):
        """Test yt-dlp download error."""
        mock_ydl = MagicMock()
        mock_ydl.extract_info.side_effect = yt_dlp.utils.DownloadError("Video unavailable")
        mock_ydl_class.return_value.__enter__.return_value = mock_ydl

        result = check_video_availability("invalid_id")

        assert result['available'] is False
        assert 'Video unavailable' in result['reason']

    @patch('yt_dlp.YoutubeDL')
    def test_generic_error(self, mock_ydl_class):
        """Test generic error handling."""
        mock_ydl = MagicMock()
        mock_ydl.extract_info.side_effect = Exception("Unknown error")
        mock_ydl_class.return_value.__enter__.return_value = mock_ydl

        result = check_video_availability("dQw4w9WgXcQ")

        assert result['available'] is False
        assert 'Error checking video' in result['reason']

    @patch('yt_dlp.YoutubeDL')
    def test_video_at_max_duration(self, mock_ydl_class):
        """Test video exactly at duration limit."""
        mock_ydl = MagicMock()
        mock_ydl.extract_info.return_value = {
            'duration': 900,  # Exactly 15 minutes
            'age_limit': 0
        }
        mock_ydl_class.return_value.__enter__.return_value = mock_ydl

        result = check_video_availability("dQw4w9WgXcQ", max_duration=900)

        assert result['available'] is True