Adopt mise for development workflows
- Lock Python and uv versions with mise - Add unified sync, app, test, lint, format, and typecheck tasks - Update development documentation and strengthen type handling
This commit is contained in:
parent
d04ab6feaf
commit
780d9c12fe
19 changed files with 216 additions and 901 deletions
|
|
@ -6,6 +6,7 @@ DNS name entries, validation, and mutual exclusion logic.
|
|||
"""
|
||||
|
||||
import pytest
|
||||
from typing import cast
|
||||
from unittest.mock import Mock
|
||||
from textual.widgets import Input, Checkbox, RadioSet, Static
|
||||
|
||||
|
|
@ -177,10 +178,7 @@ class TestAddEntryModalDNSSupport:
|
|||
self.modal.query_one = Mock(side_effect=Exception("Widget not found"))
|
||||
|
||||
# This should not raise an exception
|
||||
try:
|
||||
self.modal._show_error("dns-error", "Test error message")
|
||||
except Exception:
|
||||
pytest.fail("_show_error should handle missing widgets gracefully")
|
||||
self.modal._show_error("dns-error", "Test error message")
|
||||
|
||||
|
||||
class TestAddEntryModalRadioButtonLogic:
|
||||
|
|
@ -222,7 +220,7 @@ class TestAddEntryModalRadioButtonLogic:
|
|||
event = MockEvent()
|
||||
|
||||
# Call the event handler
|
||||
self.modal.on_radio_set_changed(event)
|
||||
self.modal.on_radio_set_changed(cast(RadioSet.Changed, event))
|
||||
|
||||
# Verify IP section is shown and DNS section is hidden
|
||||
mock_ip_section.remove_class.assert_called_with("hidden")
|
||||
|
|
@ -261,7 +259,7 @@ class TestAddEntryModalRadioButtonLogic:
|
|||
event = MockEvent()
|
||||
|
||||
# Call the event handler
|
||||
self.modal.on_radio_set_changed(event)
|
||||
self.modal.on_radio_set_changed(cast(RadioSet.Changed, event))
|
||||
|
||||
# Verify DNS section is shown and IP section is hidden
|
||||
mock_ip_section.add_class.assert_called_with("hidden")
|
||||
|
|
@ -324,7 +322,7 @@ class TestAddEntryModalSaveLogic:
|
|||
|
||||
# Verify validation was called
|
||||
self.modal._validate_input.assert_called_once_with(
|
||||
"192.168.1.1", "", "example.com, www.example.com", None
|
||||
"192.168.1.1", "", "example.com, www.example.com", False
|
||||
)
|
||||
|
||||
# Verify modal was dismissed with a HostEntry
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ class TestResolveHostname:
|
|||
assert resolution.hostname == "slow.example"
|
||||
assert resolution.resolved_ip is None
|
||||
assert resolution.status == DNSResolutionStatus.RESOLUTION_FAILED
|
||||
assert resolution.error_message is not None
|
||||
assert "Timeout after 1.0s" in resolution.error_message
|
||||
assert resolution.is_success() is False
|
||||
|
||||
|
|
@ -256,6 +257,7 @@ class TestResolveHostnamesBatch:
|
|||
assert resolutions[0].is_success() is True
|
||||
assert resolutions[1].hostname == "error.example"
|
||||
assert resolutions[1].is_success() is False
|
||||
assert resolutions[1].error_message is not None
|
||||
assert "Network error" in resolutions[1].error_message
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ validating application behavior, navigation, and user interactions.
|
|||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, cast
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
|
|
@ -192,7 +193,7 @@ class TestHostsManagerApp:
|
|||
return mock_active_checkbox
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
|
||||
# Add test entry
|
||||
app.hosts_file = HostsFile()
|
||||
|
|
@ -248,7 +249,7 @@ class TestHostsManagerApp:
|
|||
return mock_active_checkbox
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
app.hosts_file = HostsFile()
|
||||
|
||||
app.update_entry_details()
|
||||
|
|
@ -327,7 +328,7 @@ class TestHostsManagerApp:
|
|||
return mock_footer
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
|
||||
# Add test hosts_file for footer status generation
|
||||
app.hosts_file = HostsFile()
|
||||
|
|
@ -837,7 +838,7 @@ class TestHostsManagerApp:
|
|||
return mock_dns_section
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
|
||||
app.edit_handler.update_field_visibility(show_ip=True, show_dns=False)
|
||||
|
||||
|
|
@ -867,7 +868,7 @@ class TestHostsManagerApp:
|
|||
return mock_dns_section
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
|
||||
app.edit_handler.update_field_visibility(show_ip=False, show_dns=True)
|
||||
|
||||
|
|
@ -908,7 +909,7 @@ class TestHostsManagerApp:
|
|||
return mock_dns_radio
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
app.edit_handler.handle_entry_type_change = Mock()
|
||||
|
||||
# Test that the method can be called without errors
|
||||
|
|
@ -962,7 +963,7 @@ class TestHostsManagerApp:
|
|||
return mock_dns_input
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
app.edit_handler.handle_entry_type_change = Mock()
|
||||
|
||||
# Mock the set_timer method to avoid event loop issues in tests
|
||||
|
|
@ -1017,7 +1018,7 @@ class TestHostsManagerApp:
|
|||
return mock_active_checkbox
|
||||
return Mock()
|
||||
|
||||
app.query_one = mock_query_one
|
||||
cast(Any, app).query_one = mock_query_one
|
||||
|
||||
# Add test entry
|
||||
app.hosts_file = HostsFile()
|
||||
|
|
@ -1156,10 +1157,12 @@ class TestHostsManagerApp:
|
|||
assert app.hosts_file.entries[0].is_active is False
|
||||
assert app.manager.can_undo()
|
||||
assert not app.manager.can_redo()
|
||||
app.table_handler.populate_entries_table.assert_called_once()
|
||||
app.table_handler.move_cursor_to_entry_index.assert_called_once_with(0)
|
||||
app.details_handler.update_entry_details.assert_called_once()
|
||||
app.update_status.assert_called_once_with(
|
||||
cast(Mock, app.table_handler.populate_entries_table).assert_called_once()
|
||||
cast(
|
||||
Mock, app.table_handler.move_cursor_to_entry_index
|
||||
).assert_called_once_with(0)
|
||||
cast(Mock, app.details_handler.update_entry_details).assert_called_once()
|
||||
cast(Mock, app.update_status).assert_called_once_with(
|
||||
"❌ Undo save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1204,10 +1207,12 @@ class TestHostsManagerApp:
|
|||
assert app.hosts_file.entries[0].is_active is True
|
||||
assert not app.manager.can_undo()
|
||||
assert app.manager.can_redo()
|
||||
app.table_handler.populate_entries_table.assert_called_once()
|
||||
app.table_handler.move_cursor_to_entry_index.assert_called_once_with(0)
|
||||
app.details_handler.update_entry_details.assert_called_once()
|
||||
app.update_status.assert_called_once_with(
|
||||
cast(Mock, app.table_handler.populate_entries_table).assert_called_once()
|
||||
cast(
|
||||
Mock, app.table_handler.move_cursor_to_entry_index
|
||||
).assert_called_once_with(0)
|
||||
cast(Mock, app.details_handler.update_entry_details).assert_called_once()
|
||||
cast(Mock, app.update_status).assert_called_once_with(
|
||||
"❌ Redo save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1234,7 +1239,7 @@ class TestHostsManagerApp:
|
|||
assert app.selected_entry_index == 0
|
||||
assert not app.manager.can_undo()
|
||||
assert app.manager.can_redo()
|
||||
app.update_status.assert_called_once_with(
|
||||
cast(Mock, app.update_status).assert_called_once_with(
|
||||
"❌ Toggle save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1261,7 +1266,7 @@ class TestHostsManagerApp:
|
|||
]
|
||||
assert app.selected_entry_index == 1
|
||||
assert not app.manager.can_undo()
|
||||
app.update_status.assert_called_once_with(
|
||||
cast(Mock, app.update_status).assert_called_once_with(
|
||||
"❌ Move save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1287,7 +1292,7 @@ class TestHostsManagerApp:
|
|||
]
|
||||
assert app.selected_entry_index == 0
|
||||
assert not app.manager.can_undo()
|
||||
app.update_status.assert_called_once_with(
|
||||
cast(Mock, app.update_status).assert_called_once_with(
|
||||
"❌ Add save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1378,7 +1383,7 @@ class TestHostsManagerApp:
|
|||
]
|
||||
assert app.selected_entry_index == 1
|
||||
assert not app.manager.can_undo()
|
||||
app.update_status.assert_called_once_with(
|
||||
cast(Mock, app.update_status).assert_called_once_with(
|
||||
"❌ Delete save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1503,7 +1508,7 @@ class TestHostsManagerApp:
|
|||
assert entry.last_resolved == original_time
|
||||
assert entry.dns_resolution_status == "match"
|
||||
assert app.selected_entry_index == 0
|
||||
app.update_status.assert_any_call(
|
||||
cast(Mock, app.update_status).assert_any_call(
|
||||
"❌ DNS refresh save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1549,7 +1554,7 @@ class TestHostsManagerApp:
|
|||
assert entry.resolved_ip == "192.0.2.1"
|
||||
assert entry.last_resolved == original_time
|
||||
assert entry.dns_resolution_status == "match"
|
||||
app.update_status.assert_any_call(
|
||||
cast(Mock, app.update_status).assert_any_call(
|
||||
"❌ DNS refresh save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
@ -1638,7 +1643,7 @@ class TestHostsManagerApp:
|
|||
assert restored.dns_resolution_status is None
|
||||
assert restored.is_active is False
|
||||
assert app.manager.can_undo()
|
||||
app.update_status.assert_any_call(
|
||||
cast(Mock, app.update_status).assert_any_call(
|
||||
"❌ DNS activation save failed; previous state restored: Permission denied"
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue