Files
lintunes/tests/test_round69.py
T
travandClaude Opus 5.5 d5cdddee33 v0.31.4: wider now-playing panel, tighter knolled top row
The now-playing panel (and the seek row under it) caps at 700px, up from
560. The top row gets one equal gap before, between and after its
controls, capped at 28px; past that the extra splits between the two
ends, so the row sits centered instead of spreading out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:51:05 -07:00

135 lines
5.1 KiB
Python

"""Round 69: the header row moves up into the seek row's band.
The Library button, the view's header (search box or playlist name) and the
seek row share one row under the transport boxes: the Library button as wide
as the sidebar, the header where the view starts, the seek row exactly under
the now-playing panel. The panel stops at NOW_PLAYING_MAX and the gaps between
the controls share what's left.
"""
from PyQt6.QtCore import QPoint
from lintunes.gui.fit_label import FitLabel
from lintunes.gui.main_window import MainWindow
from lintunes.gui.transport import NOW_PLAYING_MAX, NOW_PLAYING_MIN
from lintunes.library_manager import LibraryManager
from lintunes.models.library import Library
from lintunes.models.playlist import Playlist
from lintunes.models.track import Track
from lintunes.preferences import Preferences
def _window(qapp, tmp_path, width=1280):
library = Library(tracks={1: Track(track_id=1, name="One")})
library.playlists["abcd1234"] = Playlist(
persistent_id="abcd1234", name="Road Trip", track_ids=[1])
window = MainWindow(LibraryManager(library, tmp_path), Preferences(tmp_path))
window.resize(width, 500)
window.show()
qapp.processEvents()
return window
def _x(widget, window, x=0):
return widget.mapTo(window, QPoint(x, 0)).x()
def _gx(widget, x=0):
return widget.mapToGlobal(QPoint(x, 0)).x()
def test_startup_still_opens_on_the_library(qapp, tmp_path):
# The moved Library button fell to the end of the focus chain, the tree
# took the first focus and selected its first playlist.
window = _window(qapp, tmp_path)
assert window._content.currentWidget() is window._library_view
assert window._sidebar.library_button.isChecked()
def test_library_button_spans_the_sidebar(qapp, tmp_path):
window = _window(qapp, tmp_path)
header = window.sidebar.header
assert header.parentWidget() is not window.sidebar
assert _gx(header) == _gx(window.sidebar)
assert header.width() == window.sidebar.width()
def test_search_then_title_sit_where_the_view_starts(qapp, tmp_path):
window = _window(qapp, tmp_path)
search_strip = window._library_view.header
assert search_strip.isVisible()
assert _gx(search_strip) == _gx(window._content)
window._show_playlist("abcd1234")
qapp.processEvents()
label = window._playlist_view.header
assert label.isVisible() and label.full_text() == "Road Trip"
assert _gx(label) == _gx(window._content)
# The search strip went home to its view, hidden.
assert not search_strip.isVisible()
assert search_strip.parentWidget() is window._library_view
def test_header_row_shares_the_seek_band(qapp, tmp_path):
window = _window(qapp, tmp_path)
bar = window._transport
panel = bar._now_playing
seek = bar._slider.parentWidget()
# Under the panel, edge to edge, and level with the Library button.
assert _gx(seek) == _gx(panel)
assert seek.width() == panel.width()
library = window.sidebar.library_button
row = bar._header_row
assert row.geometry().top() > panel.geometry().bottom()
assert library.mapTo(bar, QPoint()).y() >= row.geometry().top()
def test_panel_caps_and_gaps_take_the_rest(qapp, tmp_path):
window = _window(qapp, tmp_path, width=1600)
bar = window._transport
assert bar._now_playing.width() == NOW_PLAYING_MAX
window.resize(800, 500)
qapp.processEvents()
assert NOW_PLAYING_MIN <= bar._now_playing.width() < NOW_PLAYING_MAX
bpm = bar._bpm_button.parentWidget()
assert bar._now_playing.geometry().right() < bpm.geometry().left()
assert bpm.geometry().right() < bar.width()
def test_views_seek_row_never_overlaps_the_header(qapp, tmp_path):
window = _window(qapp, tmp_path, width=800)
strip = window._library_view.header
seek = window._transport._slider.parentWidget()
assert _gx(strip, strip.width()) <= _gx(seek)
def test_long_name_shrinks_then_elides(qapp):
label = FitLabel()
base = label.font().pointSize()
label.resize(120, 30)
label.setText("A short one")
assert label.text() == "A short one"
label.setText("An Extraordinarily Long Playlist Name That Goes On Forever")
assert label.font().pointSize() >= base - 2
assert label.text().endswith("…")
assert label.toolTip() == label.full_text()
def test_row_is_knolled_with_equal_gaps_and_ends(qapp, tmp_path):
from lintunes.gui.transport import MAX_GAP, MIN_GAP
window = _window(qapp, tmp_path)
bar = window._transport
for width in (900, 1280, 1800):
window.resize(width, 500)
qapp.processEvents()
row = [bar._prev_btn.parentWidget(), bar._shuffle_btn.parentWidget(),
bar._visualizer, bar._volume_slider, bar._now_playing,
bar._bpm_button.parentWidget()]
edges = [(w.geometry().left(), w.geometry().right()) for w in row]
gaps = [b[0] - a[1] - 1 for a, b in zip(edges, edges[1:])]
assert max(gaps) - min(gaps) <= 1
assert MIN_GAP <= gaps[0] <= MAX_GAP
left_end, right_end = edges[0][0], bar.width() - 1 - edges[-1][1]
assert abs(left_end - right_end) <= 1
assert left_end >= gaps[0] - 1