-
Notifications
You must be signed in to change notification settings - Fork 815
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3409 from joshbduncan/disabled-trees
fix Tree(disabled=True) breaking app
- Loading branch information
Showing
3 changed files
with
121 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Any | ||
|
||
from textual import on | ||
from textual.app import App, ComposeResult | ||
from textual.widgets import Tree | ||
|
||
|
||
class TreeApp(App[None]): | ||
"""Test tree app.""" | ||
|
||
def __init__(self, disabled: bool, *args: Any, **kwargs: Any) -> None: | ||
super().__init__(*args, **kwargs) | ||
self.disabled = disabled | ||
self.messages: list[tuple[str, str]] = [] | ||
|
||
def compose(self) -> ComposeResult: | ||
"""Compose the child widgets.""" | ||
yield Tree("Root", disabled=self.disabled, id="test-tree") | ||
|
||
def on_mount(self) -> None: | ||
self.query_one(Tree).root.add("Child") | ||
self.query_one(Tree).focus() | ||
|
||
def record( | ||
self, | ||
event: Tree.NodeSelected[None] | ||
| Tree.NodeExpanded[None] | ||
| Tree.NodeCollapsed[None] | ||
| Tree.NodeHighlighted[None], | ||
) -> None: | ||
self.messages.append( | ||
(event.__class__.__name__, event.node.tree.id or "Unknown") | ||
) | ||
|
||
@on(Tree.NodeSelected) | ||
def node_selected(self, event: Tree.NodeSelected[None]) -> None: | ||
self.record(event) | ||
|
||
@on(Tree.NodeExpanded) | ||
def node_expanded(self, event: Tree.NodeExpanded[None]) -> None: | ||
self.record(event) | ||
|
||
@on(Tree.NodeCollapsed) | ||
def node_collapsed(self, event: Tree.NodeCollapsed[None]) -> None: | ||
self.record(event) | ||
|
||
@on(Tree.NodeHighlighted) | ||
def node_highlighted(self, event: Tree.NodeHighlighted[None]) -> None: | ||
self.record(event) | ||
|
||
|
||
async def test_creating_disabled_tree(): | ||
"""Mounting a disabled `Tree` should result in the base `Widget` | ||
having a `disabled` property equal to `True`""" | ||
app = TreeApp(disabled=True) | ||
async with app.run_test() as pilot: | ||
tree = app.query_one(Tree) | ||
assert not tree.focusable | ||
assert tree.disabled | ||
assert tree.cursor_line == 0 | ||
await pilot.click("#test-tree") | ||
await pilot.pause() | ||
await pilot.press("down") | ||
await pilot.pause() | ||
assert tree.cursor_line == 0 | ||
|
||
|
||
async def test_creating_enabled_tree(): | ||
"""Mounting an enabled `Tree` should result in the base `Widget` | ||
having a `disabled` property equal to `False`""" | ||
app = TreeApp(disabled=False) | ||
async with app.run_test() as pilot: | ||
tree = app.query_one(Tree) | ||
assert tree.focusable | ||
assert not tree.disabled | ||
assert tree.cursor_line == 0 | ||
await pilot.click("#test-tree") | ||
await pilot.pause() | ||
await pilot.press("down") | ||
await pilot.pause() | ||
assert tree.cursor_line == 1 | ||
|
||
|
||
async def test_disabled_tree_node_selected_message() -> None: | ||
"""Clicking the root node disclosure triangle on a disabled tree | ||
should result in no messages being emitted.""" | ||
app = TreeApp(disabled=True) | ||
async with app.run_test() as pilot: | ||
tree = app.query_one(Tree) | ||
# try clicking on a disabled tree | ||
await pilot.click("#test-tree") | ||
await pilot.pause() | ||
assert not pilot.app.messages | ||
# make sure messages DO flow after enabling a disabled tree | ||
tree.disabled = False | ||
await pilot.click("#test-tree") | ||
await pilot.pause() | ||
assert pilot.app.messages == [("NodeExpanded", "test-tree")] | ||
|
||
|
||
async def test_enabled_tree_node_selected_message() -> None: | ||
"""Clicking the root node disclosure triangle on an enabled tree | ||
should result in an `NodeExpanded` message being emitted.""" | ||
app = TreeApp(disabled=False) | ||
async with app.run_test() as pilot: | ||
tree = app.query_one(Tree) | ||
# try clicking on an enabled tree | ||
await pilot.click("#test-tree") | ||
await pilot.pause() | ||
assert pilot.app.messages == [("NodeExpanded", "test-tree")] | ||
tree.disabled = True | ||
# make sure messages DO NOT flow after disabling an enabled tree | ||
app.messages = [] | ||
await pilot.click("#test-tree") | ||
await pilot.pause() | ||
assert not pilot.app.messages |