File: test_disabled.py

package info (click to toggle)
textual 2.1.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,080 kB
  • sloc: python: 85,423; lisp: 1,669; makefile: 101
file content (149 lines) | stat: -rw-r--r-- 4,664 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""Test Widget.disabled."""

import pytest

from textual.app import App, ComposeResult
from textual.containers import Vertical, VerticalScroll
from textual.widgets import (
    Button,
    Checkbox,
    DataTable,
    DirectoryTree,
    Input,
    Label,
    ListItem,
    ListView,
    Markdown,
    MarkdownViewer,
    OptionList,
    RadioButton,
    RadioSet,
    RichLog,
    Select,
    Switch,
    Tree,
)


class DisableApp(App[None]):
    """Application for testing Widget.disabled."""

    def compose(self) -> ComposeResult:
        """Compose the child widgets."""
        yield VerticalScroll(
            Button(),
            DataTable(),
            DirectoryTree("."),
            Input(),
            ListView(),
            Switch(),
            RichLog(),
            Tree("Test"),
            Markdown(),
            MarkdownViewer(),
            id="test-container",
        )


async def test_all_initially_enabled() -> None:
    """All widgets should start out enabled."""
    async with DisableApp().run_test() as pilot:
        assert all(
            not node.disabled for node in pilot.app.screen.query("#test-container > *")
        )


async def test_enabled_widgets_have_enabled_pseudo_class() -> None:
    """All enabled widgets should have the :enabled pseudoclass."""
    async with DisableApp().run_test() as pilot:
        assert all(
            node.has_pseudo_class("enabled") and not node.has_pseudo_class("disabled")
            for node in pilot.app.screen.query("#test-container > *")
        )


async def test_all_individually_disabled() -> None:
    """Post-disable all widgets should report being disabled."""
    async with DisableApp().run_test() as pilot:
        for node in pilot.app.screen.query("VerticalScroll > *"):
            node.disabled = True
        assert all(
            node.disabled for node in pilot.app.screen.query("#test-container > *")
        )


async def test_disabled_widgets_have_disabled_pseudo_class() -> None:
    """All disabled widgets should have the :disabled pseudoclass."""
    async with DisableApp().run_test() as pilot:
        for node in pilot.app.screen.query("#test-container > *"):
            node.disabled = True
        assert all(
            node.has_pseudo_class("disabled") and not node.has_pseudo_class("enabled")
            for node in pilot.app.screen.query("#test-container > *")
        )


async def test_disable_via_container() -> None:
    """All child widgets should appear (to CSS) as disabled by a container being disabled."""
    async with DisableApp().run_test() as pilot:
        pilot.app.screen.query_one("#test-container", VerticalScroll).disabled = True
        assert all(
            node.has_pseudo_class("disabled") and not node.has_pseudo_class("enabled")
            for node in pilot.app.screen.query("#test-container > *")
        )


class ChildrenNoFocusDisabledContainer(App[None]):
    """App for regression test for https://github.com/Textualize/textual/issues/2772."""

    def compose(self) -> ComposeResult:
        with Vertical():
            with Vertical():
                yield Button()
                yield Checkbox()
                yield DataTable()
                yield DirectoryTree(".")
                yield Input()
                with ListView():
                    yield ListItem(Label("one"))
                    yield ListItem(Label("two"))
                    yield ListItem(Label("three"))
                yield OptionList("one", "two", "three")
                with RadioSet():
                    yield RadioButton("one")
                    yield RadioButton("two")
                    yield RadioButton("three")
                yield Select([("one", 1), ("two", 2), ("three", 3)])
                yield Switch()

    def on_mount(self):
        dt = self.query_one(DataTable)
        dt.add_columns("one", "two", "three")
        dt.add_rows([["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]])


@pytest.mark.parametrize(
    "widget",
    [
        Button,
        Checkbox,
        DataTable,
        DirectoryTree,
        Input,
        ListView,
        OptionList,
        RadioSet,
        Select,
        Switch,
    ],
)
async def test_children_loses_focus_if_container_is_disabled(widget):
    """Regression test for https://github.com/Textualize/textual/issues/2772."""
    app = ChildrenNoFocusDisabledContainer()
    async with app.run_test() as pilot:
        app.query(widget).first().focus()
        await pilot.pause()
        assert isinstance(app.focused, widget)
        app.query(Vertical).first().disabled = True
        await pilot.pause()
        assert app.focused is None