Implements org.mpris.MediaPlayer2 and org.mpris.MediaPlayer2.Player
D-Bus interfaces, allowing desktop environment media keys and tools
like playerctl to control playback (play, pause, next, previous)
and display now-playing metadata.
Also adds _FallbackServiceInterface, _FallbackVariant and
_FallbackNameFlag so all tests pass without dbus-fast installed;
the module gracefully degrades when the library is unavailable.
Replace SearchWorker signal .connect() with mock.MagicMock to handle
the case where the player module Signal binding is a plain function
(import fallback when PySide6 is unavailable in headless CI).
The MagicMock captures .emit() calls and works across all environments:
real Qt, conftest stubs, and player.py fallback paths.
- Fix dead exception handler in discord_rpc.py (unreachable DiscordNotFound)
- Replace QMediaPlayer=None stub with proper _StubQMediaPlayer in player.py
- Make AudioVisualizer color stops Qt-free (raw tuples instead of QColor)
- Add conftest QApplication creation check for headless CI detection
- Add test_gui_widgets.py _qt_available() guard for headless environments
- Add test_main.py (30 tests) for main.py entry point and env vars
- Add test_import_fallbacks.py (14 tests) for Qt import fallback paths
- Extend test_gui_helpers.py with _css, _get_thumbnail_nam, _cached_thumb_path tests
- Extend test_discord_rpc.py with direct _connect() test for DiscordNotFound
- Extend test_player_helpers.py with SearchWorker test-mode tests
- Ensure import fallback tests clean up sys.modules to avoid cross-test pollution
100% coverage achieved on: config.py, discord_rpc.py, main.py, music_db.py
- Restructure conftest to try real Qt first, fall back to stubs
only if that fails — ensures try/except guards in player.py and
gui.py are exercised in CI, improving new_coverage
- Add tests for _migrate_legacy error paths (JSONDecodeError,
OSError, db migration) — config.py now 100% covered
- Add tests for _disconnect, _send_presence exception handlers —
discord_rpc.py now 97% covered
- Add tests for _cleanup_path and _tmp_dir helpers — player.py
coverage bumped to 33%