From 2c5a8d969c2fb8ca54b4f1c69c7c8deb9fef6a61 Mon Sep 17 00:00:00 2001 From: phg Date: Fri, 4 Sep 2026 09:04:29 +0200 Subject: [PATCH] Handle negative cursor rows with hidden entries - Guard against negative display indexes when no entries are visible - Add regression coverage for Textual's -1 cursor row --- src/hosts/tui/table_handler.py | 2 +- tests/test_main.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/hosts/tui/table_handler.py b/src/hosts/tui/table_handler.py index b3c2d5c..0384257 100644 --- a/src/hosts/tui/table_handler.py +++ b/src/hosts/tui/table_handler.py @@ -109,7 +109,7 @@ class TableHandler: def display_index_to_actual_index(self, display_index: int) -> int: """Convert a display table index to the actual hosts file entry index.""" visible_entries = self.get_visible_entries() - if display_index >= len(visible_entries): + if display_index < 0 or display_index >= len(visible_entries): return 0 target_entry = visible_entries[display_index] diff --git a/tests/test_main.py b/tests/test_main.py index 4c95e5d..520fa02 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -593,6 +593,34 @@ class TestHostsManagerApp: app.details_handler.update_entry_details.assert_called_once() app.table_handler.display_index_to_actual_index.assert_called_once_with(2) + def test_data_table_row_highlighted_with_no_visible_entries(self): + """Handle Textual's negative cursor row when all entries are hidden.""" + mock_parser = Mock(spec=HostsParser) + mock_config = Mock(spec=Config) + mock_config.should_show_default_entries.return_value = False + mock_config.is_default_entry.return_value = True + + with ( + patch("hosts.tui.app.HostsParser", return_value=mock_parser), + patch("hosts.tui.app.Config", return_value=mock_config), + ): + app = HostsManagerApp() + app.hosts_file = HostsFile( + entries=[HostEntry(ip_address="127.0.0.1", hostnames=["localhost"])] + ) + app.details_handler.update_entry_details = Mock() + + mock_table = Mock() + mock_table.id = "entries-table" + event = Mock() + event.data_table = mock_table + event.cursor_row = -1 + + app.on_data_table_row_highlighted(event) + + assert app.selected_entry_index == 0 + app.details_handler.update_entry_details.assert_called_once() + def test_data_table_header_selected_ip_column(self): """Test DataTable header selection for IP column.""" mock_parser = Mock(spec=HostsParser)