import re from contextlib import contextmanager from typing import Dict from unittest.mock import patch import pytest from mergedeep import mergedeep from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.plugins.nfo_tags import NfoTagsOptions from ytdl_sub.subscriptions.subscription import FILE_SUBSCRIPTION_VALUE_KEY from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.utils.exceptions import ValidationException @pytest.fixture def config_file_with_subscription_value(config_file: ConfigFile): config_dict = config_file.as_dict() mergedeep.merge( config_dict, {"configuration": {"subscription_value": "test_config_subscription_value"}} ) return ConfigFile.from_dict(config_dict) @contextmanager def mock_load_yaml(preset_dict: Dict) -> None: with patch("ytdl_sub.subscriptions.subscription.load_yaml") as mock_load_yaml: mock_load_yaml.return_value = preset_dict yield @pytest.fixture def preset_file(youtube_video: Dict, output_options: Dict): with patch("ytdl_sub.subscriptions.subscription.load_yaml") as mock_load_yaml: mock_load_yaml.return_value = { "__preset__": { "download": youtube_video, "output_options": output_options, "nfo_tags": { "tags": {"key-3": "file_preset"}, }, "overrides": { "test_file_subscription_value": "original", "test_config_subscription_value": "original", }, }, "test_preset": { "preset": "parent_preset_3", "nfo_tags": { "tags": {"key-4": "test_preset"}, }, }, } yield @pytest.fixture def preset_with_subscription_value(youtube_video: Dict, output_options: Dict): with patch("ytdl_sub.subscriptions.subscription.load_yaml") as mock_load_yaml: mock_load_yaml.return_value = { "__preset__": { "preset": "parent_preset_3", "download": youtube_video, "output_options": output_options, "nfo_tags": { "tags": {"key-3": "file_preset"}, }, "overrides": { "test_file_subscription_value": "original", "test_config_subscription_value": "original", }, }, "__value__": "test_file_subscription_value", "test_value": "is_overwritten", } yield @pytest.fixture def preset_file_with_value(youtube_video: Dict, output_options: Dict): with patch("ytdl_sub.subscriptions.subscription.load_yaml") as mock_load_yaml: mock_load_yaml.return_value = { "__preset__": { "preset": "parent_preset_3", "download": youtube_video, "output_options": output_options, "nfo_tags": { "tags": {"key-3": "file_preset"}, }, "overrides": { "test_file_subscription_value": "original", "test_config_subscription_value": "original", }, }, "__value__": "test_file_subscription_value", "test_value": "is_overwritten", } yield @pytest.mark.usefixtures(preset_file.__name__) def test_subscription_file_preset_applies(config_file: ConfigFile): subs = Subscription.from_file_path(config=config_file, subscription_path="mocked") assert len(subs) == 1 # Test __preset__ worked correctly preset_sub = subs[0] nfo_options: NfoTagsOptions = preset_sub.plugins.get(NfoTagsOptions) tags_string_dict = { key: formatter[0].format_string for key, formatter in nfo_options.tags.string_tags.items() } assert tags_string_dict == { "key-1": "preset_0", "key-2": "preset_2", "key-3": "file_preset", "key-4": "test_preset", } @pytest.mark.usefixtures(preset_file_with_value.__name__) def test_subscription_file_value_applies(config_file: ConfigFile): subs = Subscription.from_file_path(config=config_file, subscription_path="mocked") assert len(subs) == 1 # Test __value__ worked correctly value_sub = subs[0] assert ( value_sub.overrides.dict_with_format_strings.get("test_file_subscription_value") == "is_overwritten" ) assert ( value_sub.overrides.dict_with_format_strings.get("test_config_subscription_value") == "original" ) @pytest.mark.usefixtures(preset_file_with_value.__name__) def test_subscription_file_value_applies_sub_file_takes_precedence( config_file_with_subscription_value: ConfigFile, ): subs = Subscription.from_file_path( config=config_file_with_subscription_value, subscription_path="mocked" ) assert len(subs) == 1 # Test __value__ worked correctly value_sub = subs[0] assert ( value_sub.overrides.dict_with_format_strings.get("test_file_subscription_value") == "is_overwritten" ) assert ( value_sub.overrides.dict_with_format_strings.get("test_config_subscription_value") == "original" ) # @pytest.mark.usefixtures(preset_file.__name__) # def test_subscription_file_value_applies_from_config(config_file: ConfigFile): # subs = Subscription.from_file_path(config=config_file, subscription_path="mocked") # assert len(subs) == 1 # # # Test __value__ worked correctly # value_sub = subs[0] # assert value_sub.overrides.dict_with_format_strings.get("test_file_subscription_value") == "original" # assert value_sub.overrides.dict_with_format_strings.get( # "test_config_subscription_value") == "is_overwritten" def test_subscription_file_bad_value(config_file: ConfigFile): with mock_load_yaml(preset_dict={"__value__": {"should be": "string"}}), pytest.raises( ValidationException, match=re.escape( f"Using {FILE_SUBSCRIPTION_VALUE_KEY} in a subscription" f"must be a string that corresponds to an override variable" ), ): _ = Subscription.from_file_path(config=config_file, subscription_path="mocked") def test_subscription_file_using_value_when_not_defined(config_file: ConfigFile): with mock_load_yaml( preset_dict={"sub_name": "single value, __value__ not defined"} ), pytest.raises( ValidationException, match=re.escape( f"Subscription sub_name is a string, but " f"the subscription value is not set to an override variable" ), ): _ = Subscription.from_file_path(config=config_file, subscription_path="mocked") def test_subscription_file_invalid_form(config_file: ConfigFile): with mock_load_yaml(preset_dict={"sub_name": 4332}), pytest.raises( ValidationException, match=re.escape(f"Subscription sub_name should be in the form of a preset"), ): _ = Subscription.from_file_path(config=config_file, subscription_path="mocked")