Accessibility improvements.
This commit is contained in:
1 parent
d2e68bdcb4
commit
c4ccc39aac
5 files changed
+186
-139
No files matched your search
@@ -0,0 +1,130 @@
|
||||
"""Tree navigation and accessibility regressions, without a server or audio."""
|
||||
import pytest
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtGui import QAccessible
|
||||
from PySide6.QtTest import QTest
|
||||
from PySide6.QtWidgets import QApplication, QTreeWidgetItem
|
||||
|
||||
from src.accessibility.accessible_tree import AccessibleTreeWidget
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tree():
|
||||
app = QApplication.instance() or QApplication([])
|
||||
widget = AccessibleTreeWidget()
|
||||
widget.setHeaderHidden(True)
|
||||
widget.show()
|
||||
app.processEvents()
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def add(parent, text):
|
||||
item = QTreeWidgetItem([text])
|
||||
if isinstance(parent, AccessibleTreeWidget):
|
||||
parent.addTopLevelItem(item)
|
||||
else:
|
||||
parent.addChild(item)
|
||||
return item
|
||||
|
||||
|
||||
def press(tree, key, expected):
|
||||
QTest.keyClick(tree, key)
|
||||
assert tree.currentItem() is expected
|
||||
|
||||
|
||||
def test_collapsed_children_and_late_results_are_not_navigable(tree):
|
||||
root = add(tree, 'Albums')
|
||||
child = add(root, 'Album')
|
||||
last = add(tree, 'Playlists')
|
||||
tree.setCurrentItem(root)
|
||||
press(tree, Qt.Key_Down, last)
|
||||
press(tree, Qt.Key_Up, root)
|
||||
press(tree, Qt.Key_Right, root)
|
||||
press(tree, Qt.Key_Right, child)
|
||||
root.setExpanded(False)
|
||||
assert tree.currentItem() is root
|
||||
late = add(root, 'Loaded after collapse')
|
||||
assert not tree.isItemNavigable(late)
|
||||
press(tree, Qt.Key_Down, last)
|
||||
root.setExpanded(True)
|
||||
assert tree.isItemNavigable(late)
|
||||
|
||||
|
||||
def test_hidden_rows_are_skipped_in_both_directions_and_at_edges(tree):
|
||||
hidden_first = add(tree, 'Hidden first')
|
||||
hidden_first.setHidden(True)
|
||||
root = add(tree, 'Root')
|
||||
hidden_child = add(root, 'Hidden child')
|
||||
hidden_child.setHidden(True)
|
||||
child = add(root, 'Visible child')
|
||||
disabled = add(root, 'Disabled')
|
||||
disabled.setDisabled(True)
|
||||
other = add(root, 'Other child')
|
||||
hidden_last = add(tree, 'Hidden last')
|
||||
hidden_last.setHidden(True)
|
||||
root.setExpanded(True)
|
||||
tree.setCurrentItem(root)
|
||||
press(tree, Qt.Key_Right, child)
|
||||
press(tree, Qt.Key_Down, other)
|
||||
press(tree, Qt.Key_Up, child)
|
||||
press(tree, Qt.Key_Home, root)
|
||||
press(tree, Qt.Key_End, other)
|
||||
press(tree, Qt.Key_PageUp, root)
|
||||
press(tree, Qt.Key_PageDown, other)
|
||||
|
||||
|
||||
def test_expansion_preserves_names_descriptions_and_flags(tree):
|
||||
root = add(tree, 'Artist')
|
||||
root.setData(0, Qt.AccessibleTextRole, 'Artist, 12 albums')
|
||||
child = add(root, 'Album')
|
||||
child.setData(0, Qt.AccessibleDescriptionRole, 'Released in 2024')
|
||||
child.setFlags(child.flags() & ~Qt.ItemIsSelectable)
|
||||
disabled = add(root, 'Unavailable')
|
||||
disabled.setDisabled(True)
|
||||
original_flags = [child.flags(), disabled.flags()]
|
||||
states = []
|
||||
tree.itemStateChanged.connect(lambda item, state: states.append(state))
|
||||
for _ in range(2):
|
||||
root.setExpanded(True)
|
||||
root.setExpanded(False)
|
||||
assert root.data(0, Qt.AccessibleTextRole) == 'Artist, 12 albums'
|
||||
assert child.data(0, Qt.AccessibleDescriptionRole) == 'Released in 2024'
|
||||
assert [child.flags(), disabled.flags()] == original_flags
|
||||
assert states == ['expanded', 'collapsed'] * 2
|
||||
|
||||
|
||||
def test_nested_collapsed_branch_stays_closed_on_parent_reopen(tree):
|
||||
root = add(tree, 'Root')
|
||||
branch = add(root, 'Branch')
|
||||
leaf = add(branch, 'Leaf')
|
||||
root.setExpanded(True)
|
||||
branch.setExpanded(True)
|
||||
tree.setCurrentItem(leaf)
|
||||
branch.setExpanded(False)
|
||||
assert tree.currentItem() is branch
|
||||
root.setExpanded(False)
|
||||
root.setExpanded(True)
|
||||
assert not tree.isItemNavigable(leaf)
|
||||
tree.setCurrentItem(branch)
|
||||
press(tree, Qt.Key_End, branch)
|
||||
|
||||
|
||||
def test_accessibility_exposes_only_expanded_rows(tree):
|
||||
root = add(tree, 'Albums')
|
||||
add(root, 'Song')
|
||||
tree.setCurrentItem(root)
|
||||
QApplication.processEvents()
|
||||
interface = QAccessible.queryAccessibleInterface(tree)
|
||||
def spoken_rows():
|
||||
return [interface.child(i).text(QAccessible.Name)
|
||||
for i in range(interface.childCount())
|
||||
if interface.child(i).role() == QAccessible.TreeItem]
|
||||
|
||||
assert spoken_rows() == ['Albums']
|
||||
root.setExpanded(True)
|
||||
QApplication.processEvents()
|
||||
assert spoken_rows() == ['Albums', 'Song']
|
||||
root.setExpanded(False)
|
||||
QApplication.processEvents()
|
||||
assert spoken_rows() == ['Albums']
|
||||
Reference in new issue
Block a user