From f4b293b0a00e5d4ce63aafbc517edd9289fa44f5 Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 23 Feb 2026 15:24:41 -0700 Subject: [PATCH] Fixing bug where editing video download could not save with collection_id. --- wrolpi/schema.py | 4 ++++ wrolpi/test/test_root_api.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/wrolpi/schema.py b/wrolpi/schema.py index ca4e7986..0dc3a636 100644 --- a/wrolpi/schema.py +++ b/wrolpi/schema.py @@ -218,7 +218,10 @@ class EchoResponse: class DownloadSettings: channel_id: Optional[int] = None channel_tag_name: List[str] = field(default_factory=list) + channel_url: Optional[str] = None + collection_id: Optional[int] = None depth: Optional[int] = None + destination: Optional[str] = None # Legacy support download_metadata_only: bool = False download_order: Optional[str] = None excluded_urls: Optional[str] = None @@ -226,6 +229,7 @@ class DownloadSettings: maximum_duration: Optional[int] = None minimum_duration: Optional[int] = None suffix: Optional[str] = None + tag_names: Optional[List[str]] = None # Legacy support title_exclude: Optional[str] = None title_include: Optional[str] = None video_count_limit: Optional[int] = None diff --git a/wrolpi/test/test_root_api.py b/wrolpi/test/test_root_api.py index 5f67610a..6718d865 100644 --- a/wrolpi/test/test_root_api.py +++ b/wrolpi/test/test_root_api.py @@ -428,6 +428,52 @@ async def test_download_crud(test_session, async_client, test_download_manager_c assert download_config['tag_names'] == [tag1.name, tag2.name] +@pytest.mark.asyncio +async def test_update_download_with_settings_collection_id(test_session, async_client, test_download_manager_config, + test_directory): + """Updating a download should accept collection_id and other legacy fields in settings. + + The frontend sends collection_id inside settings when editing a download, even though it's also at the top level. + This should not cause a validation error.""" + + async def dispatch_downloads(*a, **kw): + pass + + with mock.patch('wrolpi.downloader.DownloadManager.dispatch_downloads', dispatch_downloads): + # Create a recurring download first. + body = dict( + urls=['https://www.youtube.com/watch?v=r9pF8CdUbD0'], + frequency=86400, + downloader='video', + ) + request, response = await async_client.post('/api/download', content=json.dumps(body)) + assert response.status_code == HTTPStatus.CREATED + + download = test_session.query(Download).one() + + # Update the download with collection_id in settings (mimics frontend behavior). + # This is the exact payload from the bug report. + body = dict( + destination='', + downloader='video', + settings=dict( + video_format='mp4', + video_resolutions=['360p'], + collection_id=195, # This was causing ValidationError + parent_download_url='https://youtube.com/@cheimerdinger/videos', + channel_tag_name=None, + channel_url='https://youtube.com/@cheimerdinger', # Also stored in settings + destination='videos/test', # Legacy field + tag_names=['test'], # Legacy field + ), + tag_names=[], + urls=['https://www.youtube.com/watch?v=r9pF8CdUbD0'], + ) + request, response = await async_client.put(f'/api/download/{download.id}', json=body) + assert response.status_code == HTTPStatus.NO_CONTENT, \ + f'Expected NO_CONTENT but got {response.status_code}: {response.json}' + + @pytest.mark.asyncio async def test_get_downloaders(async_client): """A list of Downloaders the user can use can be gotten."""