Fix #6: Make advanced filtering reachable from the TUI
This commit is contained in:
parent
780d9c12fe
commit
6d4a4ccc19
6 changed files with 734 additions and 0 deletions
|
|
@ -3,9 +3,15 @@
|
|||
from contextlib import contextmanager
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from textual.app import SuspendNotSupported
|
||||
from textual.widgets import HelpPanel, RadioButton, Static
|
||||
|
||||
from src.hosts.core.filters import FilterOptions
|
||||
from src.hosts.core.models import HostEntry, HostsFile
|
||||
from src.hosts.tui.app import HostsManagerApp
|
||||
from src.hosts.tui.custom_footer import CustomFooter
|
||||
from src.hosts.tui.filter_modal import FilterModal
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
|
@ -14,6 +20,89 @@ def suspended_tui():
|
|||
yield
|
||||
|
||||
|
||||
def app_with_filterable_entries() -> HostsManagerApp:
|
||||
"""Create an app whose filter workflow cannot access the system Hosts File."""
|
||||
app = HostsManagerApp()
|
||||
app.hosts_file = HostsFile(
|
||||
entries=[
|
||||
HostEntry(ip_address="192.0.2.1", hostnames=["active.test"]),
|
||||
HostEntry(
|
||||
ip_address="192.0.2.2",
|
||||
hostnames=["inactive.test"],
|
||||
is_active=False,
|
||||
),
|
||||
]
|
||||
)
|
||||
app.load_hosts_file = Mock()
|
||||
return app
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_filter_shortcut_opens_modal_and_applies_the_selected_filter():
|
||||
"""The filter shortcut opens a modal whose Apply action changes the view state."""
|
||||
app = app_with_filterable_entries()
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
footer = app.query_one("#custom-footer", CustomFooter)
|
||||
footer_text = footer.query_one("#footer-right", Static).render()
|
||||
assert "ctrl+f Filter entries" in str(footer_text)
|
||||
|
||||
app.action_help()
|
||||
await pilot.pause()
|
||||
assert isinstance(app.query_one(HelpPanel), HelpPanel)
|
||||
assert any(
|
||||
binding.action == "show_filters" and binding.description == "Filter entries"
|
||||
for _, binding, _, _ in app.screen.active_bindings.values()
|
||||
)
|
||||
app.action_help()
|
||||
await pilot.pause()
|
||||
|
||||
await pilot.press("ctrl+f")
|
||||
|
||||
assert isinstance(app.screen, FilterModal)
|
||||
app.screen.query_one("#status-active", RadioButton).value = True
|
||||
await pilot.pause()
|
||||
await pilot.click("#apply")
|
||||
await pilot.pause()
|
||||
|
||||
assert app.current_filter_options.active_only
|
||||
assert not app.current_filter_options.show_inactive
|
||||
assert [entry.hostnames[0] for entry in app.get_visible_entries()] == [
|
||||
"active.test"
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_filter_reset_clears_filters_and_cancel_preserves_applied_filters():
|
||||
"""Reset clears the form on Apply, while Cancel leaves the applied filter alone."""
|
||||
app = app_with_filterable_entries()
|
||||
app.current_filter_options = FilterOptions(
|
||||
active_only=True,
|
||||
show_inactive=False,
|
||||
)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press("ctrl+f")
|
||||
await pilot.click("#reset")
|
||||
await pilot.click("#apply")
|
||||
await pilot.pause()
|
||||
|
||||
assert app.current_filter_options.is_empty()
|
||||
|
||||
await pilot.press("ctrl+f")
|
||||
assert isinstance(app.screen, FilterModal)
|
||||
app.screen.query_one("#status-active", RadioButton).value = True
|
||||
await pilot.pause()
|
||||
await pilot.press("escape")
|
||||
await pilot.pause()
|
||||
|
||||
assert app.current_filter_options.is_empty()
|
||||
assert [entry.hostnames[0] for entry in app.get_visible_entries()] == [
|
||||
"active.test",
|
||||
"inactive.test",
|
||||
]
|
||||
|
||||
|
||||
class TestPrivilegedModeAuthorization:
|
||||
"""Test the user-visible privileged-mode authorization flow."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue