Add comprehensive tests for configuration management and main TUI components

This commit is contained in:
Philip Henning 2025-07-29 21:14:29 +02:00
parent 79069bc2ea
commit 0051932014
4 changed files with 1008 additions and 1 deletions

229
tests/test_config_modal.py Normal file
View file

@ -0,0 +1,229 @@
"""
Tests for the configuration modal TUI component.
This module contains unit tests for the ConfigModal class,
validating modal behavior and configuration interaction.
"""
import pytest
from unittest.mock import Mock, patch
from textual.widgets import Checkbox, Button
from hosts.core.config import Config
from hosts.tui.config_modal import ConfigModal
class TestConfigModal:
"""Test cases for the ConfigModal class."""
def test_modal_initialization(self):
"""Test modal initialization with config."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
assert modal.config == mock_config
def test_modal_compose_method_exists(self):
"""Test that modal has compose method."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = True
modal = ConfigModal(mock_config)
# Test that compose method exists and is callable
assert hasattr(modal, 'compose')
assert callable(modal.compose)
def test_action_save_updates_config(self):
"""Test that save action updates configuration."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
modal.dismiss = Mock()
# Mock the checkbox query
mock_checkbox = Mock()
mock_checkbox.value = True
modal.query_one = Mock(return_value=mock_checkbox)
# Trigger save action
modal.action_save()
# Verify config was updated
mock_config.set.assert_called_once_with("show_default_entries", True)
mock_config.save.assert_called_once()
modal.dismiss.assert_called_once_with(True)
def test_action_save_preserves_false_state(self):
"""Test that save action preserves False checkbox state."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = True
modal = ConfigModal(mock_config)
modal.dismiss = Mock()
# Mock the checkbox query with False value
mock_checkbox = Mock()
mock_checkbox.value = False
modal.query_one = Mock(return_value=mock_checkbox)
# Trigger save action
modal.action_save()
# Verify the False value was saved
mock_config.set.assert_called_once_with("show_default_entries", False)
mock_config.save.assert_called_once()
modal.dismiss.assert_called_once_with(True)
def test_action_cancel_no_config_changes(self):
"""Test that cancel action doesn't modify configuration."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
modal.dismiss = Mock()
# Trigger cancel action
modal.action_cancel()
# Verify config was NOT updated
mock_config.set.assert_not_called()
mock_config.save.assert_not_called()
modal.dismiss.assert_called_once_with(False)
def test_save_button_pressed_event(self):
"""Test save button pressed event handling."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
modal.action_save = Mock()
# Create mock save button
save_button = Mock()
save_button.id = "save-button"
event = Button.Pressed(save_button)
modal.on_button_pressed(event)
modal.action_save.assert_called_once()
def test_cancel_button_pressed_event(self):
"""Test cancel button pressed event handling."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
modal.action_cancel = Mock()
# Create mock cancel button
cancel_button = Mock()
cancel_button.id = "cancel-button"
event = Button.Pressed(cancel_button)
modal.on_button_pressed(event)
modal.action_cancel.assert_called_once()
def test_unknown_button_pressed_ignored(self):
"""Test that unknown button presses are ignored."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
modal.action_save = Mock()
modal.action_cancel = Mock()
# Create a mock button with unknown ID
unknown_button = Mock()
unknown_button.id = "unknown-button"
event = Button.Pressed(unknown_button)
# Should not raise exception
modal.on_button_pressed(event)
# Should not trigger any actions
modal.action_save.assert_not_called()
modal.action_cancel.assert_not_called()
def test_modal_bindings_defined(self):
"""Test that modal has expected key bindings."""
mock_config = Mock(spec=Config)
modal = ConfigModal(mock_config)
# Check that bindings are defined
assert len(modal.BINDINGS) == 2
# Check specific bindings
binding_keys = [binding.key for binding in modal.BINDINGS]
assert "escape" in binding_keys
assert "enter" in binding_keys
binding_actions = [binding.action for binding in modal.BINDINGS]
assert "cancel" in binding_actions
assert "save" in binding_actions
def test_modal_css_defined(self):
"""Test that modal has CSS styling defined."""
mock_config = Mock(spec=Config)
modal = ConfigModal(mock_config)
# Check that CSS is defined
assert hasattr(modal, 'CSS')
assert isinstance(modal.CSS, str)
assert len(modal.CSS) > 0
# Check for key CSS classes
assert "config-container" in modal.CSS
assert "config-title" in modal.CSS
assert "button-row" in modal.CSS
def test_config_method_called_during_initialization(self):
"""Test that config method is called during modal setup."""
mock_config = Mock(spec=Config)
# Test with True
mock_config.should_show_default_entries.return_value = True
modal = ConfigModal(mock_config)
# Verify the config object is stored
assert modal.config == mock_config
# Test with False
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
# Verify the config object is stored
assert modal.config == mock_config
def test_compose_method_signature(self):
"""Test that compose method has the expected signature."""
mock_config = Mock(spec=Config)
mock_config.should_show_default_entries.return_value = False
modal = ConfigModal(mock_config)
# Test that compose method exists and has correct signature
import inspect
sig = inspect.signature(modal.compose)
assert len(sig.parameters) == 0 # No parameters except self
# Test return type annotation if present
if sig.return_annotation != inspect.Signature.empty:
from textual.app import ComposeResult
assert sig.return_annotation == ComposeResult
def test_modal_inheritance(self):
"""Test that ConfigModal properly inherits from ModalScreen."""
mock_config = Mock(spec=Config)
modal = ConfigModal(mock_config)
from textual.screen import ModalScreen
assert isinstance(modal, ModalScreen)
# Should have the config attribute
assert hasattr(modal, 'config')
assert modal.config == mock_config