Fix #7: persist undo and redo results immediately

This commit is contained in:
Philip Henning 2026-09-03 19:39:12 +02:00
parent 68a9696e7d
commit 89b37239b2
4 changed files with 149 additions and 22 deletions

View file

@ -986,6 +986,108 @@ class TestHostsManagerApp:
# Should start DNS resolution
app.run_worker.assert_called()
def test_undo_saves_the_reverted_hosts_file(self):
"""Undo persists its result before refreshing the interface."""
with patch("hosts.tui.app.HostsParser"), patch("hosts.tui.app.Config"):
app = HostsManagerApp()
app.edit_mode = True
app.manager.edit_mode = True
app.hosts_file = HostsFile()
entry = HostEntry(ip_address="192.168.1.1", hostnames=["test.local"])
app.hosts_file.add_entry(entry)
app.manager.execute_toggle_command(app.hosts_file, 0)
app.manager.save_hosts_file = Mock(return_value=(True, "Hosts file saved"))
app.table_handler.populate_entries_table = Mock()
app.details_handler.update_entry_details = Mock()
app.update_status = Mock()
app.action_undo()
assert entry.is_active is True
app.manager.save_hosts_file.assert_called_once_with(app.hosts_file)
app.table_handler.populate_entries_table.assert_called_once()
app.details_handler.update_entry_details.assert_called_once()
def test_undo_save_failure_restores_the_persisted_state(self):
"""Undo failure leaves the display and undo history at the saved state."""
with patch("hosts.tui.app.HostsParser"), patch("hosts.tui.app.Config"):
app = HostsManagerApp()
app.edit_mode = True
app.manager.edit_mode = True
app.hosts_file = HostsFile()
entry = HostEntry(ip_address="192.168.1.1", hostnames=["test.local"])
app.hosts_file.add_entry(entry)
app.manager.execute_toggle_command(app.hosts_file, 0)
app.manager.save_hosts_file = Mock(
return_value=(False, "Permission denied")
)
app.table_handler.populate_entries_table = Mock()
app.details_handler.update_entry_details = Mock()
app.update_status = Mock()
app.action_undo()
assert entry.is_active is False
assert app.manager.can_undo()
assert not app.manager.can_redo()
app.table_handler.populate_entries_table.assert_not_called()
app.details_handler.update_entry_details.assert_not_called()
app.update_status.assert_called_once_with(
"❌ Undo save failed; previous state restored: Permission denied"
)
def test_redo_saves_the_reapplied_hosts_file(self):
"""Redo persists its result before refreshing the interface."""
with patch("hosts.tui.app.HostsParser"), patch("hosts.tui.app.Config"):
app = HostsManagerApp()
app.edit_mode = True
app.manager.edit_mode = True
app.hosts_file = HostsFile()
entry = HostEntry(ip_address="192.168.1.1", hostnames=["test.local"])
app.hosts_file.add_entry(entry)
app.manager.execute_toggle_command(app.hosts_file, 0)
app.manager.undo_last_operation(app.hosts_file)
app.manager.save_hosts_file = Mock(return_value=(True, "Hosts file saved"))
app.table_handler.populate_entries_table = Mock()
app.details_handler.update_entry_details = Mock()
app.update_status = Mock()
app.action_redo()
assert entry.is_active is False
app.manager.save_hosts_file.assert_called_once_with(app.hosts_file)
app.table_handler.populate_entries_table.assert_called_once()
app.details_handler.update_entry_details.assert_called_once()
def test_redo_save_failure_restores_the_persisted_state(self):
"""Redo failure leaves the display and redo history at the saved state."""
with patch("hosts.tui.app.HostsParser"), patch("hosts.tui.app.Config"):
app = HostsManagerApp()
app.edit_mode = True
app.manager.edit_mode = True
app.hosts_file = HostsFile()
entry = HostEntry(ip_address="192.168.1.1", hostnames=["test.local"])
app.hosts_file.add_entry(entry)
app.manager.execute_toggle_command(app.hosts_file, 0)
app.manager.undo_last_operation(app.hosts_file)
app.manager.save_hosts_file = Mock(
return_value=(False, "Permission denied")
)
app.table_handler.populate_entries_table = Mock()
app.details_handler.update_entry_details = Mock()
app.update_status = Mock()
app.action_redo()
assert entry.is_active is True
assert not app.manager.can_undo()
assert app.manager.can_redo()
app.table_handler.populate_entries_table.assert_not_called()
app.details_handler.update_entry_details.assert_not_called()
app.update_status.assert_called_once_with(
"❌ Redo save failed; previous state restored: Permission denied"
)
def test_main_function(self):
"""Test main entry point function."""
with patch("hosts.main.HostsManagerApp") as mock_app_class: