diff --git a/tests/automation/test_handlers_playlist.py b/tests/automation/test_handlers_playlist.py index a690d7b6..e13179e3 100644 --- a/tests/automation/test_handlers_playlist.py +++ b/tests/automation/test_handlers_playlist.py @@ -738,6 +738,12 @@ class TestSyncPlaylist: import time time.sleep(0.01) assert len(sync_calls) == 1 + # #823 — the handler must NOT force a sync mode; it leaves it unset so + # _run_sync_task resolves the user's configured global mode (else the + # automated sync always 'replace'd and wiped the playlist image/desc). + args, kwargs = sync_calls[0] + assert kwargs.get('sync_mode') is None # not forced via kwarg + assert len(args) == 6 # no 7th positional sync_mode either def test_organize_by_playlist_passes_skip_wishlist_add(self): discovered_track = { diff --git a/tests/test_playlist_edit.py b/tests/test_playlist_edit.py index 8cc0e10d..66caae40 100644 --- a/tests/test_playlist_edit.py +++ b/tests/test_playlist_edit.py @@ -138,6 +138,15 @@ def test_normalize_keeps_reconcile_from_config(): assert normalize_sync_mode('', 'reconcile') == 'reconcile' +def test_normalize_keeps_append_from_config(): + # #823 — an AUTOMATED sync (mirrored auto-sync / Playlist Pipeline) passes no + # per-request mode, so it must resolve to the user's configured global mode + # instead of hardcoding 'replace' (which recreated the playlist + wiped its + # image/description). Default 'replace' users are unaffected. + assert normalize_sync_mode(None, 'append') == 'append' + assert normalize_sync_mode(None, 'replace') == 'replace' + + def test_normalize_request_overrides_config(): assert normalize_sync_mode('append', 'reconcile') == 'append' assert normalize_sync_mode('reconcile', 'replace') == 'reconcile' diff --git a/web_server.py b/web_server.py index b4c537a2..9e7bc148 100644 --- a/web_server.py +++ b/web_server.py @@ -24136,9 +24136,20 @@ def _run_sync_task( automation_id=None, profile_id=1, playlist_image_url='', - sync_mode='replace', + sync_mode=None, skip_wishlist_add=False, ): + # When a caller doesn't specify a mode — the mirrored auto-sync + Playlist + # Pipeline (auto_sync_playlist), iTunes-link sync, Wing It — honor the user's + # configured global "Playlist sync mode" instead of hardcoding 'replace'. + # Hardcoding replace meant every AUTOMATED sync recreated the server + # playlist, wiping its custom image + description even when the user chose + # Append/Reconcile (#823 carlosjfcasero). The global default is still + # 'replace', so default users are unaffected; only users who set + # Append/Reconcile get the change. (Mirrors _submit_sync_task.) + if sync_mode is None: + from core.sync.playlist_edit import normalize_sync_mode + sync_mode = normalize_sync_mode(None, config_manager.get('playlist_sync.mode', 'replace')) return _discovery_sync.run_sync_task( playlist_id, playlist_name, tracks_json, automation_id, profile_id, playlist_image_url, _build_sync_deps(),