ytdl-sub/tests/integration/cli/test_entrypoint.py
Jesse Bannon 57fd6901e4
[DEV] Linter: Use ruff over black and isort (#1445)
Will eventually replace pylint with ruff
2026-03-09 11:39:01 -07:00

158 lines
5.8 KiB
Python

import re
import sys
from pathlib import Path
from typing import Callable, List
from unittest.mock import patch
import pytest
from ytdl_sub.cli.entrypoint import _download_subscriptions_from_yaml_files, main
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.exceptions import ExperimentalFeatureNotEnabled
####################################################################################################
# SHARED FIXTURES
####################################################################################################
# PERSIST LOGS FIXTURES + TESTS
@pytest.mark.parametrize("dry_run", [True, False])
@pytest.mark.parametrize("mock_success_output", [True, False])
@pytest.mark.parametrize("keep_successful_logs", [True, False])
@pytest.mark.parametrize("match", [[], ["Rick", "Michael"]])
def test_subscription_logs_write_to_file(
persist_logs_directory: str,
persist_logs_config_factory: Callable,
mock_subscription_download_factory: Callable,
music_video_subscription_path: Path,
dry_run: bool,
mock_success_output: bool,
keep_successful_logs: bool,
match: List[str],
):
subscription_names = ["Rick Astley", "Michael Jackson", "Eric Clapton", "Guns N' Roses"]
if match:
subscription_names = ["Rick Astley", "Michael Jackson"]
num_runs = 2
config = persist_logs_config_factory(keep_successful_logs=keep_successful_logs)
subscription_paths = [str(music_video_subscription_path)] * num_runs
with (
patch.object(
Subscription,
"download",
new=mock_subscription_download_factory(mock_success_output=mock_success_output),
# mock datetime to be an index to be able to run instantly
),
patch("ytdl_sub.cli.entrypoint._log_time", side_effect=[str(idx) for idx in range(10)]),
):
try:
_download_subscriptions_from_yaml_files(
config=config,
subscription_paths=subscription_paths,
subscription_matches=match,
subscription_override_dict={},
update_with_info_json=False,
dry_run=dry_run,
shuffle=False,
)
except ValueError:
assert not mock_success_output
log_directory_files = sorted(list(Path(persist_logs_directory).rglob("*")))
# If dry run or success but success logging disabled, expect 0 log files
if dry_run or (mock_success_output and not keep_successful_logs):
assert len(log_directory_files) == 0
return
# If not success, expect 2 log files for both sub errors
elif not mock_success_output:
assert len(log_directory_files) == (num_runs * len(subscription_names))
for log_path, subscription_name in zip(log_directory_files, subscription_names):
subscription_log_file_name = subscription_name.lower().replace(" ", "_")
assert bool(re.match(rf"\d\.{subscription_log_file_name}\.error\.log", log_path.name))
with open(log_path, "r", encoding="utf-8") as log_file:
assert log_file.readlines()[-1] == (
f"Please upload the error log file '{str(log_path)}' and make a Github issue "
f"at https://github.com/jmbannon/ytdl-sub/issues with your config and "
f"command/subscription yaml file to reproduce. Thanks for trying ytdl-sub!\n"
)
# If success and success logging, expect 3 log files
else:
assert len(log_directory_files) == (num_runs * len(subscription_names))
for log_file_path, subscription_name in zip(
log_directory_files, subscription_names * num_runs
):
subscription_log_file_name = subscription_name.lower().replace(" ", "_")
assert bool(
re.match(rf"\d\.{subscription_log_file_name}\.success\.log", log_file_path.name)
)
with open(log_file_path, "r", encoding="utf-8") as log_file:
assert (
log_file.readlines()[-1]
== f"[ytdl-sub] name={subscription_name} success=True dry_run=False\n"
)
def test_update_with_info_json_requires_experimental_flag(
default_config_path: Path,
music_video_subscription_path: Path,
) -> None:
with (
patch.object(
sys,
"argv",
[
"ytdl-sub",
"--config",
str(default_config_path),
"sub",
str(music_video_subscription_path),
"--update-with-info-json",
],
),
pytest.raises(ExperimentalFeatureNotEnabled),
):
_ = main()
def test_subscription_shuffle(
default_config: ConfigFile,
mock_subscription_download_factory: Callable,
music_video_subscription_path: Path,
):
subscription_paths = [str(music_video_subscription_path)]
with (
patch.object(
Subscription,
"download",
new=mock_subscription_download_factory(mock_success_output=True),
),
):
out1 = _download_subscriptions_from_yaml_files(
config=default_config,
subscription_paths=subscription_paths,
subscription_matches=[],
subscription_override_dict={},
update_with_info_json=False,
dry_run=True,
shuffle=True,
)
out2 = _download_subscriptions_from_yaml_files(
config=default_config,
subscription_paths=subscription_paths,
subscription_matches=[],
subscription_override_dict={},
update_with_info_json=False,
dry_run=True,
shuffle=True,
)
assert [sub.name for sub in out1] != [sub.name for sub in out2]