Merge pull request #1785 from davep/promote-disabled

Promote disabled to `Widget` level
This commit is contained in:
Will McGugan
2023-02-21 09:56:01 +00:00
committed by GitHub
20 changed files with 555 additions and 156 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,84 @@
from textual.app import App, ComposeResult
from textual.containers import Vertical, Horizontal
from textual.widgets import (
Header,
Footer,
Button,
DataTable,
Input,
ListView,
ListItem,
Label,
Markdown,
MarkdownViewer,
Tree,
TextLog,
)
class WidgetDisableTestApp(App[None]):
CSS = """
Horizontal {
height: auto;
}
DataTable, ListView, Tree, TextLog {
height: 2;
}
Markdown, MarkdownViewer {
height: 1fr;
}
"""
@property
def data_table(self) -> DataTable:
data_table = DataTable[str]()
data_table.add_columns("Column 1", "Column 2", "Column 3", "Column 4")
data_table.add_rows(
[(str(n), str(n * 10), str(n * 100), str(n * 1000)) for n in range(100)]
)
return data_table
@property
def list_view(self) -> ListView:
return ListView(*[ListItem(Label(f"This is list item {n}")) for n in range(20)])
@property
def test_tree(self) -> Tree:
tree = Tree[None](label="This is a test tree")
for n in range(10):
tree.root.add_leaf(f"Leaf {n}")
tree.root.expand()
return tree
def compose(self) -> ComposeResult:
yield Header()
yield Vertical(
Horizontal(
Button(),
Button(variant="primary"),
Button(variant="success"),
Button(variant="warning"),
Button(variant="error"),
),
self.data_table,
self.list_view,
self.test_tree,
TextLog(),
Input(),
Input(placeholder="This is an empty input with a placeholder"),
Input("This is some text in an input"),
Markdown("# Hello, World!"),
MarkdownViewer("# Hello, World!"),
id="test-container",
)
yield Footer()
def on_mount(self) -> None:
self.query_one(TextLog).write("Hello, World!")
self.query_one("#test-container", Vertical).disabled = True
if __name__ == "__main__":
WidgetDisableTestApp().run()

View File

@@ -231,3 +231,7 @@ def test_auto_width_input(snap_compare):
def test_screen_switch(snap_compare):
assert snap_compare(SNAPSHOT_APPS_DIR / "screen_switch.py", press=["a", "b"])
def test_disabled_widgets(snap_compare):
assert snap_compare(SNAPSHOT_APPS_DIR / "disable_widgets.py")

84
tests/test_disabled.py Normal file
View File

@@ -0,0 +1,84 @@
"""Test Widget.disabled."""
from textual.app import App, ComposeResult
from textual.containers import Vertical
from textual.widgets import (
Button,
DataTable,
DirectoryTree,
Input,
ListView,
Markdown,
MarkdownViewer,
Switch,
TextLog,
Tree,
)
class DisableApp(App[None]):
"""Application for testing Widget.disabled."""
def compose(self) -> ComposeResult:
"""Compose the child widgets."""
yield Vertical(
Button(),
DataTable(),
DirectoryTree("."),
Input(),
ListView(),
Switch(),
TextLog(),
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("Vertical > *"):
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", Vertical).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 > *")
)