More work on the UI accessibility.

This commit is contained in:
Storm Dragon committed 2026-09-15 14:48:55 -04:00
1 parent c4ccc39aac
commit d9f4ac4135
3 files changed
+131 -6

No files matched your search

+129
View File
@@ -0,0 +1,129 @@
"""Exercise the assembled library UI with fake data and controlled requests."""
from unittest.mock import Mock
import pytest
from PySide6.QtCore import Qt
from PySide6.QtTest import QTest
from PySide6.QtWidgets import QApplication
from src.api.models import Album, Artist, Song
from src.main_window import MainWindow
@pytest.fixture
def window(monkeypatch, tmp_path):
app = QApplication.instance() or QApplication([])
for name in ('XDG_CONFIG_HOME', 'XDG_DATA_HOME', 'XDG_CACHE_HOME'):
monkeypatch.setenv(name, str(tmp_path / name))
monkeypatch.setattr(MainWindow, 'setupMpris', lambda self: None)
monkeypatch.setattr(MainWindow, 'showServerSetup', lambda self: None)
# Avoid the production close handler's forced process exit.
monkeypatch.setattr(MainWindow, 'closeEvent', lambda self, event: event.accept())
monkeypatch.setattr("src.managers.playback_manager.QMediaPlayer", Mock())
monkeypatch.setattr("src.managers.playback_manager.QAudioOutput", Mock())
w = MainWindow()
w.client = Mock()
w.startPlaybackWithSongs = Mock()
pending = []
w._run_background = lambda label, work, on_success=None, **kw: pending.append(on_success)
w._applyLibraryData({'artists': [Artist('artist', 'Artist', 1)]})
w.show()
w.libraryTree.setFocus()
app.processEvents()
yield w, pending
w._executor.shutdown(wait=True)
w.close()
w.deleteLater()
app.processEvents()
def open_album(window):
w, pending = window
tree = w.libraryTree
artist = w.artistsRoot.child(0)
tree.setCurrentItem(artist)
QTest.keyClick(tree, Qt.Key_Right)
pending.pop()([Album('album', 'Album', 'Artist', songCount=1)])
QTest.keyClick(tree, Qt.Key_Right)
album = tree.currentItem()
assert album.parent() is artist
QTest.keyClick(tree, Qt.Key_Right)
songs = [Song('song', 'Song', 'Album', 'album', 'Artist')]
pending.pop()(songs)
QApplication.processEvents()
return album, songs
def test_album_can_collapse_and_reopen_after_loading(window):
w, pending = window
album, songs = open_album(window)
tree = w.libraryTree
assert album.isExpanded()
QTest.keyClick(tree, Qt.Key_Right)
assert tree.currentItem() is album.child(0)
QTest.keyClick(tree, Qt.Key_Left)
assert tree.currentItem() is album
QTest.keyClick(tree, Qt.Key_Left)
assert not album.isExpanded()
assert tree.visualItemRect(album.child(0)).isEmpty()
QTest.keyClick(tree, Qt.Key_Right)
assert album.isExpanded()
assert not pending
def test_playback_completion_respects_album_collapse(window):
w, pending = window
album, songs = open_album(window)
QTest.keyClick(w.libraryTree, Qt.Key_Return)
assert len(pending) == 1
QTest.keyClick(w.libraryTree, Qt.Key_Left)
assert not album.isExpanded()
pending.pop()((None, songs))
QApplication.processEvents()
assert not album.isExpanded()
assert w.libraryTree.visualItemRect(album.child(0)).isEmpty()
w.startPlaybackWithSongs.assert_called_once()
def test_album_can_collapse_with_mouse(window):
w, _ = window
album, _ = open_album(window)
tree = w.libraryTree
tree.setCurrentItem(album.child(0))
rect = tree.visualItemRect(album)
# Click the branch indicator just before the album's text rectangle.
point = rect.center()
point.setX(rect.left() - tree.indentation() // 2)
QTest.mouseClick(tree.viewport(), Qt.LeftButton, pos=point)
QApplication.processEvents()
assert not album.isExpanded()
assert tree.currentItem() is album
def test_album_browse_response_does_not_reopen_collapsed_branch(window):
w, pending = window
album, songs = open_album(window)
data = album.data(0, Qt.UserRole)
data['loaded'] = False
album.setData(0, Qt.UserRole, data)
QTest.keyClick(w.libraryTree, Qt.Key_Left)
QTest.keyClick(w.libraryTree, Qt.Key_Right)
assert len(pending) == 1
QTest.keyClick(w.libraryTree, Qt.Key_Left)
pending.pop()(songs)
QApplication.processEvents()
assert not album.isExpanded()
assert not w.libraryTree.isItemNavigable(album.child(0))
@pytest.mark.parametrize('kind', ['artist', 'genre'])
def test_other_playback_responses_preserve_collapsed_branches(window, kind):
w, _ = window
album, songs = open_album(window)
album.setExpanded(False)
if kind == 'artist':
w._onArtistLoadedForPlay(album, (None, songs))
else:
w._onGenreLoadedForPlay('Genre', album, (songs, False))
assert not album.isExpanded()
w.startPlaybackWithSongs.assert_called_once()