""" Test fixtures and configuration for YouTube TUI tests """ import asyncio from unittest.mock import AsyncMock, MagicMock, patch import pytest # Test fixtures @pytest.fixture def sample_video_data(): """Sample video data for testing""" return { "video_id": "dQw4w9WgXcQ", "title": "Rick Astley - Never Gonna Give You Up", "channel": "RickAstleyVEVO", "channel_id": "UCuZqHn2U8f4o7bVlY8v8w", "duration": "3:33", "view_count": "1000000", "upload_date": "20091025", "description": "The official video for Rick Astley's hit song.", "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg", "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "is_short": False, } @pytest.fixture def sample_video_object(sample_video_data): """Sample Video object for testing""" from youtube_tui.models.video import Video return Video(**sample_video_data) @pytest.fixture def mock_yt_dlp_result(): """Mock yt-dlp search result""" return { "id": "abc123", "title": "Sample Video", "author": "Sample Channel", "channel": "Sample Channel", "channel_id": "channel123", "length": "10:30", "view_count": 150000, "upload_date": "20240115", "description": "A sample video description", "thumbnail": "https://i.ytimg.com/vi/abc123/hqdefault.jpg", "url": "https://www.youtube.com/watch?v=abc123", } @pytest.fixture def mock_youtube_service(): """Mock YouTubeService for testing""" from youtube_cli.main import YouTubeCLI from youtube_tui.services.youtube import YouTubeService # Create a real service with mocked cli with patch.object(YouTubeCLI, "__init__", return_value=None): service = YouTubeService.__new__(YouTubeService) service.cli = MagicMock() service.console = MagicMock() # Mock async methods service.search_videos = AsyncMock() service.download_video = AsyncMock() service.download_playlist = AsyncMock() service.get_categories = AsyncMock() service.is_video_downloaded = AsyncMock() service.add_to_archive = AsyncMock() service.get_archive = AsyncMock() service.get_downloaded_video_ids = AsyncMock() service.remove_from_archive = AsyncMock() service._create_video_from_result = MagicMock() return service @pytest.fixture def mock_video(): """Mock Video object""" from youtube_tui.models.video import Video video = Video( video_id="test123", 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=test123", is_short=False, ) return video @pytest.fixture def mock_search_results(): """Mock search results""" from youtube_tui.models.video import Video videos = [ Video( video_id=f"video{i}", title=f"Video {i}", channel=f"Channel {i}", channel_id=f"channel{i}", duration=f"{i}:00", view_count=str(i * 1000), upload_date="20240101", description=f"Description {i}", is_short=(i % 3 == 0), url=f"https://www.youtube.com/watch?v=video{i}", ) for i in range(1, 16) ] return videos @pytest.fixture def app_config(tmp_path): """Temporary app configuration""" config = { "download_dir": str(tmp_path / "downloads"), "default_locations": [ str(tmp_path / "downloads"), str(tmp_path / "movies"), ], "max_videos_per_page": 15, "yt_dlp_args": { "format": "bestvideo[height=1080]+bestaudio", }, "network_share_path": str(tmp_path / "network"), "default_network_subfolder": "General", } return config @pytest.fixture def mock_app(): """Mock Textual App for testing screens""" from textual.app import App mock_app = MagicMock(spec=App) mock_app.screen_stack = [None, None, None] # Simulate screen stack mock_app.notify = MagicMock() mock_app.exit = MagicMock() # Mock push_screen and pop_screen mock_app.push_screen = MagicMock() mock_app.push_results_screen = MagicMock() mock_app.pop_screen = MagicMock() mock_app.action_open_search = MagicMock() mock_app.run_background = MagicMock() return mock_app # Async test utilities @pytest.fixture def event_loop(): """Create an event loop for async tests""" loop = asyncio.new_event_loop() yield loop loop.close() @pytest.fixture async def async_mock_search_results(): """Async mock search results""" from youtube_tui.models.video import Video videos = [ Video( video_id=f"video{i}", title=f"Video {i}", channel=f"Channel {i}", channel_id=f"channel{i}", duration=f"{i}:00", view_count=str(i * 1000), upload_date="20240101", description=f"Description {i}", is_short=(i % 3 == 0), url=f"https://www.youtube.com/watch?v=video{i}", ) for i in range(1, 16) ] return videos # Mock patches @pytest.fixture def mock_yt_dlp(): """Patch yt-dlp for testing""" with patch("youtube_tui.services.youtube.subprocess") as mock_subprocess: mock_result = MagicMock() mock_result.returncode = 0 mock_result.stdout = "2024.01.01" mock_subprocess.run.return_value = mock_result yield mock_subprocess @pytest.fixture def mock_archive(): """Mock archive data""" return { "video123": { "url": "https://www.youtube.com/watch?v=video123", "id": "video123", "title": "Downloaded Video", } } @pytest.fixture def mock_archive_file(tmp_path, mock_archive): """Create a mock archive file""" archive_path = tmp_path / "archive.json" import json with open(archive_path, "w") as f: json.dump(mock_archive, f) return archive_path