development-hub/tests/test_settings.py

250 lines
7.9 KiB
Python

"""Tests for settings and session serialization."""
import json
import pytest
from pathlib import Path
from development_hub.settings import Settings
class TestSettingsPersistence:
"""Test settings persistence and round-trips."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create an isolated Settings instance with temp files."""
# Reset singleton
Settings._instance = None
# Point to temp directory
settings_file = tmp_path / "settings.json"
session_file = tmp_path / "session.json"
monkeypatch.setattr(Settings, "_settings_file", settings_file)
monkeypatch.setattr(Settings, "_session_file", session_file)
settings = Settings()
yield settings
# Clean up singleton
Settings._instance = None
def test_default_values(self, isolated_settings):
"""Settings have sensible defaults."""
settings = isolated_settings
assert settings.deploy_docs_after_creation == True
assert settings.preferred_editor == "auto"
assert settings.auto_start_docs_server == True
assert isinstance(settings.project_search_paths, list)
assert isinstance(settings.project_ignore_folders, list)
def test_set_and_get(self, isolated_settings):
"""Values can be set and retrieved."""
settings = isolated_settings
settings.preferred_editor = "pycharm"
assert settings.preferred_editor == "pycharm"
settings.deploy_docs_after_creation = False
assert settings.deploy_docs_after_creation == False
def test_persistence_round_trip(self, isolated_settings, tmp_path):
"""Settings persist across instances."""
settings = isolated_settings
# Modify settings
settings.preferred_editor = "code"
settings.auto_start_docs_server = False
settings.set("custom_key", "custom_value")
# Reset singleton and create new instance
Settings._instance = None
new_settings = Settings()
assert new_settings.preferred_editor == "code"
assert new_settings.auto_start_docs_server == False
assert new_settings.get("custom_key") == "custom_value"
def test_file_created_on_save(self, isolated_settings, tmp_path):
"""Settings file is created when saving."""
settings = isolated_settings
settings.preferred_editor = "xed"
# Check file exists
assert Settings._settings_file.exists()
def test_invalid_json_handled(self, isolated_settings, tmp_path):
"""Invalid JSON in settings file doesn't crash."""
# Write invalid JSON
Settings._settings_file.parent.mkdir(parents=True, exist_ok=True)
Settings._settings_file.write_text("{ invalid json }")
# Reset and reload
Settings._instance = None
settings = Settings()
# Should fall back to defaults
assert settings.preferred_editor == "auto"
class TestSessionSerialization:
"""Test session state serialization."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create an isolated Settings instance with temp files."""
Settings._instance = None
settings_file = tmp_path / "settings.json"
session_file = tmp_path / "session.json"
monkeypatch.setattr(Settings, "_settings_file", settings_file)
monkeypatch.setattr(Settings, "_session_file", session_file)
settings = Settings()
yield settings
Settings._instance = None
def test_save_load_session_round_trip(self, isolated_settings):
"""Session state round-trips correctly."""
settings = isolated_settings
state = {
"window_geometry": {"x": 100, "y": 200, "width": 800, "height": 600},
"splitter_sizes": [300, 500],
"panes": [
{
"tabs": [
{"type": "terminal", "cwd": "/home/user/project", "title": "Terminal 1"},
{"type": "dashboard", "project_key": "my-project"},
],
"active_tab": 0,
}
],
"active_pane": 0,
}
settings.save_session(state)
loaded = settings.load_session()
assert loaded == state
def test_save_session_creates_directory(self, isolated_settings, tmp_path):
"""Session save creates config directory if needed."""
settings = isolated_settings
# Ensure parent doesn't exist
if Settings._session_file.parent.exists():
import shutil
shutil.rmtree(Settings._session_file.parent)
state = {"test": True}
settings.save_session(state)
assert Settings._session_file.exists()
def test_load_empty_session(self, isolated_settings):
"""Loading non-existent session returns empty dict."""
settings = isolated_settings
loaded = settings.load_session()
assert loaded == {}
def test_load_invalid_session(self, isolated_settings):
"""Invalid JSON in session returns empty dict."""
settings = isolated_settings
Settings._session_file.parent.mkdir(parents=True, exist_ok=True)
Settings._session_file.write_text("not valid json")
loaded = settings.load_session()
assert loaded == {}
def test_session_preserves_types(self, isolated_settings):
"""Session preserves various data types."""
settings = isolated_settings
state = {
"string": "hello",
"number": 42,
"float": 3.14,
"bool": True,
"none": None,
"list": [1, 2, 3],
"nested": {"a": {"b": "c"}},
}
settings.save_session(state)
loaded = settings.load_session()
assert loaded["string"] == "hello"
assert loaded["number"] == 42
assert loaded["float"] == 3.14
assert loaded["bool"] == True
assert loaded["none"] is None
assert loaded["list"] == [1, 2, 3]
assert loaded["nested"]["a"]["b"] == "c"
def test_session_handles_unicode(self, isolated_settings):
"""Session handles unicode characters."""
settings = isolated_settings
state = {
"emoji": "Test",
"japanese": "Hello",
"symbols": "angle bracket < > quotes \" '",
}
settings.save_session(state)
loaded = settings.load_session()
assert loaded == state
class TestGitHostSettings:
"""Test git hosting configuration."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create an isolated Settings instance."""
Settings._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
def test_git_not_configured_by_default(self, isolated_settings):
"""Git is not configured initially."""
settings = isolated_settings
assert settings.is_git_configured == False
def test_git_configured_when_all_set(self, isolated_settings):
"""Git is configured when all required fields are set."""
settings = isolated_settings
settings.git_host_type = "gitea"
settings.git_host_url = "https://gitea.example.com"
settings.git_host_owner = "myuser"
assert settings.is_git_configured == True
def test_git_not_configured_if_missing_field(self, isolated_settings):
"""Git not configured if any required field is missing."""
settings = isolated_settings
settings.git_host_type = "github"
settings.git_host_url = "https://github.com"
# Missing: git_host_owner
assert settings.is_git_configured == False
if __name__ == "__main__":
pytest.main([__file__, "-v"])