diff --git a/.ytdl-sub-downloads/pz/UCcRSMoQqXc_JrBZRHDFGbqA.info.json b/.ytdl-sub-downloads/pz/UCcRSMoQqXc_JrBZRHDFGbqA.info.json new file mode 100644 index 00000000..fb31e285 --- /dev/null +++ b/.ytdl-sub-downloads/pz/UCcRSMoQqXc_JrBZRHDFGbqA.info.json @@ -0,0 +1 @@ +{"uploader": "Project Zombie", "uploader_id": "UCcRSMoQqXc_JrBZRHDFGbqA", "uploader_url": "https://www.youtube.com/channel/UCcRSMoQqXc_JrBZRHDFGbqA", "thumbnails": [{"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w320-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj", "height": 88, "width": 320, "preference": -10, "id": "0", "resolution": "320x88"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj", "height": 180, "width": 320, "preference": -10, "id": "1", "resolution": "320x180"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w640-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj", "height": 175, "width": 640, "preference": -10, "id": "2", "resolution": "640x175"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj", "height": 480, "width": 854, "preference": -10, "id": "3", "resolution": "854x480"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w960-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj", "height": 263, "width": 960, "preference": -10, "id": "4", "resolution": "960x263"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj", "height": 175, "width": 1060, "preference": -10, "id": "5", "resolution": "1060x175"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1138-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj", "height": 188, "width": 1138, "preference": -10, "id": "6", "resolution": "1138x188"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1280-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj", "height": 351, "width": 1280, "preference": -10, "id": "7", "resolution": "1280x351"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj", "height": 720, "width": 1280, "preference": -10, "id": "8", "resolution": "1280x720"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1440-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj", "height": 395, "width": 1440, "preference": -10, "id": "9", "resolution": "1440x395"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1707-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj", "height": 283, "width": 1707, "preference": -10, "id": "10", "resolution": "1707x283"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj", "height": 1080, "width": 1920, "preference": -10, "id": "11", "resolution": "1920x1080"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w2120-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj", "height": 351, "width": 2120, "preference": -10, "id": "12", "resolution": "2120x351"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj", "height": 1192, "width": 2120, "preference": -10, "id": "13", "resolution": "2120x1192"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w2276-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj", "height": 377, "width": 2276, "preference": -10, "id": "14", "resolution": "2276x377"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj", "height": 424, "width": 2560, "preference": -10, "id": "15", "resolution": "2560x424"}, {"url": "https://yt3.ggpht.com/JTVn6Fc3T9tFqL4gUfXVSFg069jVn-Y68eRS8W_ffbKpd2Q-cskP0fM_wssYnW9pBuS8cu_X=s0", "id": "banner_uncropped", "preference": -5}, {"url": "https://yt3.ggpht.com/ytc/AMLnZu_H2CZwR-Rj1D1WJZ1iagbHHLy9yHNxTVMBLdoB=s900-c-k-c0x00ffffff-no-rj", "height": 900, "width": 900, "id": "17", "resolution": "900x900"}, {"url": "https://yt3.ggpht.com/ytc/AMLnZu_H2CZwR-Rj1D1WJZ1iagbHHLy9yHNxTVMBLdoB=s0", "id": "avatar_uncropped", "preference": 1}], "tags": [], "channel_follower_count": 2710, "channel": "Project Zombie", "channel_id": "UCcRSMoQqXc_JrBZRHDFGbqA", "channel_url": "https://www.youtube.com/channel/UCcRSMoQqXc_JrBZRHDFGbqA", "id": "UCcRSMoQqXc_JrBZRHDFGbqA", "title": "Project Zombie - Videos", "description": "Plugin and map updates for the server Project Zombie.", "_type": "playlist", "webpage_url": "https://youtube.com/channel/UCcRSMoQqXc_JrBZRHDFGbqA", "webpage_url_basename": "UCcRSMoQqXc_JrBZRHDFGbqA", "webpage_url_domain": "youtube.com", "extractor": "youtube:tab", "extractor_key": "YoutubeTab", "epoch": 1660155821} \ No newline at end of file diff --git a/src/ytdl_sub/downloaders/youtube/split_video.py b/src/ytdl_sub/downloaders/youtube/split_video.py index 5a2e545d..c113af63 100644 --- a/src/ytdl_sub/downloaders/youtube/split_video.py +++ b/src/ytdl_sub/downloaders/youtube/split_video.py @@ -161,7 +161,8 @@ class YoutubeSplitVideoDownloader( entry = YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory) # convert the entry thumbnail early so we do not have to guess the thumbnail extension # when copying it - convert_download_thumbnail(entry=entry) + if not self.is_dry_run: + convert_download_thumbnail(entry=entry) for idx, title in enumerate(chapters.titles): new_uid = _split_video_uid(source_uid=entry.uid, idx=idx) @@ -181,12 +182,12 @@ class YoutubeSplitVideoDownloader( ) ) - # Copy the original vid thumbnail to the working directory with the new uid. This so - # downstream logic thinks this split video has its own thumbnail - FileHandler.copy( - src_file_path=entry.get_download_thumbnail_path(), - dst_file_path=Path(self.working_directory) / f"{new_uid}.{entry.thumbnail_ext}", - ) + # Copy the original vid thumbnail to the working directory with the new uid. This so + # downstream logic thinks this split video has its own thumbnail + FileHandler.copy( + src_file_path=entry.get_download_thumbnail_path(), + dst_file_path=Path(self.working_directory) / f"{new_uid}.{entry.thumbnail_ext}", + ) # Format the split video as a YoutubePlaylistVideo split_videos_and_metadata.append( diff --git a/tests/e2e/expected_download.py b/tests/e2e/expected_download.py index 8608ca2e..673d4fe7 100644 --- a/tests/e2e/expected_download.py +++ b/tests/e2e/expected_download.py @@ -5,10 +5,10 @@ from dataclasses import dataclass from pathlib import Path from typing import List from typing import Optional -from typing import Union _EXPECTED_DOWNLOADS_SUMMARY_PATH = Path("tests/e2e/resources/expected_downloads_summaries") + def _get_files_in_directory(relative_directory: Path | str) -> List[Path]: relative_file_paths: List[Path] = [] for path in Path(relative_directory).rglob("*"): @@ -18,14 +18,16 @@ def _get_files_in_directory(relative_directory: Path | str) -> List[Path]: return relative_file_paths + def _get_file_md5_hash(full_file_path: Path | str) -> str: with open(full_file_path, "rb") as file: return hashlib.md5(file.read()).hexdigest() + @dataclass class ExpectedDownloadFile: path: Path - md5: Optional[Union[str, List[str]]] = None + md5: str class ExpectedDownloads: @@ -47,10 +49,15 @@ class ExpectedDownloads: def contains(self, relative_path: Path) -> bool: return sum(relative_path == download.path for download in self.expected_downloads) == 1 - def assert_files_exist(self, relative_directory: str | Path): + def assert_files_exist( + self, relative_directory: str | Path, ignore_md5_hashes_for: Optional[List[str]] = None + ): """ Assert each expected file exists and that its respective md5 hash matches. """ + if ignore_md5_hashes_for is None: + ignore_md5_hashes_for = [] + relative_file_paths = _get_files_in_directory(relative_directory=relative_directory) for file_path in relative_file_paths: @@ -64,33 +71,26 @@ class ExpectedDownloads: full_path ), f"Expected {str(expected_download.path)} to be a file but it is not" - if expected_download.md5 is None: + if expected_download.path in ignore_md5_hashes_for: continue md5_hash = _get_file_md5_hash(full_file_path=full_path) - expected_md5_hash = expected_download.md5 - if isinstance(expected_download.md5, str): - expected_md5_hash = [expected_download.md5] - - assert md5_hash in expected_md5_hash, ( + assert md5_hash in expected_download.md5, ( f"MD5 hash for {str(expected_download.path)} does not match: " - f"{md5_hash} != {expected_md5_hash}" + f"{md5_hash} != {expected_download.md5}" ) @classmethod def from_dict(cls, expected_downloads_dict) -> "ExpectedDownloads": expected_downloads: List[ExpectedDownloadFile] = [] for file_path, md5_hash in expected_downloads_dict.items(): - expected_downloads.append(ExpectedDownloadFile( - path=Path(file_path), md5=md5_hash - )) + expected_downloads.append(ExpectedDownloadFile(path=Path(file_path), md5=md5_hash)) return cls(expected_downloads=expected_downloads) - @classmethod def from_file(cls, file_path: str | Path) -> "ExpectedDownloads": - with open(file_path, mode='r', encoding='utf-8') as file: + with open(file_path, mode="r", encoding="utf-8") as file: expected_downloads_dict = json.load(file) return cls.from_dict(expected_downloads_dict) @@ -98,35 +98,41 @@ class ExpectedDownloads: def from_directory(cls, directory_path: str | Path) -> "ExpectedDownloads": relative_file_paths = _get_files_in_directory(relative_directory=directory_path) expected_downloads_dict = { - str(file_path): _get_file_md5_hash(full_file_path=Path(directory_path) / file_path) for file_path in relative_file_paths + str(file_path): _get_file_md5_hash(full_file_path=Path(directory_path) / file_path) + for file_path in relative_file_paths } return cls.from_dict(expected_downloads_dict) - def to_summary_file(self, summary_file_path: Path | str) -> None: expected_downloads_dict = { str(exp_dl.path): exp_dl.md5 for exp_dl in self.expected_downloads } - with open(summary_file_path, mode='w', encoding='utf-8') as file: - json.dump(obj=expected_downloads_dict, fp=file, sort_keys=True, ensure_ascii=False, indent=2) + with open(summary_file_path, mode="w", encoding="utf-8") as file: + json.dump( + obj=expected_downloads_dict, fp=file, sort_keys=True, ensure_ascii=False, indent=2 + ) def assert_expected_downloads( - output_directory: str | Path, - dry_run: bool, - expected_download_summary_file_name: str, - regenerate_expected_download_summary: bool = True, + output_directory: str | Path, + dry_run: bool, + expected_download_summary_file_name: str, + regenerate_expected_download_summary: bool = False, ): if dry_run: output_directory_contents = list(Path(output_directory).rglob("*")) - assert len(output_directory_contents) == 0, f"Expected output directory to be empty after a dry-run, but found {output_directory_contents}" + assert ( + len(output_directory_contents) == 0 + ), f"Expected output directory to be empty after a dry-run, but found {output_directory_contents}" return summary_full_path = _EXPECTED_DOWNLOADS_SUMMARY_PATH / expected_download_summary_file_name if regenerate_expected_download_summary: - ExpectedDownloads.from_directory(directory_path=output_directory).to_summary_file(summary_file_path=summary_full_path) - - ExpectedDownloads.from_file(summary_full_path).assert_files_exist(relative_directory=output_directory) - + ExpectedDownloads.from_directory(directory_path=output_directory).to_summary_file( + summary_file_path=summary_full_path + ) + ExpectedDownloads.from_file(summary_full_path).assert_files_exist( + relative_directory=output_directory + ) diff --git a/tests/e2e/expected_transaction_log.py b/tests/e2e/expected_transaction_log.py index f50fda2c..12d23187 100644 --- a/tests/e2e/expected_transaction_log.py +++ b/tests/e2e/expected_transaction_log.py @@ -10,7 +10,7 @@ def assert_transaction_log_matches( output_directory: str, transaction_log: FileHandlerTransactionLog, transaction_log_summary_file_name: str, - regenerate_transaction_log: bool = True, + regenerate_transaction_log: bool = False, ): """ Parameters diff --git a/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json b/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json new file mode 100644 index 00000000..f3ce14cd --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/soundcloud/test_soundcloud_discography.json @@ -0,0 +1,19 @@ +{ + ".ytdl-sub-jb-download-archive.json": "1a99156e9ece62539fb2608416a07200", + "j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "bffbd558e12c6a9e029dc136a88342c4", + "j_b/[2021] Baby Santana's Dorian Groove/folder.jpg": "967892be44b8c47e1be73f055a7c6f08", + "j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "038db58aebe2ba875b733932b42a94d6", + "j_b/[2021] Purple Clouds/folder.jpg": "967892be44b8c47e1be73f055a7c6f08", + "j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "e145f0a2f6012768280c38655ca58065", + "j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "60c8b8817a197a13e4bb90903af612c5", + "j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "8265b7e4f79878af877bc6ecd9757efe", + "j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "accf46b76891d2954b893d0f91d82816", + "j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "e1f584f523336160d5c1104a61de77f3", + "j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "f6885b25901177f0357649afe97328cc", + "j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "fa057f221cbe4cf2442cd2fdb960743e", + "j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "7794ae812c64580e2ac8fc457d5cc85f", + "j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "adbf02eddb2090c008eb497d13ff84b9", + "j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "65bb10c84366c71498161734f953e93d", + "j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "6904b2918e5dc38d9a9f72d967eb74bf", + "j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json new file mode 100644 index 00000000..8e2db637 --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_full.json @@ -0,0 +1,42 @@ +{ + ".ytdl-sub-pz-download-archive.json": "ce0ef71efbe27d9f67d80b5fbc57fc84", + "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.mp4": "931a705864c57d21d6fedebed4af6bbc", + "Season 2010/s2010.e0813 - Oblivion Mod "Falcor" p.1.nfo": "67d8d71d048039080acbba3bce4febaa", + "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2-thumb.jpg": "8b32ee9c037fa669e444a0ac181525a1", + "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.mp4": "d3469b4dca7139cb3dbc38712b6796bf", + "Season 2010/s2010.e1202 - Oblivion Mod "Falcor" p.2.nfo": "d81f49cedbd7edaee987521e89b37904", + "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d", + "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc", + "Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "f7c0de89038f8c491bded8a3968720a2", + "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb", + "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d", + "Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "ee1eda78fa0980bc703e602b5012dd1f", + "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", + "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d", + "Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "61eb6369430da0ab6134d78829a7621b", + "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net)-thumb.jpg": "c956192a379b3661595c9920972d4819", + "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).mp4": "3d9c19835b03355d6fd5d00cd59dbe5b", + "Season 2011/s2011.e0529 - Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net).nfo": "60f72b99f5c69f9e03a071a12160928f", + "Season 2011/s2011.e0630 - Project Zombie |Fin|-thumb.jpg": "00ed383591779ffe98291de60f198fe9", + "Season 2011/s2011.e0630 - Project Zombie |Fin|.mp4": "4971cb2d4fa29460361031f3fa8e1ea9", + "Season 2011/s2011.e0630 - Project Zombie |Fin|.nfo": "a7b5d9e57d20852f5daf360a1373bb7a", + "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC]-thumb.jpg": "1718599d5189c65f7d8cf6acfa5ea851", + "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].mp4": "55e9b0add08c48c9c66105da0def2426", + "Season 2011/s2011.e1121 - Skyrim 'Ultra HD w⧸Mods' [PC].nfo": "fe60e2b6b564f9316b6c7c183e1cf300", + "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6", + "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.mp4": "65e4ce53ed5ec4139995469f99477a50", + "Season 2012/s2012.e0123 - Project Zombie |Map Trailer|.nfo": "c8900adcca83c473c79a4afbc7ad2de1", + "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|-thumb.jpg": "e29d49433175de8a761af35c5307791f", + "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.mp4": "18620a8257a686beda65e54add4d4cd1", + "Season 2013/s2013.e0719 - Project Zombie Rewind |Trailer|.nfo": "1c993c41d4308a6049333154d0adee16", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg": "6f8f5e1e031ec2a04b0a4906c04a19ee", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo": "cc7886aae3af6b7b0facd82f95390242", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "49cc64b25314155c1b8ab0361ac0c34f", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "2b3ccb3f1ef81ee49fe1afb88f275a09", + "fanart.jpg": "c16b8b88a82cbd47d217ee80f6a8b5f3", + "poster.jpg": "e92872ff94c96ad49e9579501c791578", + "tvshow.nfo": "83c7db96081ac5bdf289fcf396bec157" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_no_additional_downloads.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_no_additional_downloads.json new file mode 100644 index 00000000..c6756721 --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_no_additional_downloads.json @@ -0,0 +1,6 @@ +{ + ".ytdl-sub-pz-download-archive.json": "99914b932bd37a50b983c5e7c90ae93b", + "fanart.jpg": "c16b8b88a82cbd47d217ee80f6a8b5f3", + "poster.jpg": "e92872ff94c96ad49e9579501c791578", + "tvshow.nfo": "83c7db96081ac5bdf289fcf396bec157" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_recent.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_recent.json new file mode 100644 index 00000000..7acf32f8 --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_recent.json @@ -0,0 +1,12 @@ +{ + ".ytdl-sub-pz-download-archive.json": "523518e883758d9d89b656f9e9966efa", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg": "6f8f5e1e031ec2a04b0a4906c04a19ee", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc", + "Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo": "cc7886aae3af6b7b0facd82f95390242", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "49cc64b25314155c1b8ab0361ac0c34f", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "2b3ccb3f1ef81ee49fe1afb88f275a09", + "fanart.jpg": "c16b8b88a82cbd47d217ee80f6a8b5f3", + "poster.jpg": "e92872ff94c96ad49e9579501c791578", + "tvshow.nfo": "83c7db96081ac5bdf289fcf396bec157" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_rolling_recent.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_rolling_recent.json new file mode 100644 index 00000000..faf8fab2 --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_channel_rolling_recent.json @@ -0,0 +1,9 @@ +{ + ".ytdl-sub-pz-download-archive.json": "9639fffe58c44d084124c8398b46ef32", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg": "49cc64b25314155c1b8ab0361ac0c34f", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e", + "Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo": "2b3ccb3f1ef81ee49fe1afb88f275a09", + "fanart.jpg": "c16b8b88a82cbd47d217ee80f6a8b5f3", + "poster.jpg": "e92872ff94c96ad49e9579501c791578", + "tvshow.nfo": "83c7db96081ac5bdf289fcf396bec157" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json new file mode 100644 index 00000000..c77548fe --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_merge_playlist.json @@ -0,0 +1,5 @@ +{ + "JMC - Jesse's Minecraft Server-thumb.jpg": "a3f1910f9c51f6442f845a528e190829", + "JMC - Jesse's Minecraft Server.mkv": "f523ac968dd9dfbd1954cbca72ad4108", + "JMC - Jesse's Minecraft Server.nfo": "10df5dcdb65ab18ecf21b3503c77e48b" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json new file mode 100644 index 00000000..f1021c06 --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_playlist.json @@ -0,0 +1,12 @@ +{ + ".ytdl-sub-music_video_playlist_test-download-archive.json": "9f785c29194a6ecfba6a6b4018763ddc", + "JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d", + "JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc", + "JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "3d272fe58487b6011ad049b6000b046f", + "JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb", + "JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d", + "JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "6f99af10bef67276a507d1d9770c5e92", + "JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530", + "JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d", + "JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "beec3c1326654bd8c858cecf4e40977a" +} \ No newline at end of file diff --git a/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json b/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json new file mode 100644 index 00000000..4bd8de28 --- /dev/null +++ b/tests/e2e/resources/expected_downloads_summaries/youtube/test_split_video.json @@ -0,0 +1,20 @@ +{ + "Project Zombie - 1-6.Intro.mp4": "eaec6f50f364b13ef1a201e736ec9c05", + "Project Zombie - 2-6.Part 1.mp4": "5850b19acb250cc13db36f80fa1bba5a", + "Project Zombie - 3-6.Part 2.mp4": "445d95eba437db6df284df7e1ab633e8", + "Project Zombie - 4-6.Part 3.mp4": "2b6e7532d515c9e64ed2a33d850cf199", + "Project Zombie - 5-6.Part 4.mp4": "842bf3c4d1fcc4c5ab110635935dac66", + "Project Zombie - 6-6.Part 5.mp4": "238de99f00f829ab72f042b79da9a33a", + "Project Zombie - Intro-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Intro.nfo": "ded59ac906f579312cc3cf98a57e7ea3", + "Project Zombie - Part 1-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 1.nfo": "70ff5cd0092b8bc22dc4db93a824789b", + "Project Zombie - Part 2-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 2.nfo": "54450c18a2cbb9d6d2ee5d0a1fb3f279", + "Project Zombie - Part 3-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 3.nfo": "0effb13fc4039363a95969d1048dde57", + "Project Zombie - Part 4-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 4.nfo": "74bd0d7c12105469838768a0cc323a8c", + "Project Zombie - Part 5-thumb.jpg": "fb95b510681676e81c321171fc23143e", + "Project Zombie - Part 5.nfo": "a8cf2e77721335ea7c18e22734e7996c" +} \ No newline at end of file diff --git a/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_rolling_recent.txt b/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_rolling_recent.txt index 2e4d09e9..fefdde78 100644 --- a/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_rolling_recent.txt +++ b/tests/e2e/resources/transaction_log_summaries/youtube/test_channel_rolling_recent.txt @@ -10,6 +10,6 @@ tvshow.nfo Files removed from '{output_directory}' ---------------------------------------- -Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer-thumb.jpg -Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer.mp4 -Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer.nfo \ No newline at end of file +Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer-thumb.jpg +Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.mp4 +Season 2018/s2018.e1029 - Jesse's Minecraft Server | Teaser Trailer.nfo \ No newline at end of file diff --git a/tests/e2e/soundcloud/test_soundcloud_discography.py b/tests/e2e/soundcloud/test_soundcloud_discography.py index d1674e8d..0907441c 100644 --- a/tests/e2e/soundcloud/test_soundcloud_discography.py +++ b/tests/e2e/soundcloud/test_soundcloud_discography.py @@ -1,12 +1,7 @@ -from pathlib import Path - import pytest -from e2e.expected_download import ExpectedDownloadFile -from e2e.expected_download import ExpectedDownloads +from e2e.expected_download import assert_expected_downloads from e2e.expected_transaction_log import assert_transaction_log_matches -from ytdl_sub.config.config_file import ConfigFile -from ytdl_sub.config.preset import Preset from ytdl_sub.subscriptions.subscription import Subscription @@ -25,40 +20,6 @@ def subscription_dict(output_directory): } -@pytest.fixture -def expected_discography_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - # Download mapping - ExpectedDownloadFile(path=Path(".ytdl-sub-jb-download-archive.json"), md5="1a99156e9ece62539fb2608416a07200"), - - # Entry files (singles) - ExpectedDownloadFile(path=Path("j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3"), md5="bffbd558e12c6a9e029dc136a88342c4"), - ExpectedDownloadFile(path=Path("j_b/[2021] Baby Santana's Dorian Groove/folder.jpg"), md5="967892be44b8c47e1be73f055a7c6f08"), - - ExpectedDownloadFile(path=Path("j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3"), md5="038db58aebe2ba875b733932b42a94d6"), - ExpectedDownloadFile(path=Path("j_b/[2021] Purple Clouds/folder.jpg"), md5="967892be44b8c47e1be73f055a7c6f08"), - - # Entry files (albums) - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3"), md5="e145f0a2f6012768280c38655ca58065"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3"), md5="60c8b8817a197a13e4bb90903af612c5"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3"), md5="8265b7e4f79878af877bc6ecd9757efe"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3"), md5="accf46b76891d2954b893d0f91d82816"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3"), md5="e1f584f523336160d5c1104a61de77f3"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3"), md5="f6885b25901177f0357649afe97328cc"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3"), md5="fa057f221cbe4cf2442cd2fdb960743e"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3"), md5="7794ae812c64580e2ac8fc457d5cc85f"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/09 - Finding Home.mp3"), md5="adbf02eddb2090c008eb497d13ff84b9"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3"), md5="65bb10c84366c71498161734f953e93d"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/11 - Untold History.mp3"), md5="6904b2918e5dc38d9a9f72d967eb74bf"), - ExpectedDownloadFile(path=Path("j_b/[2022] Acoustic Treats/folder.jpg"), md5="967892be44b8c47e1be73f055a7c6f08"), - ] - ) - # fmt: on - - class TestSoundcloudDiscography: """ Downloads my (bad) SC recordings I made. Ensure the above files exist and have the @@ -70,7 +31,6 @@ class TestSoundcloudDiscography: self, subscription_dict, soundcloud_discography_config, - expected_discography_download, output_directory, dry_run, ): @@ -85,5 +45,8 @@ class TestSoundcloudDiscography: transaction_log=transaction_log, transaction_log_summary_file_name="soundcloud/test_soundcloud_discography.txt", ) - if not dry_run: - expected_discography_download.assert_files_exist(relative_directory=output_directory) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="soundcloud/test_soundcloud_discography.json", + ) diff --git a/tests/e2e/youtube/test_channel.py b/tests/e2e/youtube/test_channel.py index 7499871e..f7a1fa11 100644 --- a/tests/e2e/youtube/test_channel.py +++ b/tests/e2e/youtube/test_channel.py @@ -1,12 +1,10 @@ import copy -from pathlib import Path from typing import Dict import mergedeep import pytest from conftest import assert_debug_log -from e2e.expected_download import ExpectedDownloadFile -from e2e.expected_download import ExpectedDownloads +from e2e.expected_download import assert_expected_downloads from e2e.expected_transaction_log import assert_transaction_log_matches import ytdl_sub.downloaders.downloader @@ -45,77 +43,6 @@ def channel_subscription_generator(channel_as_tv_show_config, subscription_name) return _channel_subscription_generator -#################################################################################################### -# FULL CHANNEL FIXTURES - - -@pytest.fixture -def expected_full_channel_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - # Download mapping - ExpectedDownloadFile(path=Path(".ytdl-sub-pz-download-archive.json"), md5="dd3c6236a107a665b884f701b8d14d4d"), - - # Output directory files - ExpectedDownloadFile(path=Path("fanart.jpg"), md5="c16b8b88a82cbd47d217ee80f6a8b5f3"), - ExpectedDownloadFile(path=Path("poster.jpg"), md5="e92872ff94c96ad49e9579501c791578"), - ExpectedDownloadFile(path=Path("tvshow.nfo"), md5="83c7db96081ac5bdf289fcf396bec157"), - - # Entry files - ExpectedDownloadFile(path=Path("Season 2010/s2010.e0813 - Oblivion Mod 'Falcor' p.1-thumb.jpg"), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path("Season 2010/s2010.e0813 - Oblivion Mod 'Falcor' p.1.mp4"), md5="931a705864c57d21d6fedebed4af6bbc"), - ExpectedDownloadFile(path=Path("Season 2010/s2010.e0813 - Oblivion Mod 'Falcor' p.1.nfo"), md5="67d8d71d048039080acbba3bce4febaa"), - - ExpectedDownloadFile(path=Path("Season 2010/s2010.e1202 - Oblivion Mod 'Falcor' p.2-thumb.jpg"), md5="8b32ee9c037fa669e444a0ac181525a1"), - ExpectedDownloadFile(path=Path("Season 2010/s2010.e1202 - Oblivion Mod 'Falcor' p.2.mp4"), md5="d3469b4dca7139cb3dbc38712b6796bf"), - ExpectedDownloadFile(path=Path("Season 2010/s2010.e1202 - Oblivion Mod 'Falcor' p.2.nfo"), md5="d81f49cedbd7edaee987521e89b37904"), - - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg"), md5="b232d253df621aa770b780c1301d364d"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4"), md5="e66287b9832277b6a4d1554e29d9fdcc"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo"), md5="f7c0de89038f8c491bded8a3968720a2"), - - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg"), md5="d17c379ea8b362f5b97c6b213b0342cb"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4"), md5="04ab5cb3cc12325d0c96a7cd04a8b91d"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo"), md5="ee1eda78fa0980bc703e602b5012dd1f"), - - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg"), md5="e7830aa8a64b0cde65ba3f7e5fc56530"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4"), md5="025de6099a5c98e6397153c7a62d517d"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo"), md5="61eb6369430da0ab6134d78829a7621b"), - - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0529 - Project Zombie _Official Trailer_ (IP - mc.projectzombie.beastnode.net)-thumb.jpg"), md5="c956192a379b3661595c9920972d4819"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0529 - Project Zombie _Official Trailer_ (IP - mc.projectzombie.beastnode.net).mp4"), md5="3d9c19835b03355d6fd5d00cd59dbe5b"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0529 - Project Zombie _Official Trailer_ (IP - mc.projectzombie.beastnode.net).nfo"), md5="60f72b99f5c69f9e03a071a12160928f"), - - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0630 - Project Zombie _Fin-thumb.jpg"), md5="00ed383591779ffe98291de60f198fe9"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0630 - Project Zombie _Fin.mp4"), md5="4971cb2d4fa29460361031f3fa8e1ea9"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e0630 - Project Zombie _Fin.nfo"), md5="a7b5d9e57d20852f5daf360a1373bb7a"), - - ExpectedDownloadFile(path=Path("Season 2011/s2011.e1121 - Skyrim 'Ultra HD w_Mods' [PC]-thumb.jpg"), md5="1718599d5189c65f7d8cf6acfa5ea851"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e1121 - Skyrim 'Ultra HD w_Mods' [PC].mp4"), md5="55e9b0add08c48c9c66105da0def2426"), - ExpectedDownloadFile(path=Path("Season 2011/s2011.e1121 - Skyrim 'Ultra HD w_Mods' [PC].nfo"), md5="fe60e2b6b564f9316b6c7c183e1cf300"), - - ExpectedDownloadFile(path=Path("Season 2012/s2012.e0123 - Project Zombie _Map Trailer-thumb.jpg"), md5="54ebe9df801b278fdd17b21afa8373a6"), - ExpectedDownloadFile(path=Path("Season 2012/s2012.e0123 - Project Zombie _Map Trailer.mp4"), md5="65e4ce53ed5ec4139995469f99477a50"), - ExpectedDownloadFile(path=Path("Season 2012/s2012.e0123 - Project Zombie _Map Trailer.nfo"), md5="c8900adcca83c473c79a4afbc7ad2de1"), - - ExpectedDownloadFile(path=Path("Season 2013/s2013.e0719 - Project Zombie Rewind _Trailer-thumb.jpg"), md5="e29d49433175de8a761af35c5307791f"), - ExpectedDownloadFile(path=Path("Season 2013/s2013.e0719 - Project Zombie Rewind _Trailer.mp4"), md5="18620a8257a686beda65e54add4d4cd1"), - ExpectedDownloadFile(path=Path("Season 2013/s2013.e0719 - Project Zombie Rewind _Trailer.nfo"), md5="1c993c41d4308a6049333154d0adee16"), - - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer-thumb.jpg"), md5="6f8f5e1e031ec2a04b0a4906c04a19ee"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer.mp4"), md5="82f6ee7253e1dbb83ae7215af08ffacc"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer.nfo"), md5="cc7886aae3af6b7b0facd82f95390242"), - - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id-thumb.jpg"), md5="49cc64b25314155c1b8ab0361ac0c34f"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.mp4"), md5="e733b4cc385b953b08c8eb0f47e03c1e"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server | IP mc.jesse.id.nfo"), md5="2b3ccb3f1ef81ee49fe1afb88f275a09"), - ] - ) - # fmt: on - - #################################################################################################### # RECENT CHANNEL FIXTURES @pytest.fixture @@ -132,55 +59,6 @@ def recent_channel_preset_dict(channel_preset_dict): ) -@pytest.fixture -def expected_recent_channel_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - # Download mapping - ExpectedDownloadFile(path=Path(".ytdl-sub-pz-download-archive.json"), md5="91534d1c5921d121aa35d7a197ba1940"), - - # Output directory files - ExpectedDownloadFile(path=Path("fanart.jpg"), md5="c16b8b88a82cbd47d217ee80f6a8b5f3"), - ExpectedDownloadFile(path=Path("poster.jpg"), md5="e92872ff94c96ad49e9579501c791578"), - ExpectedDownloadFile(path=Path("tvshow.nfo"), md5="83c7db96081ac5bdf289fcf396bec157"), - - # Recent Entry files - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer-thumb.jpg"), md5="6f8f5e1e031ec2a04b0a4906c04a19ee"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer.mp4"), md5="82f6ee7253e1dbb83ae7215af08ffacc"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1029 - Jesse's Minecraft Server _ Teaser Trailer.nfo"), md5="cc7886aae3af6b7b0facd82f95390242"), - - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server _ IP mc.jesse.id-thumb.jpg"), md5="49cc64b25314155c1b8ab0361ac0c34f"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server _ IP mc.jesse.id.mp4"), md5="e733b4cc385b953b08c8eb0f47e03c1e"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server _ IP mc.jesse.id.nfo"), md5="2b3ccb3f1ef81ee49fe1afb88f275a09"), - ] - ) - # fmt: on - - -#################################################################################################### -# RECENT CHANNEL FIXTURES -- NO VIDS IN RANGE - - -@pytest.fixture -def expected_recent_channel_no_vids_in_range_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - # Download mapping - ExpectedDownloadFile(path=Path(".ytdl-sub-pz-download-archive.json"), md5="99914b932bd37a50b983c5e7c90ae93b"), - - # Output directory files - ExpectedDownloadFile(path=Path("fanart.jpg"), md5="c16b8b88a82cbd47d217ee80f6a8b5f3"), - ExpectedDownloadFile(path=Path("poster.jpg"), md5="e92872ff94c96ad49e9579501c791578"), - ExpectedDownloadFile(path=Path("tvshow.nfo"), md5="83c7db96081ac5bdf289fcf396bec157"), - ] - ) - # fmt: on - - #################################################################################################### # ROLLING RECENT CHANNEL FIXTURES @pytest.fixture @@ -195,29 +73,6 @@ def rolling_recent_channel_preset_dict(recent_channel_preset_dict): ) -@pytest.fixture -def expected_rolling_recent_channel_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - # Download mapping - ExpectedDownloadFile(path=Path(".ytdl-sub-pz-download-archive.json"), md5="97ff47a7c5d89a426a653493ad1a3f06"), - - # Output directory files - ExpectedDownloadFile(path=Path("fanart.jpg"), md5="c16b8b88a82cbd47d217ee80f6a8b5f3"), - ExpectedDownloadFile(path=Path("poster.jpg"), md5="e92872ff94c96ad49e9579501c791578"), - ExpectedDownloadFile(path=Path("tvshow.nfo"), md5="83c7db96081ac5bdf289fcf396bec157"), - - # Rolling Recent Entry files - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server _ IP mc.jesse.id-thumb.jpg"), md5="49cc64b25314155c1b8ab0361ac0c34f"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server _ IP mc.jesse.id.mp4"), md5="e733b4cc385b953b08c8eb0f47e03c1e"), - ExpectedDownloadFile(path=Path("Season 2018/s2018.e1102 - Jesse's Minecraft Server _ IP mc.jesse.id.nfo"), md5="2b3ccb3f1ef81ee49fe1afb88f275a09"), - ] - ) - # fmt: on - - class TestChannelAsKodiTvShow: """ Downloads my old minecraft youtube channel. Ensure the above files exist and have the @@ -240,8 +95,11 @@ class TestChannelAsKodiTvShow: transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_channel_full.txt", ) - if not dry_run: - expected_full_channel_download.assert_files_exist(relative_directory=output_directory) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_channel_full.json", + ) @pytest.mark.parametrize("dry_run", [True, False]) def test_recent_channel_download( @@ -262,9 +120,12 @@ class TestChannelAsKodiTvShow: transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_channel_recent.txt", ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_channel_recent.json", + ) if not dry_run: - expected_recent_channel_download.assert_files_exist(relative_directory=output_directory) - # try downloading again, ensure nothing more was downloaded with assert_debug_log( logger=ytdl_sub.downloaders.downloader.download_logger, @@ -278,8 +139,10 @@ class TestChannelAsKodiTvShow: "youtube/test_channel_no_additional_downloads.txt" ), ) - expected_recent_channel_download.assert_files_exist( - relative_directory=output_directory + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_channel_recent.json", ) @pytest.mark.parametrize("dry_run", [True, False]) @@ -287,7 +150,6 @@ class TestChannelAsKodiTvShow: self, channel_subscription_generator, recent_channel_preset_dict, - expected_recent_channel_no_vids_in_range_download, output_directory, dry_run, ): @@ -304,10 +166,11 @@ class TestChannelAsKodiTvShow: transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_channel_no_additional_downloads.txt", ) - if not dry_run: - expected_recent_channel_no_vids_in_range_download.assert_files_exist( - relative_directory=output_directory - ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_channel_no_additional_downloads.json", + ) @pytest.mark.parametrize("dry_run", [True, False]) def test_rolling_recent_channel_download( @@ -315,8 +178,6 @@ class TestChannelAsKodiTvShow: channel_subscription_generator, recent_channel_preset_dict, rolling_recent_channel_preset_dict, - expected_recent_channel_download, - expected_rolling_recent_channel_download, output_directory, dry_run, ): @@ -333,14 +194,18 @@ class TestChannelAsKodiTvShow: logger=ytdl_sub.downloaders.downloader.download_logger, expected_message="RejectedVideoReached, stopping additional downloads", ): - transaction_log = recent_channel_subscription.download() + transaction_log = recent_channel_subscription.download(dry_run=False) - expected_recent_channel_download.assert_files_exist(relative_directory=output_directory) assert_transaction_log_matches( output_directory=output_directory, transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_channel_recent.txt", ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name="youtube/test_channel_recent.json", + ) # Then, download the rolling recent vids subscription. This should remove one of the # two videos @@ -350,16 +215,22 @@ class TestChannelAsKodiTvShow: ): transaction_log = rolling_recent_channel_subscription.download(dry_run=dry_run) + expected_downloads_summary = ( + "youtube/test_channel_recent.json" + if dry_run + else "youtube/test_channel_rolling_recent.json" + ) + assert_transaction_log_matches( output_directory=output_directory, transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_channel_rolling_recent.txt", - regenerate_transaction_log=True, ) - if not dry_run: - expected_rolling_recent_channel_download.assert_files_exist( - relative_directory=output_directory - ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name=expected_downloads_summary, + ) # Invoke the rolling download again, ensure downloading stopped early from it already # existing @@ -375,6 +246,8 @@ class TestChannelAsKodiTvShow: transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_channel_no_additional_downloads.txt", ) - expected_rolling_recent_channel_download.assert_files_exist( - relative_directory=output_directory + assert_expected_downloads( + output_directory=output_directory, + dry_run=False, + expected_download_summary_file_name=expected_downloads_summary, ) diff --git a/tests/e2e/youtube/test_merge_playlist.py b/tests/e2e/youtube/test_merge_playlist.py index 0792855e..6d88533f 100644 --- a/tests/e2e/youtube/test_merge_playlist.py +++ b/tests/e2e/youtube/test_merge_playlist.py @@ -1,8 +1,5 @@ -from pathlib import Path - import pytest -from e2e.expected_download import ExpectedDownloadFile -from e2e.expected_download import ExpectedDownloads +from e2e.expected_download import assert_expected_downloads from e2e.expected_transaction_log import assert_transaction_log_matches from ytdl_sub.config.config_file import ConfigFile @@ -63,17 +60,17 @@ def playlist_subscription(config, subscription_name, subscription_dict): ) -@pytest.fixture -def expected_playlist_download(): - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server-thumb.jpg"), md5="a3f1910f9c51f6442f845a528e190829"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server.mkv")), # not bitexact TODO: check size - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server.nfo"), md5="10df5dcdb65ab18ecf21b3503c77e48b"), - ] - ) - # fmt: on +# @pytest.fixture +# def expected_playlist_download(): +# # fmt: off +# return ExpectedDownloads( +# expected_downloads=[ +# ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server-thumb.jpg"), md5="a3f1910f9c51f6442f845a528e190829"), +# ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server.mkv")), # not bitexact TODO: check size +# ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server.nfo"), md5="10df5dcdb65ab18ecf21b3503c77e48b"), +# ] +# ) +# # fmt: on class TestYoutubeMergePlaylist: @@ -83,15 +80,16 @@ class TestYoutubeMergePlaylist: """ @pytest.mark.parametrize("dry_run", [True, False]) - def test_merge_playlist_download( - self, playlist_subscription, expected_playlist_download, output_directory, dry_run - ): + def test_merge_playlist_download(self, playlist_subscription, output_directory, dry_run): transaction_log = playlist_subscription.download(dry_run=dry_run) assert_transaction_log_matches( output_directory=output_directory, transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_merge_playlist.txt", ) - - if not dry_run: - expected_playlist_download.assert_files_exist(relative_directory=output_directory) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + ignore_md5_hashes_for=["JMC - Jesse's Minecraft Server.mkv"], # TODO, better test here + expected_download_summary_file_name="youtube/test_merge_playlist.json", + ) diff --git a/tests/e2e/youtube/test_playlist.py b/tests/e2e/youtube/test_playlist.py index e3e27b7a..77c020a8 100644 --- a/tests/e2e/youtube/test_playlist.py +++ b/tests/e2e/youtube/test_playlist.py @@ -1,10 +1,7 @@ -from pathlib import Path - import pytest from conftest import assert_debug_log from e2e.conftest import mock_run_from_cli -from e2e.expected_download import ExpectedDownloadFile -from e2e.expected_download import ExpectedDownloads +from e2e.expected_download import assert_expected_downloads from e2e.expected_transaction_log import assert_transaction_log_matches import ytdl_sub.downloaders.downloader @@ -26,32 +23,6 @@ def playlist_preset_dict(output_directory): } -@pytest.fixture -def expected_playlist_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - # Download mapping - ExpectedDownloadFile(path=Path(".ytdl-sub-music_video_playlist_test-download-archive.json"), md5="9f785c29194a6ecfba6a6b4018763ddc"), - - # Entry files - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg"), md5="b232d253df621aa770b780c1301d364d"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4"), md5="e66287b9832277b6a4d1554e29d9fdcc"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo"), md5="3d272fe58487b6011ad049b6000b046f"), - - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg"), md5="d17c379ea8b362f5b97c6b213b0342cb"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4"), md5="04ab5cb3cc12325d0c96a7cd04a8b91d"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo"), md5="6f99af10bef67276a507d1d9770c5e92"), - - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg"), md5="e7830aa8a64b0cde65ba3f7e5fc56530"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4"), md5="025de6099a5c98e6397153c7a62d517d"), - ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo"), md5="beec3c1326654bd8c858cecf4e40977a"), - ] - ) - # fmt: on - - class TestPlaylistAsKodiMusicVideo: """ Downloads my old minecraft youtube channel, pretends they are music videos. Ensure the above @@ -63,7 +34,6 @@ class TestPlaylistAsKodiMusicVideo: self, music_video_config, playlist_preset_dict, - expected_playlist_download, output_directory, dry_run, ): @@ -73,24 +43,32 @@ class TestPlaylistAsKodiMusicVideo: preset_dict=playlist_preset_dict, ) - transaction_log = playlist_subscription.download() + transaction_log = playlist_subscription.download(dry_run=dry_run) assert_transaction_log_matches( output_directory=output_directory, transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_playlist.txt", ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_playlist.json", + ) + # Ensure another invocation will hit ExistingVideoReached if not dry_run: - expected_playlist_download.assert_files_exist(relative_directory=output_directory) - - # Ensure another invocation will hit ExistingVideoReached with assert_debug_log( logger=ytdl_sub.downloaders.downloader.download_logger, expected_message="ExistingVideoReached, stopping additional downloads", ): transaction_log = playlist_subscription.download() - expected_playlist_download.assert_files_exist(relative_directory=output_directory) - assert transaction_log.is_empty + + assert transaction_log.is_empty + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_playlist.json", + ) @pytest.mark.parametrize("dry_run", [True, False]) def test_playlist_download_from_cli_sub( @@ -98,7 +76,6 @@ class TestPlaylistAsKodiMusicVideo: preset_dict_to_subscription_yaml_generator, music_video_config_path, playlist_preset_dict, - expected_playlist_download, output_directory, dry_run, ): @@ -118,17 +95,23 @@ class TestPlaylistAsKodiMusicVideo: transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_playlist.txt", ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_playlist.json", + ) if not dry_run: - expected_playlist_download.assert_files_exist(relative_directory=output_directory) - # Ensure another invocation will hit ExistingVideoReached with assert_debug_log( logger=ytdl_sub.downloaders.downloader.download_logger, expected_message="ExistingVideoReached, stopping additional downloads", ): transaction_log = mock_run_from_cli(args=args)[0][1] - expected_playlist_download.assert_files_exist( - relative_directory=output_directory - ) - assert transaction_log.is_empty + + assert transaction_log.is_empty + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_playlist.json", + ) diff --git a/tests/e2e/youtube/test_split_video.py b/tests/e2e/youtube/test_split_video.py index 86255cb1..6d1f75d8 100644 --- a/tests/e2e/youtube/test_split_video.py +++ b/tests/e2e/youtube/test_split_video.py @@ -1,9 +1,5 @@ -from pathlib import Path -from tempfile import NamedTemporaryFile - import pytest -from e2e.expected_download import ExpectedDownloadFile -from e2e.expected_download import ExpectedDownloads +from e2e.expected_download import assert_expected_downloads from e2e.expected_transaction_log import assert_transaction_log_matches from ytdl_sub.config.preset import Preset @@ -50,35 +46,6 @@ def single_video_subscription(music_video_config, subscription_dict): ) -@pytest.fixture -def expected_single_video_download(): - # turn off black formatter here for readability - # fmt: off - return ExpectedDownloads( - expected_downloads=[ - ExpectedDownloadFile(path=Path('Project Zombie - 1-6.Intro.mp4'), md5="eaec6f50f364b13ef1a201e736ec9c05"), - ExpectedDownloadFile(path=Path('Project Zombie - 2-6.Part 1.mp4'), md5="5850b19acb250cc13db36f80fa1bba5a"), - ExpectedDownloadFile(path=Path('Project Zombie - 3-6.Part 2.mp4'), md5="445d95eba437db6df284df7e1ab633e8"), - ExpectedDownloadFile(path=Path('Project Zombie - 4-6.Part 3.mp4'), md5="2b6e7532d515c9e64ed2a33d850cf199"), - ExpectedDownloadFile(path=Path('Project Zombie - 5-6.Part 4.mp4'), md5="842bf3c4d1fcc4c5ab110635935dac66"), - ExpectedDownloadFile(path=Path('Project Zombie - 6-6.Part 5.mp4'), md5="238de99f00f829ab72f042b79da9a33a"), - ExpectedDownloadFile(path=Path('Project Zombie - Intro-thumb.jpg'), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path('Project Zombie - Intro.nfo'), md5="ded59ac906f579312cc3cf98a57e7ea3"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 1-thumb.jpg'), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 1.nfo'), md5="70ff5cd0092b8bc22dc4db93a824789b"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 2-thumb.jpg'), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 2.nfo'), md5="54450c18a2cbb9d6d2ee5d0a1fb3f279"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 3-thumb.jpg'), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 3.nfo'), md5="0effb13fc4039363a95969d1048dde57"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 4-thumb.jpg'), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 4.nfo'), md5="74bd0d7c12105469838768a0cc323a8c"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 5-thumb.jpg'), md5="fb95b510681676e81c321171fc23143e"), - ExpectedDownloadFile(path=Path('Project Zombie - Part 5.nfo'), md5="a8cf2e77721335ea7c18e22734e7996c"), - ] - ) - # fmt: on - - class TestPlaylistAsKodiMusicVideo: """ Downloads my old minecraft youtube channel, pretends they are music videos. Ensure the above @@ -86,15 +53,15 @@ class TestPlaylistAsKodiMusicVideo: """ @pytest.mark.parametrize("dry_run", [True, False]) - def test_split_video_download( - self, single_video_subscription, expected_single_video_download, output_directory, dry_run - ): - transaction_log = single_video_subscription.download() + def test_split_video_download(self, single_video_subscription, output_directory, dry_run): + transaction_log = single_video_subscription.download(dry_run=dry_run) assert_transaction_log_matches( output_directory=output_directory, transaction_log=transaction_log, transaction_log_summary_file_name="youtube/test_split_video.txt", ) - - if not dry_run: - expected_single_video_download.assert_files_exist(relative_directory=output_directory) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="youtube/test_split_video.json", + ) diff --git a/tests/e2e/youtube/test_video.py b/tests/e2e/youtube/test_video.py index df468b3c..ef43181e 100644 --- a/tests/e2e/youtube/test_video.py +++ b/tests/e2e/youtube/test_video.py @@ -51,7 +51,7 @@ class TestYoutubeVideo: assert_expected_downloads( output_directory=output_directory, dry_run=dry_run, - expected_download_summary_file_name="youtube/test_video.json" + expected_download_summary_file_name="youtube/test_video.json", ) @pytest.mark.parametrize("dry_run", [True, False]) @@ -79,7 +79,7 @@ class TestYoutubeVideo: assert_expected_downloads( output_directory=output_directory, dry_run=dry_run, - expected_download_summary_file_name="youtube/test_video.json" + expected_download_summary_file_name="youtube/test_video.json", ) @pytest.mark.parametrize("dry_run", [True, False]) @@ -107,5 +107,5 @@ class TestYoutubeVideo: assert_expected_downloads( output_directory=output_directory, dry_run=dry_run, - expected_download_summary_file_name="youtube/test_video_with_chapter_timestamps.json" + expected_download_summary_file_name="youtube/test_video_with_chapter_timestamps.json", )