mirror of
				https://github.com/Textualize/textual.git
				synced 2025-10-17 02:38:12 +03:00 
			
		
		
		
	 879c985296
			
		
	
	879c985296
	
	
	
		
			
			* log * tests * snapshot tests * change to richlog * keep raw lines * disable highlighting by default * simplify * superfluous test * optimization * update cell length * add refresh * write method * version bump * doc fix link * makes lines private * docstring * relax dev dependancy * remove superfluous code [skip ci] * added FAQ [skipci] * fix code in faq [skipci] * fix typo * max lines fix
		
			
				
	
	
		
			150 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """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
 |