1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
from __future__ import annotations
import pytest
from textual.app import App, ComposeResult
from textual.widgets import Label, ListItem, ListView
class EmptyListViewApp(App[None]):
def compose(self) -> ComposeResult:
yield ListView()
async def test_listview_pop_empty_raises_index_error():
app = EmptyListViewApp()
async with app.run_test() as pilot:
listview = pilot.app.query_one(ListView)
with pytest.raises(IndexError) as excinfo:
listview.pop()
assert "pop from empty list" in str(excinfo.value)
class ListViewApp(App[None]):
def __init__(self, initial_index: int | None = None):
super().__init__()
self.initial_index = initial_index
self.highlighted = []
def compose(self) -> ComposeResult:
yield ListView(
ListItem(Label("0")),
ListItem(Label("1")),
ListItem(Label("2")),
ListItem(Label("3")),
ListItem(Label("4")),
ListItem(Label("5")),
ListItem(Label("6")),
ListItem(Label("7")),
ListItem(Label("8")),
initial_index=self.initial_index,
)
def _on_list_view_highlighted(self, message: ListView.Highlighted) -> None:
if message.item is None:
self.highlighted.append(None)
else:
self.highlighted.append(str(message.item.children[0].renderable))
async def test_listview_remove_items() -> None:
"""Regression test for https://github.com/Textualize/textual/issues/4735"""
app = ListViewApp()
async with app.run_test() as pilot:
listview = pilot.app.query_one(ListView)
assert len(listview) == 9
await listview.remove_items(range(4, 9))
assert len(listview) == 4
@pytest.mark.parametrize(
"initial_index, pop_index, expected_new_index, expected_highlighted",
[
(2, 2, 2, ["2", "3"]), # Remove highlighted item
(0, 0, 0, ["0", "1"]), # Remove first item when highlighted
(8, None, 7, ["8", "7"]), # Remove last item when highlighted
(4, 2, 3, ["4", "4"]), # Remove item before the highlighted index
(4, -2, 4, ["4"]), # Remove item after the highlighted index
],
)
async def test_listview_pop_updates_index_and_highlighting(
initial_index, pop_index, expected_new_index, expected_highlighted
) -> None:
"""Regression test for https://github.com/Textualize/textual/issues/5114"""
app = ListViewApp(initial_index)
async with app.run_test() as pilot:
listview = pilot.app.query_one(ListView)
await listview.pop(pop_index)
await pilot.pause()
assert listview.index == expected_new_index
assert listview._nodes[expected_new_index].highlighted is True
assert app.highlighted == expected_highlighted
@pytest.mark.parametrize(
"initial_index, remove_indices, expected_new_index, expected_highlighted",
[
(2, [2], 2, ["2", "3"]), # Remove highlighted item
(0, [0], 0, ["0", "1"]), # Remove first item when highlighted
(8, [-1], 7, ["8", "7"]), # Remove last item when highlighted
(4, [2, 1], 2, ["4", "4"]), # Remove items before the highlighted index
(4, [-2, 5], 4, ["4"]), # Remove items after the highlighted index
(4, range(0, 9), None, ["4", None]), # Remove all items
],
)
async def test_listview_remove_items_updates_index_and_highlighting(
initial_index, remove_indices, expected_new_index, expected_highlighted
) -> None:
"""Regression test for https://github.com/Textualize/textual/issues/5114"""
app = ListViewApp(initial_index)
async with app.run_test() as pilot:
listview = pilot.app.query_one(ListView)
await listview.remove_items(remove_indices)
await pilot.pause()
assert listview.index == expected_new_index
if expected_new_index is not None:
assert listview._nodes[expected_new_index].highlighted is True
assert app.highlighted == expected_highlighted
if __name__ == "__main__":
app = ListViewApp()
app.run()
|