File: test_listview_remove_items.py

package info (click to toggle)
textual 2.1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,084 kB
  • sloc: python: 85,423; lisp: 1,669; makefile: 101
file content (116 lines) | stat: -rw-r--r-- 4,124 bytes parent folder | download | duplicates (2)
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()