feedBack/tests
ChrisBeWithYou 8fbbc761fc
fix(v3): reject accidental text-selection of UI chrome (user-select policy) (#637)
* fix(v3): reject accidental text-selection of UI chrome (user-select policy)

Dragging/double-clicking across the v3 UI marquee-highlighted buttons, labels,
the sidebar, transport, and the note-highway HUD — looks broken (reported Mac +
Windows). Default the v3 shell to user-select:none on html, then opt CONTENT
back in. Decided by a 4-lens panel (UX / a11y / dev-ops / plugin-ecosystem);
their guardrails are baked in:

- Form fields ALWAYS re-enabled (input/textarea/select/[contenteditable]) so the
  caret + IME composition never break. No `* { user-select:none }` (WebKit input
  bug 82692).
- Plugin screens (.screen[id^="plugin-"]) stay selectable BY INHERITANCE (no `*`,
  so a plugin's own non-select chrome still wins) — a plugin's copyable text
  (lyrics, chords, results), including community/out-of-tree plugins that never
  adopt the class, isn't silently locked.
- Core read-only content opts back in by CONTAINER via a hand-authored
  `.fb-selectable` (not a Tailwind utility — so runtime-installed plugins get it
  too): the whole Settings panel (paths, device names, version, diagnostics,
  About) and the now-playing song metadata. Answers the open "keep settings
  copyable?" question: yes, at the container.

Cosmetic only — never used to lock copy-worthy text (errors/IDs/paths/versions/
metadata stay selectable; WCAG 2.2 allows copy-paste as a mechanism). v3-only
(v2 unchanged; v3.css loads only on /v3); plain CSS, no Tailwind rebuild; no
desktop/Electron changes (standard OS-framed window). `.fb-selectable` is
documented in CLAUDE.md for plugin authors.

Tests: tests/js/v3_user_select_policy.test.js (html default, form-field
re-enable, plugin-screen carve without `*`, .fb-selectable, container opt-ins,
and the no-`*`-rule guardrail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbexxfTt8q2tAn436MqGWF

* fix(v3): address review of the user-select policy (#637)

Review (manual + Codex) of the v3 text-selection policy:

- P1 (real bug): the now-playing HUD metadata opted into `.fb-selectable` but
  its `#player-hud` parent is `pointer-events: none`, so the mouse could never
  reach the text to select it — the opt-in was inert. Add `pointer-events-auto`
  to the metadata block (verified in-browser: user-select:text + pointer-
  events:auto, while the HUD parent stays pointer-events:none).
- Coverage: the PR's a11y guardrail promised copyable text stays selectable
  "incl. in modals/toasts", but only Settings + the HUD were opted in. Blanket-
  opt the focused copyable surfaces back in by selector — `.feedBack-modal`,
  `[role="dialog"]`, `#fb-notify-stack`, `#v3-fb-toast`, `#scan-banner` — so
  errors / IDs / paths / file names in dialogs, toasts, and the scan banner stay
  copyable. These are focused panels, not dense card lists, so re-enabling
  selection there can't recreate the across-cards marquee mess.
  (Deliberately NOT opting in the library grid / dashboard / profile card lists:
  making dense card text selectable would reintroduce exactly that marquee mess
  on a drag — copy song metadata from the now-playing HUD / Settings instead.)
- Test (P3): assert the selectable rule's selectors order-independently, cover
  the new modal/toast/banner surfaces, and check the HUD block carries BOTH
  fb-selectable and pointer-events-auto (class-order independent).

Verified in a real browser (chromium): html=none, sidebar chrome=none, input=
text, Settings=text, HUD meta=text+pointer-events:auto, dialog/modal=text.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>
2026-06-29 14:44:56 +02:00
..
browser feat(v3): DOM-virtualize the Songs grid (#636 item 3 stage 2) (#643) 2026-06-29 12:26:29 +02:00
fixtures Remove unused binary test fixture; correct stale scan comments 2026-06-16 18:49:40 +01:00
js fix(v3): reject accidental text-selection of UI chrome (user-select policy) (#637) 2026-06-29 14:44:56 +02:00
plugins feat(folder_library): Folder Library core plugin (#610) 2026-06-27 16:03:54 +02:00
__init__.py Clean release snapshot 2026-06-16 18:47:13 +02:00
conftest.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_audio_local_path.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_audio.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_builtin_diagnostic_seed.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_collections_api.py feat(library): smart collections as a library provider (#641) 2026-06-29 10:42:41 +02:00
test_correlation_id.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_demo_mode.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_diagnostics_bundle.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_drums_lib.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_env_compat.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_feedpak_extension.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_gp2midi.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_gp2notation.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_gp2rs_drums.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_gp2rs_gpx.py fix(gp-import): correct bass string count, lead/rhythm roles, preview note count (#601) 2026-06-26 18:58:35 +02:00
test_gp2rs.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_gp_audio_sync.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_highway_3d_routes.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_highway_ws_authors.py feat(highway): show feedpak author/editor credits on song load (#629) 2026-06-28 22:08:44 +02:00
test_highway_ws_notation.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_library_filters.py feat(v3 library): A–Z fast-scroll jump rail on the Songs grid (#634) 2026-06-29 08:49:01 +02:00
test_library_keyset.py feat(library): keyset cursor pagination + stable sort tiebreak (#636 item 3, stage 1) (#642) 2026-06-29 10:40:47 +02:00
test_library_providers.py feat(v3 library): A–Z fast-scroll jump rail on the Songs grid (#634) 2026-06-29 08:49:01 +02: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_loose_traversal.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_loosefolder.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_lyrics_transcribe.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_midi_import_drums.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_midi_import.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_minigames_routes.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_notation_lib.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_notation_lift.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_notation_to_notes.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_parse_arrangement.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_playlists_api.py feat(v3): content-dependent playlist covers + custom art (#626) 2026-06-28 14:10:15 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_plugins.py feat(plugins): full-screen (immersive) plugin screens via manifest opt-in (#590) 2026-06-25 00:02:16 +02:00
test_profile_api.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_profile_domains.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_progression_api.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_progression.py Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
test_safepath.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_settings_api.py feat(achievements): opt-in, privacy controls & data-min gate (epic PR2) (#591) 2026-06-24 17:00:30 +02:00
test_settings_export_library_db.py feat(settings): back up the library DB + custom art in the export bundle (#639) 2026-06-29 09:34:47 +02:00
test_settings_export.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_settings_instrument.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_sloppak_cent_offset.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_sloppak_cover_art.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02: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_original_audio_load.py feat(sloppak): expose full-mix original_audio alongside stems (#583) 2026-06-23 18:05:45 +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_song_score.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_song_stats_api.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_song.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_songmeta.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_startup_status.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_tailwind_rebuild.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_tones.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_tunings.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_version_endpoint.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
test_vocal_pitch.py Clean release snapshot 2026-06-16 18:47:13 +02:00
test_wanted_api.py feat(library): persisted wishlist / "wanted" list (#640) 2026-06-29 09:36:02 +02:00
test_xp.py Clean release snapshot 2026-06-16 18:47:13 +02:00