diff --git a/tests/conftest.py b/tests/conftest.py index 5fae5a81..3e2be58e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ import contextlib import json import logging import os +import shutil import tempfile from pathlib import Path from typing import Any @@ -11,10 +12,14 @@ from typing import List from unittest.mock import patch import pytest +from expected_download import _get_files_in_directory +from ytdl_sub.config.config_file import ConfigFile +from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.logger import LoggerLevels +from ytdl_sub.utils.yaml import load_yaml @pytest.fixture(autouse=True) @@ -28,9 +33,31 @@ def cleanup_debug_file(): @pytest.fixture -def working_directory() -> Path: +def working_directory() -> str: + """ + Any time the working directory is used, ensure no files remain on cleaning it up + """ + logger = Logger.get("test") + with tempfile.TemporaryDirectory() as temp_dir: - yield temp_dir + + def _assert_working_directory_empty(self, is_error: bool = False): + files = [str(file_path) for file_path in _get_files_in_directory(temp_dir)] + num_files = len(files) + if os.path.isdir(temp_dir): + shutil.rmtree(temp_dir) + + if not is_error: + if num_files > 0: + logger.error("left-over files in working dir:\n%s", "\n".join(files)) + assert num_files == 0 + + with patch.object( + SubscriptionDownload, + "_delete_working_directory", + new=_assert_working_directory_empty, + ): + yield temp_dir @pytest.fixture() @@ -106,3 +133,38 @@ def preset_dict_to_subscription_yaml_generator() -> Callable: FileHandler.delete(tmp_file.name) return _preset_dict_to_subscription_yaml_generator + + +################################################################################################### +# Example config fixtures + + +def _load_config(config_path: Path, working_directory: Path) -> ConfigFile: + config_dict = load_yaml(file_path=config_path) + config_dict["configuration"]["working_directory"] = working_directory + + return ConfigFile.from_dict(config_dict) + + +@pytest.fixture() +def music_video_config_path() -> Path: + return Path("examples/music_videos_config.yaml") + + +@pytest.fixture() +def music_video_config(music_video_config_path, working_directory) -> ConfigFile: + return _load_config(music_video_config_path, working_directory) + + +@pytest.fixture() +def channel_as_tv_show_config(working_directory) -> ConfigFile: + return _load_config( + config_path=Path("examples/tv_show_config.yaml"), working_directory=working_directory + ) + + +@pytest.fixture() +def music_audio_config(working_directory) -> ConfigFile: + return _load_config( + config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory + ) diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index e307abd5..0cb271bb 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -1,69 +1,16 @@ import json -import os -import shutil import sys import tempfile -from pathlib import Path from typing import List from typing import Tuple from unittest.mock import patch import pytest -from expected_download import _get_files_in_directory from ytdl_sub.cli.main import main -from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.subscriptions.subscription import Subscription -from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandlerTransactionLog -from ytdl_sub.utils.logger import Logger -from ytdl_sub.utils.yaml import load_yaml - -logger = Logger.get("test") - - -@pytest.fixture -def working_directory() -> str: - """ - Any time the working directory is used, ensure no files remain on cleaning it up - """ - with tempfile.TemporaryDirectory() as temp_dir: - - def _assert_working_directory_empty(self, is_error: bool = False): - files = [str(file_path) for file_path in _get_files_in_directory(temp_dir)] - num_files = len(files) - if os.path.isdir(temp_dir): - shutil.rmtree(temp_dir) - - if not is_error: - if num_files > 0: - logger.error("left-over files in working dir:\n%s", "\n".join(files)) - assert num_files == 0 - - with patch.object( - SubscriptionDownload, - "_delete_working_directory", - new=_assert_working_directory_empty, - ): - yield temp_dir - - -@pytest.fixture() -def music_video_config_path() -> Path: - return Path("examples/music_videos_config.yaml") - - -def _load_config(config_path: Path, working_directory: Path) -> ConfigFile: - config_dict = load_yaml(file_path=config_path) - config_dict["configuration"]["working_directory"] = working_directory - - return ConfigFile.from_dict(config_dict) - - -@pytest.fixture() -def music_video_config(music_video_config_path, working_directory) -> ConfigFile: - return _load_config(music_video_config_path, working_directory) @pytest.fixture() @@ -77,20 +24,6 @@ def music_video_config_for_cli(music_video_config) -> str: FileHandler.delete(tmp_file.name) -@pytest.fixture() -def channel_as_tv_show_config(working_directory) -> ConfigFile: - return _load_config( - config_path=Path("examples/tv_show_config.yaml"), working_directory=working_directory - ) - - -@pytest.fixture() -def music_audio_config(working_directory) -> ConfigFile: - return _load_config( - config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory - ) - - @pytest.fixture def timestamps_file_path(): timestamps = [ diff --git a/tests/unit/cli/test_main.py b/tests/unit/cli/test_main.py index bc61b5cb..67f305f6 100644 --- a/tests/unit/cli/test_main.py +++ b/tests/unit/cli/test_main.py @@ -1,6 +1,9 @@ import sys +import tempfile from unittest.mock import patch +import pytest + from ytdl_sub.cli.main import main @@ -16,3 +19,30 @@ def test_args_after_sub_work(): assert mock_sub.call_args.kwargs["args"].config == "examples/tv_show_config.yaml" assert mock_sub.call_args.kwargs["args"].subscription_paths == ["subscriptions.yaml"] assert mock_sub.call_args.kwargs["args"].ytdl_sub_log_level == "debug" + + +@pytest.fixture +def persist_logs_directory(): + with tempfile.TemporaryDirectory() as temp_dir: + yield temp_dir + + +@pytest.fixture +def persist_logs_config(): + pass + + +class TestPersistLogs: + @pytest.mark.parametrize("mock_success_output", [True, False]) + @pytest.mark.parametrize("keep_successful_logs", [True, False]) + def test_subscription_logs_write_to_file( + self, persist_logs_directory: str, mock_success_output: bool, keep_successful_logs: bool + ): + + config_dict = { + "working_directory": ".", + "persist_logs": { + "logs_directory": persist_logs_directory, + "keep_successful_logs": keep_successful_logs, + }, + } diff --git a/tests/unit/prebuilt_presets/conftest.py b/tests/unit/prebuilt_presets/conftest.py index 9401b3d2..e1f8ad14 100644 --- a/tests/unit/prebuilt_presets/conftest.py +++ b/tests/unit/prebuilt_presets/conftest.py @@ -56,6 +56,7 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable: playlist_index: int = 1, playlist_count: int = 1, is_youtube_channel: bool = False, + mock_download_to_working_dir: bool = True, ) -> Dict: entry_dict = { UID: uid, @@ -84,12 +85,14 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable: ] # Create mock video file - copy_file_fixture( - fixture_name="sample_vid.mp4", output_file_path=mock_downloaded_file_path(f"{uid}.mp4") - ) - copy_file_fixture( - fixture_name="thumb.jpg", output_file_path=mock_downloaded_file_path(f"{uid}.jpg") - ) + if mock_download_to_working_dir: + copy_file_fixture( + fixture_name="sample_vid.mp4", + output_file_path=mock_downloaded_file_path(f"{uid}.mp4"), + ) + copy_file_fixture( + fixture_name="thumb.jpg", output_file_path=mock_downloaded_file_path(f"{uid}.jpg") + ) return entry_dict return _mock_entry_dict_factory @@ -124,36 +127,33 @@ def mock_download_collection_entries( ): @contextlib.contextmanager def _mock_download_collection_entries_factory(is_youtube_channel: bool): - def _(**kwargs): - return mock_entry_dict_factory(**kwargs) - def _write_entries_to_working_dir(*args, **kwargs) -> List[Dict]: if (len(args[0].collection.urls.list) == 1) or ( "season.2" in kwargs["url"] and len(args[0].download_options.urls.list) > 1 ): return [ - _( + mock_entry_dict_factory( uid="21-1", upload_date="20210808", playlist_index=1, playlist_count=4, is_youtube_channel=is_youtube_channel, ), # 1 - _( + mock_entry_dict_factory( uid="20-1", upload_date="20200808", playlist_index=2, playlist_count=4, is_youtube_channel=is_youtube_channel, ), # 2 98 - _( + mock_entry_dict_factory( uid="20-2", upload_date="20200808", playlist_index=3, playlist_count=4, is_youtube_channel=is_youtube_channel, ), # 1 99 - _( + mock_entry_dict_factory( uid="20-3", upload_date="20200807", playlist_index=4, @@ -163,35 +163,36 @@ def mock_download_collection_entries( ] return [ # 20-3 should resolve to collection 1 (which is season 2) - _( + mock_entry_dict_factory( uid="20-3", upload_date="20200807", playlist_index=1, playlist_count=5, is_youtube_channel=is_youtube_channel, + mock_download_to_working_dir=False, ), - _( + mock_entry_dict_factory( uid="20-4", upload_date="20200806", playlist_index=2, playlist_count=5, is_youtube_channel=is_youtube_channel, ), - _( + mock_entry_dict_factory( uid="20-5", upload_date="20200706", playlist_index=3, playlist_count=5, is_youtube_channel=is_youtube_channel, ), - _( + mock_entry_dict_factory( uid="20-6", upload_date="20200706", playlist_index=4, playlist_count=5, is_youtube_channel=is_youtube_channel, ), - _( + mock_entry_dict_factory( uid="20-7", upload_date="20200606", playlist_index=5,