soulsync/tests
Broque Thomas 7e1c4c26ec Reorganize: fix moved-count + status/total UX issues from PR #377 review
Four changes addressing kettui's PR #377 review comments:

1. **`_finalize_track` no longer over-counts on DB failure (🔴 bug).**
   The function previously bailed on DB-update failure but
   `_process_one_track` still incremented `summary['moved']`
   unconditionally — overstating how many tracks the UI knows are
   at their new locations. Fixed by:
   - `_finalize_track` now returns ``bool`` (True only when DB row
     was updated AND original was dealt with)
   - Caller checks the return; on False, records as a failed track
     with a clear message ("Track landed at new location but DB
     update failed — file is at both old and new paths until library
     scan re-indexes")
   - Existing `test_db_update_failure_leaves_original_in_place` now
     also asserts `moved == 0`, `failed == 1`, and that the error
     message names the cause

2. **`executeReorganize` toast no longer says "undefined tracks" (🐛
   bug).** `/reorganize` doesn't return `result.total` anymore (the
   track count is determined server-side after planning), so the
   "Reorganizing undefined tracks..." string was meaningless. Now uses
   `result.message` from the backend instead.

3. **`_pollReorganizeStatus` distinguishes completed from skipped
   (🟡 risk).** Backend now propagates the orchestrator's status
   (`completed` / `no_source_id` / `no_album` / `no_tracks` /
   `setup_failed` / `error`) into `_reorganize_state['result_status']`
   so the frontend can warn appropriately. Two new helpers:
   - `_classifyReorganizeOutcome(state)` — returns 'success' only
     when `result_status === 'completed'` AND `failed === 0`;
     'warning' otherwise
   - `_formatReorganizeResultMessage(state)` — returns a message
     specific to the outcome ("Reorganize skipped — album has no
     metadata source ID. Run enrichment first." for `no_source_id`,
     etc.)
   Zero-failure non-completed runs now show as warnings instead of
   green checkmarks.

4. **Bulk mode no longer counts skipped albums as succeeded (🟡
   risk).** `_executeReorganizeAll`'s loop was treating any HTTP
   200 response as success, ignoring the orchestrator's actual
   outcome for that album. Fixed by:
   - `_waitForReorganizeComplete()` now resolves with the final
     state object (was: void)
   - Loop checks `finalState.result_status === 'completed'` AND
     `finalState.failed === 0` before counting `succeeded++`;
     otherwise increments `skipped` (with a per-album warning
     toast) or `failed` accordingly
   - Final summary toast now reads
     "Reorganized N of M albums, K skipped, J failed" and only
     shows green when nothing was skipped or failed

All four addressed in a single commit because they form one
coherent UX-correctness fix — the bug bug (#1) and the count-
overstatement bug (#4) both made the user see "everything succeeded"
when reality was different. Together they make the UI honestly
reflect what actually happened.

Files:
- core/library_reorganize.py — `_finalize_track` returns bool,
  `_process_one_track` reads it
- web_server.py — `_reorganize_state['result_status']` populated
  from orchestrator's summary on success and on exception
- webui/static/library.js — `_classifyReorganizeOutcome` /
  `_formatReorganizeResultMessage` helpers, single-album +
  bulk-mode flows both consume them
- tests/test_library_reorganize_orchestrator.py — strengthened
  the existing DB-failure test to assert moved/failed counts

Credit: kettui — four PR #377 review comments named all of these
precisely with line numbers and severity.
2026-04-25 09:07:44 -07:00
..
conftest.py Remove emojis from all Python log and print statements 2026-04-11 21:11:02 -07:00
test_acoustid_scanner.py Fix null-pointer error in acoustid_scanner 2026-04-17 19:17:24 +03:00
test_album_completeness_job.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_artist_source_detail.py Extract _build_source_only_artist_detail into core/artist_source_detail.py 2026-04-23 08:09:29 -07:00
test_artist_source_lookup.py Make artist_name Optional in find_library_artist_for_source 2026-04-22 22:15:03 -07:00
test_auth_usage_throttle.py test: auth last_used_at write throttle 2026-04-19 15:22:24 -07:00
test_content_filter_regex.py Fix watchlist content filters: live false positives + auto-scan bypass 2026-04-21 19:16:25 -07:00
test_dashboard_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_downloads_pagination.py test: downloads endpoint pagination and filtering 2026-04-19 15:22:25 -07:00
test_enrichment_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_library_reorganize.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_library_reorganize_orchestrator.py Reorganize: fix moved-count + status/total UX issues from PR #377 review 2026-04-25 09:07:44 -07:00
test_listening_stats_batch_queries.py test: listening stats worker batched query paths 2026-04-19 15:22:25 -07:00
test_metadata_cache_batch_lookup.py test: metadata cache batch entity lookups 2026-04-19 15:22:24 -07:00
test_metadata_gap_filler.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_metadata_service_album_tracks.py Refactor album track lookup to use source priority 2026-04-20 21:29:46 +03:00
test_metadata_service_artist_image.py Fix test-order-dependent failures in new metadata_service tests 2026-04-21 11:39:56 -07:00
test_metadata_service_cache.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_metadata_service_discography.py Add regression tests for source-artist lookup + dedup_variants flag 2026-04-22 21:14:11 -07:00
test_metadata_service_musicmap.py Fix test-order-dependent failures in new metadata_service tests 2026-04-21 11:39:56 -07:00
test_missing_cover_art.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_musicbrainz_search.py MusicBrainz: Dedupe same-named homonyms in artist search results 2026-04-24 10:27:45 -07:00
test_repair_worker_album_fill.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_request_cleanup_timer.py test: api/request periodic cleanup timer 2026-04-19 15:22:25 -07:00
test_script_split_integrity.py Unify artist detail: route source artists to standalone page, retire inline Artists page 2026-04-22 17:00:52 -07:00
test_spa_deep_linking.py Rename Search page id from 'downloads' to 'search', bump to 2.43 2026-04-22 13:22:49 -07:00
test_sync_discovery_scan_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_tidal_search_shortening.py Reject Tidal streams that silently downgrade from the requested quality 2026-04-24 13:12:30 -07:00
test_tidal_stream_tier_verification.py Reject Tidal streams that silently downgrade from the requested quality 2026-04-24 13:12:30 -07:00
test_tool_progress_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_track_number_repair.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_track_search_single_query.py test: api_search_tracks single-query track search 2026-04-19 15:22:24 -07:00
test_unknown_artist_fixer.py Fix test using old deezer_track_id column name 2026-04-20 21:11:45 -07:00
test_watchlist_scanner_scan.py Fix date-dependent watchlist scanner tests failing on CI 2026-04-22 20:56:10 -07:00
test_websocket_client_transport.py Repoint websocket transport test to core.js after split 2026-04-22 11:30:39 -07:00
test_websocket_infrastructure.py Realign test file names 2026-04-17 21:25:01 +03:00
test_wishlist_pagination.py test: wishlist SQL pagination and category filter 2026-04-19 15:22:24 -07:00
test_worker_existing_id_marks_matched.py test: enrichment worker re-processing fix and migration backfill 2026-04-19 15:22:24 -07:00