aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_enrich_audio.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-24 19:46:06 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-24 19:46:06 +0200
commit62253b9592a83ce152d0c64471e20514218fb132 (patch)
treed41b84661da3252045937f5a90dc45ca7b029edc /packages/meshbay-node/tests/test_enrich_audio.py
parentd053d083627f1f9f010752f8ad67941e22d49f27 (diff)
downloadmeshbay-62253b9592a83ce152d0c64471e20514218fb132.tar.gz
feat(hub): consolidate loose tracks, "&"/"and" fold, player close/queue
Album-grid readability, part two: - groupMusicEntries (music-app.js): an album bucket left with exactly one track - a real album tag, but only one song from it, not the whole release - clutters the grid the same way an untagged loose track does. Both kinds now fold into one "<artist> - Various" tile per artist, unless there is only one leftover track overall, where relabeling buys nothing and the track keeps its own name (or the generic placeholder, if it never had one). - foldKey also normalizes "&" vs "and" ("Artist & The Band" / "Artist and The Band" is one act, tagged both ways across different rips of the same catalogue) alongside the existing case/whitespace fold. - music-player.js: a close button pauses and tears the player down; an unmount cleanup effect (pause, revoke every cached blob URL) fires either way, whether that's the close button or the shell tearing the bar down on its own. A "current queue" button opens an overlay listing the whole playing queue with the current track highlighted, click any to jump to it - works identically regardless of how the queue was built (an album, the consolidated misc bucket, a single standalone track), since it only ever reads the player's own live tracks/order/pos. - group-page.js: this component is not remounted when switching to a *different* group on the same /group/:id route (only the groupId prop changes) - so without an explicit reset, music from one group would carry into the next one opened. Resets musicQueue to null on groupId change; a tab switch inside one group still leaves it alone. - Scrubbed real artist/band names that had leaked into code comments and test fixtures (enrich_audio.py's docstrings, several test_enrich_audio.py assertions, a music-app.js comment) - replaced with generic placeholders, no behavioural change. - i18n: music.various, music.player_close, music.player_queue, music.queue_title added across all ten locales. Client-side only except none of this touches the node at all. npm run sync-ui re-run. Full suite: 1129 passed, no regressions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KBi7ALLGfwcjBXt57yNMcy
Diffstat (limited to 'packages/meshbay-node/tests/test_enrich_audio.py')
-rw-r--r--packages/meshbay-node/tests/test_enrich_audio.py39
1 files changed, 20 insertions, 19 deletions
diff --git a/packages/meshbay-node/tests/test_enrich_audio.py b/packages/meshbay-node/tests/test_enrich_audio.py
index 221f1c6..0fd8e17 100644
--- a/packages/meshbay-node/tests/test_enrich_audio.py
+++ b/packages/meshbay-node/tests/test_enrich_audio.py
@@ -68,18 +68,18 @@ def test_artist_album_from_ancestors_refuses_to_name_the_root_as_artist(tmp_path
The regression this whole revision exists for: a flat `Artist/track.mp3`
layout (no album subfolder) used to read the *root's own directory
name* as the artist, because the walk always climbed two levels with no
- idea where the root was. Measured live: 289 tracks across 41 real,
- unrelated artists collapsed into one fake "artist" this way — the
+ idea where the root was. Measured live against a real library: dozens
+ of unrelated artists collapsed into one fake "artist" this way — the
single biggest bucket in the whole library.
"""
- folder = tmp_path / "Ben Harper"
+ folder = tmp_path / "Some Flat Artist"
folder.mkdir(parents=True)
- track = folder / "Ashes.mp3"
+ track = folder / "A Track.mp3"
track.touch()
artist, album = _artist_album_from_ancestors(track, tmp_path)
- assert artist == "Ben Harper"
+ assert artist == "Some Flat Artist"
assert album is None, "no album folder exists — must not invent one, or swap artist/album"
@@ -106,22 +106,22 @@ def test_artist_album_from_ancestors_without_a_root_keeps_the_old_two_level_beha
def test_split_top_level_folder_splits_artist_dash_album():
- artist, album = _split_top_level_folder("GHOST DOG - Soundtrack")
- assert artist == "GHOST DOG"
+ artist, album = _split_top_level_folder("Some Movie - Soundtrack")
+ assert artist == "Some Movie"
assert album == "Soundtrack"
def test_split_top_level_folder_with_no_separator_is_artist_only():
- artist, album = _split_top_level_folder("Ben Harper")
- assert artist == "Ben Harper"
+ artist, album = _split_top_level_folder("Some Flat Artist")
+ assert artist == "Some Flat Artist"
assert album is None
def test_split_top_level_folder_cleans_rip_tag_noise():
artist, album = _split_top_level_folder(
- "Sinsemilia - Premiere Recolte [MP3 320kbps Album]")
- assert artist == "Sinsemilia"
- assert album == "Premiere Recolte"
+ "Some Artist - Some Release [MP3 320kbps Album]")
+ assert artist == "Some Artist"
+ assert album == "Some Release"
def test_clean_tag_filters_known_placeholders():
@@ -139,16 +139,17 @@ def test_clean_tag_keeps_various_artists_as_a_real_credit():
def test_clean_tag_keeps_a_real_value():
- assert _clean_tag("Björk") == "Björk"
+ # Non-ASCII must not be mistaken for a placeholder pattern.
+ assert _clean_tag("Ünïqùé Ärtïst") == "Ünïqùé Ärtïst"
def test_strip_track_prefix_removes_a_leaked_filename_number():
- assert strip_track_prefix("01 - Venus As A Boy (Edited Lp Version)") == \
- "Venus As A Boy (Edited Lp Version)"
+ assert strip_track_prefix("01 - Some Track (Edited Version)") == \
+ "Some Track (Edited Version)"
def test_strip_track_prefix_is_a_noop_on_a_clean_title():
- assert strip_track_prefix("Venus As A Boy") == "Venus As A Boy"
+ assert strip_track_prefix("Some Track") == "Some Track"
# ── end-to-end against a real (tiny, synthetic) MP3 file ────────────────────
@@ -234,9 +235,9 @@ async def test_enricher_falls_back_to_filename_and_folder_when_tags_absent(tmp_p
@pytest.mark.asyncio
async def test_enricher_falls_back_to_artist_only_for_a_flat_top_level_dir(tmp_path, media_cache):
"""The real-world regression case, end to end through the whole pool."""
- folder = tmp_path / "Ben Harper"
+ folder = tmp_path / "Some Flat Artist"
folder.mkdir(parents=True)
- clip = folder / "Ashes.mp3"
+ clip = folder / "A Track.mp3"
_make_clip(clip) # no metadata tags at all
entry = IndexEntry(id="fileid3", name=clip.name,
path=str(clip.relative_to(tmp_path)),
@@ -251,7 +252,7 @@ async def test_enricher_falls_back_to_artist_only_for_a_flat_top_level_dir(tmp_p
enricher.spawn(entry, clip, on_done, tmp_path)
_, fields = await asyncio.wait_for(done, timeout=30)
- assert fields["artist"] == "Ben Harper"
+ assert fields["artist"] == "Some Flat Artist"
assert fields["album"] is None
assert fields["artist"] != tmp_path.name, \
"must never fall back to the shared root's own directory name"