feedBack/tests
ChrisBeWithYou 0e3522ccc3
Some checks are pending
ship-ci / ci (push) Waiting to run
feat(player): drum-part picker for multiple drum charts (re-land of #1021) (#1028)
* feat(player): drum-part picker for multiple drum charts (feedpak 1.17.0)

The last mile of the multiple-drum-parts feature: let a player CHOOSE which
drum chart plays. #1020 taught the loader + highway WS to carry several drum
parts (song_info.drum_parts + ?drum_part=<id> + a part_id echo on drum_tab);
this adds the host-chrome selector that drives it.

A "Drum part" <select> sits beside the arrangement switcher in the advanced
settings popover, shown only when a song has 2+ drum charts (drum_parts is
always present — empty for non-drum songs — so single-drum / no-drum songs
hide the row and nothing changes for them). Selecting a part re-streams that
part's tab over the highway WS, exactly like an arrangement switch.

- static/highway.js:
  - reconnect() gains a third `drumPart` arg → sets `?drum_part=<id>` on the WS
    URL (mirrors the existing `arrangement` param one line up). Empty/undefined
    → the primary part, i.e. byte-identical to today for any pack untouched.
  - song_info handler populates #drum-part-select from msg.drum_parts and
    shows/hides #v3-drum-part-row on `length > 1` (parallel to the #arr-select
    block right above it).
  - drum_tab handler carries msg.part_id onto hwState.drumTab (plugins can read
    bundle.drumTab.part_id) and reflects it as the picker's selected value, so
    the dropdown stays honest even when the server resolves an unknown/absent
    selection to the primary.
- static/app.js:
  - changeArrangement() gains an optional `drumPart`; at reconnect it forwards
    the explicit part, else preserves the current picker selection — so an
    ARRANGEMENT switch keeps the chosen drum part (parts are song-level).
  - new changeDrumPart(id) delegates to changeArrangement with the current
    arrangement held + the new part applied (a part switch is the same
    re-stream, so it reuses all the transition ceremony). Exported on window.
- static/v3/index.html: the #drum-part-select row (hidden by default).

No plugin change: the drum renderers just draw whatever drum_tab streams.

RUNTIME-VERIFIED (Playwright, the core player, a 2-drum pack + a no-drum pack):
10/10 — the picker populates with both parts and shows for the multi-drum song;
song_info.drum_parts reaches getSongInfo(); the primary is pre-selected;
selecting the 2nd part drives highway.reconnect with the id and the WS URL
carries `?drum_part=drums-2`; the picker then reflects the server's part_id
echo; a no-drum song hides the row; no page errors. ESLint 0 errors (the two
max-lines warnings are pre-existing on these files). No pytest touched (JS-only).
Stacked on #1020.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017xGPjDBF8NTwTK7VQvizix
Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>

* Update reconnect source contract test

---------

Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 15:35:08 +02:00
..
browser fix(plugins): restore window.esc for out-of-tree plugins (#986) 2026-07-16 12:06:52 +02:00
fixtures Remove unused binary test fixture; correct stale scan comments 2026-06-16 18:49:40 +01:00
js feat(player): drum-part picker for multiple drum charts (re-land of #1021) (#1028) 2026-07-21 15:35:08 +02:00
plugins fix(career): gig song selection — full-genre pool, working re-roll, and the venue pack loads (#976) 2026-07-15 10:50:55 +02:00
__init__.py Clean release snapshot 2026-06-16 18:47:13 +02:00
conftest.py refactor(server): carve the library scanner into lib/scan.py (R3b) (#901) 2026-07-12 01:26:02 +02:00
test_acoustid_match.py feat(enrichment): AcoustID audio-fingerprint identification (opt-in) (#759) 2026-07-05 00:17:43 +02:00
test_albums_view.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_appstate.py feat(server): add appstate.py, the router seam (R3) (#833) 2026-07-10 15:06:22 +02:00
test_art_candidates.py refactor(server): extract the album-art routes into routers/art.py (R3) (#862) 2026-07-11 11:56:53 +02:00
test_art_layer.py refactor(server): extract the album-art routes into routers/art.py (R3) (#862) 2026-07-11 11:56:53 +02:00
test_artist_alias.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_artist_page.py refactor(server): move the metadata-enrichment subsystem into lib/enrichment.py (R3) (#861) 2026-07-11 11:32:21 +02:00
test_artist_sort_title_order.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_audio_bundled.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_audio_effect_mappings.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_audio_local_path.py refactor(server): extract the media/file-serving routes into routers/media.py (R3) (#869) 2026-07-11 15:36:22 +02:00
test_audio.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_batch_user_meta.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_builtin_diagnostic_seed.py refactor(server): carve builtin-content seeding into lib/builtin_content.py (R3b) (#900) 2026-07-12 00:50:50 +02:00
test_builtin_starter_seed.py refactor(server): carve builtin-content seeding into lib/builtin_content.py (R3b) (#900) 2026-07-12 00:50:50 +02:00
test_collections_api.py refactor(server): extract library + collections routes + the provider registry (R3) (#866) 2026-07-11 14:56:12 +02:00
test_context_menu_api.py refactor(server): move the metadata-enrichment subsystem into lib/enrichment.py (R3) (#861) 2026-07-11 11:32:21 +02:00
test_correlation_id.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_curated_album.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_demo_mode.py fix(demo): the janitor re-entry guard actually works now (#902) (#909) 2026-07-12 11:30:53 +02:00
test_diagnostics_bundle.py fix(tests): isolate plugin routes modules + redact .feedpak filenames (#736) 2026-07-03 13:01:07 +02:00
test_diagnostics_hardware.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_diagnostics_redact.py fix(tests): isolate plugin routes modules + redact .feedpak filenames (#736) 2026-07-03 13:01:07 +02:00
test_dlc_junction.py fix(library): serve art/load for songs mounted through a library junction (#766) 2026-07-05 00:15:50 +02:00
test_drums_lib.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_enrichment_plumbing.py refactor(server): move the metadata-enrichment subsystem into lib/enrichment.py (R3) (#861) 2026-07-11 11:32:21 +02:00
test_env_compat.py refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
test_feedpak_extension.py perf(scan): skip full library re-stat when the tree is unchanged (#979) 2026-07-15 21:23:10 +02:00
test_field_overrides.py feat(library): effective genre falls back to MusicBrainz enrichment (#949) 2026-07-13 16:53:06 +02:00
test_gap_fill.py feat(v3 library): "Fix metadata" popup — per-song override + lock, cover picker, MusicBrainz + AcoustID (#777) 2026-07-05 21:09:38 +02:00
test_gp2midi.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_gp2notation.py fix: correctly import and notate multi-staff (piano/keys) tracks from GP8 (#692) 2026-07-02 08:40:20 +02:00
test_gp2rs_drums.py feat(drums): capture velocities alongside times in unmapped-percussion reporting (#808) 2026-07-07 23:58:49 +02:00
test_gp2rs_gpx.py fix(gpx): clamp partial final BCFS sector so GP6 .gpx import works (#749) 2026-07-05 00:20:31 +02:00
test_gp2rs_xml_encoding.py fix(gp2rs): write arrangement XML as UTF-8 so GP import survives non-ASCII metadata (#984) 2026-07-19 00:56:32 -05:00
test_gp2rs.py fix(gp2rs): write beat times at 6-decimal precision so imported tempo matches Guitar Pro (#819) 2026-07-10 13:12:10 +02:00
test_gp_audio_sync.py fix(gp8): confine registry asset matching to the declared directory (#1011) 2026-07-19 01:36:28 -05:00
test_gp_autosync_warp.py feat(gp_autosync): piecewise time-warp helpers + refine_sync onset pass (#787) 2026-07-05 20:08:19 +02:00
test_group_filter_law.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_highway_3d_routes.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_highway_ws_authors.py refactor(server): extract the highway WebSocket into routers/ws_highway.py (R3) (#844) 2026-07-10 21:12:54 +02:00
test_highway_ws_drum_parts.py feat(sloppak): load multiple drum parts (feedpak 1.17.0 drums-as-arrangements) (#1020) 2026-07-21 13:27:41 +02:00
test_highway_ws_instrument_routing.py refactor(server): extract the highway WebSocket into routers/ws_highway.py (R3) (#844) 2026-07-10 21:12:54 +02:00
test_highway_ws_notation.py refactor(server): extract the highway WebSocket into routers/ws_highway.py (R3) (#844) 2026-07-10 21:12:54 +02:00
test_library_filters.py feat(library): sort and badge by personal difficulty rating (#810) 2026-07-07 23:57:20 +02:00
test_library_keyset.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_library_providers.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_library_tuning_instrument.py fix(library): tuning filter answers for your instrument, not always guitar (#1003) 2026-07-19 00:04:30 -05:00
test_library_tuning_perspectives.py fix(library): tuning filter answers for your instrument, not always guitar (#1003) 2026-07-19 00:04:30 -05:00
test_lift_keys_notation.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_logging_setup.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_loops_concurrency.py fix(loops): take the DB lock for the count+insert and the list read (#840) 2026-07-10 19:16:01 +02:00
test_loose_traversal.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_loosefolder.py fix(library): tuning filter answers for your instrument, not always guitar (#1003) 2026-07-19 00:04:30 -05:00
test_lyrics_transcribe_remote.py fix: remote transcription posts to /transcribe, not /align (stem-splitter#17) (#959) 2026-07-14 01:58:24 -04:00
test_lyrics_transcribe.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_mb_enrichment.py refactor(server): move the metadata-enrichment subsystem into lib/enrichment.py (R3) (#861) 2026-07-11 11:32:21 +02:00
test_mb_match.py feat(enrichment): alias-aware scoring — auto-confirm non-Latin-primary artists (#772) 2026-07-05 01:11:38 +02:00
test_midi_import_drums.py feat(drums): capture velocities alongside times in unmapped-percussion reporting (#808) 2026-07-07 23:58:49 +02:00
test_midi_import.py fix(midi): guard non-positive division in the legacy inline tempo path (#805) 2026-07-07 10:27:45 +02:00
test_midi_tempo_map.py feat(midi): convert_midi_tempo_map — extract tempos, time signatures, beat grid (#796) 2026-07-07 10:27:17 +02:00
test_migrate_full_mix_stem.py fix(sloppak): the full mix is a stem — drop the invented original_audio key (#946) 2026-07-13 12:22:42 -04:00
test_minigames_routes.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_notation_lib.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_notation_lift.py feat(notation_lift): authored per-note hands steer the split — heuristic only guesses the rest (#992) 2026-07-19 00:40:08 -05:00
test_notation_to_notes.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_packaging.py fix(build): move appstate.py + routers/ under lib/ so the desktop app ships them (#836) 2026-07-10 17:16:34 +02:00
test_parse_arrangement.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_playlist_cover_errors.py fix(playlists): split cover decode (400) from persist (500), unique temp, existence re-check (#842) 2026-07-10 20:16:22 +02:00
test_playlists_api.py feat(playlists): flag songs that are not in your current tuning (#1009) 2026-07-19 00:10:53 -05:00
test_plugin_context_contract.py test(plugins): pin the plugin_context contract before carving server.py (R3b) (#898) 2026-07-12 00:29:48 +02:00
test_plugin_manifest_contract.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_plugin_runtime_idempotence.py refactor(app): carve the JUCE/desktop audio shims out of app.js (R3a) (#893) 2026-07-11 22:44:03 +02:00
test_plugin_src_route.py fix(plugins): make a module plugin actually re-evaluate on reload (#879) (#897) 2026-07-12 00:19:59 +02:00
test_plugins.py test(plugins): pin the plugin_context contract before carving server.py (R3b) (#898) 2026-07-12 00:29:48 +02:00
test_practice_suggestions.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_profile_api.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_profile_domains.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_progression_api.py refactor(server): carve builtin-content seeding into lib/builtin_content.py (R3b) (#900) 2026-07-12 00:50:50 +02:00
test_progression.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_resolved_root_cache.py perf(paths): resolve the library root once, not on every path check (#966) 2026-07-14 19:48:39 +02:00
test_safepath.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_scraper_options.py refactor(server): move the metadata-enrichment subsystem into lib/enrichment.py (R3) (#861) 2026-07-11 11:32:21 +02:00
test_settings_api.py refactor(server): carve the library scanner into lib/scan.py (R3b) (#901) 2026-07-12 01:26:02 +02:00
test_settings_export_library_db.py refactor(server): extract the settings routes into routers/settings.py (R3) (#863) 2026-07-11 12:35:05 +02:00
test_settings_export.py refactor(server): extract the settings routes into routers/settings.py (R3) (#863) 2026-07-11 12:35:05 +02:00
test_settings_instrument.py settings: add host instrument profiles (#753) 2026-07-05 00:16:42 +02:00
test_sloppak_cent_offset.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_sloppak_cover_art.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_sloppak_drum_parts.py feat(sloppak): load multiple drum parts (feedpak 1.17.0 drums-as-arrangements) (#1020) 2026-07-21 13:27:41 +02:00
test_sloppak_drumtab_load.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_sloppak_feedpak_version.py feat(core): adopt feedpak_version — read on load + stamp on manifest writes (spec §4) (#530) 2026-06-20 21:59:04 +02:00
test_sloppak_file_traversal.py refactor(server): extract the media/file-serving routes into routers/media.py (R3) (#869) 2026-07-11 15:36:22 +02:00
test_sloppak_full_mix_load.py fix(sloppak): the full mix is a stem — drop the invented original_audio key (#946) 2026-07-13 12:22:42 -04:00
test_sloppak_jsonc_load.py feat(core): read .jsonc data files (strip C-style comments) (feedpak-spec §8) 2026-06-20 14:10:04 -07:00
test_sloppak_keys_load.py feat(core): consume keys.json — song-level key/scale track (loader + WS) (#528) 2026-06-20 21:23:48 +02:00
test_sloppak_notation_load.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_sloppak_song_timeline_load.py feat(core): consume song_timeline tempos + time_signatures + per-chart tempos (feedpak 1.2.0) (#529) 2026-06-20 21:35:07 +02:00
test_sloppak_unpack_cache.py fix(sloppak): bound the unpack cache; add read_member_bytes() so callers stop unpacking whole songs (#950) 2026-07-13 17:13:08 +02:00
test_song_info_stems.py Pass per-stem name/description through to the stems payloads (#1013) 2026-07-19 11:45:16 -04:00
test_song_score.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_song_stats_api.py test(stats): prove seconds-only recency on a fresh row (#948) 2026-07-13 15:36:05 +02:00
test_song_user_meta.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_song.py fix(song): make bass detection instrument-type-aware, not name-only (#1019) 2026-07-21 13:30:54 +02:00
test_songmeta.py fix: Edit Metadata persists into .feedpak files (suffix gate predated the rename) (#725) 2026-07-02 20:51:57 +02:00
test_spec_gate.py ci: cover gap-fill manifest key scans 2026-07-13 13:25:44 +02:00
test_starter_suggestions.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_startup_status.py refactor(server): carve demo mode into lib/demo_mode.py (R3b) (#903) 2026-07-12 01:32:46 +02:00
test_tailwind_rebuild.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_tailwind_runtime_path.py fix(tailwind): stop the dev server rewriting a tracked file (#911) (#918) 2026-07-12 13:25:16 +02:00
test_tones.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_tuning_provider_isolation.py feat(sloppak): load multiple drum parts (feedpak 1.17.0 drums-as-arrangements) (#1020) 2026-07-21 13:27:41 +02:00
test_tunings.py Harden freqs_to_midis against NaN/Inf; badges read exact tuningMidis 2026-07-12 15:24:39 -05:00
test_version_endpoint.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_vocal_pitch.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_wanted_api.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_work_charts_api.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_work_grouping.py fix(tests): join background scan/enrich workers before closing the DB (#735) 2026-07-03 12:15:43 +02:00
test_ws_highway_disconnect.py fix(ws_highway): swallow a mid-stream WebSocketDisconnect quietly (#845) 2026-07-10 21:30:53 +02:00
test_xp.py Clean release snapshot 2026-06-16 18:47:13 +02:00