""" Tests for engine.config module. """ import sys import tempfile from pathlib import Path from unittest.mock import patch from engine import config class TestArgValue: """Tests for _arg_value helper.""" def test_returns_value_when_flag_present(self): """Returns the value following the flag.""" with patch.object(sys, "argv", ["prog", "--font-file", "test.otf"]): result = config._arg_value("--font-file") assert result == "test.otf" def test_returns_none_when_flag_missing(self): """Returns None when flag is not present.""" with patch.object(sys, "argv", ["prog"]): result = config._arg_value("--font-file") assert result is None def test_returns_none_when_no_value(self): """Returns None when flag is last.""" with patch.object(sys, "argv", ["prog", "--font-file"]): result = config._arg_value("--font-file") assert result is None class TestArgInt: """Tests for _arg_int helper.""" def test_parses_valid_int(self): """Parses valid integer.""" with patch.object(sys, "argv", ["prog", "--font-index", "5"]): result = config._arg_int("--font-index", 0) assert result == 5 def test_returns_default_on_invalid(self): """Returns default on invalid input.""" with patch.object(sys, "argv", ["prog", "--font-index", "abc"]): result = config._arg_int("--font-index", 0) assert result == 0 def test_returns_default_when_missing(self): """Returns default when flag missing.""" with patch.object(sys, "argv", ["prog"]): result = config._arg_int("--font-index", 10) assert result == 10 class TestResolveFontPath: """Tests for _resolve_font_path helper.""" def test_returns_absolute_paths(self): """Absolute paths are returned as-is.""" result = config._resolve_font_path("/absolute/path.otf") assert result == "/absolute/path.otf" def test_resolves_relative_paths(self): """Relative paths are resolved to repo root.""" result = config._resolve_font_path("fonts/test.otf") assert str(config._REPO_ROOT) in result def test_expands_user_home(self): """Tilde paths are expanded.""" with patch("pathlib.Path.expanduser", return_value=Path("/home/user/fonts")): result = config._resolve_font_path("~/fonts/test.otf") assert isinstance(result, str) class TestListFontFiles: """Tests for _list_font_files helper.""" def test_returns_empty_for_missing_dir(self): """Returns empty list for missing directory.""" result = config._list_font_files("/nonexistent/directory") assert result == [] def test_filters_by_extension(self): """Only returns valid font extensions.""" with tempfile.TemporaryDirectory() as tmpdir: Path(tmpdir, "valid.otf").touch() Path(tmpdir, "valid.ttf").touch() Path(tmpdir, "invalid.txt").touch() Path(tmpdir, "image.png").touch() result = config._list_font_files(tmpdir) assert len(result) == 2 assert all(f.endswith((".otf", ".ttf")) for f in result) def test_sorts_alphabetically(self): """Results are sorted alphabetically.""" with tempfile.TemporaryDirectory() as tmpdir: Path(tmpdir, "zfont.otf").touch() Path(tmpdir, "afont.otf").touch() result = config._list_font_files(tmpdir) filenames = [Path(f).name for f in result] assert filenames == ["afont.otf", "zfont.otf"] class TestDefaults: """Tests for default configuration values.""" def test_headline_limit(self): """HEADLINE_LIMIT has sensible default.""" assert config.HEADLINE_LIMIT > 0 def test_feed_timeout(self): """FEED_TIMEOUT has sensible default.""" assert config.FEED_TIMEOUT > 0 def test_font_extensions(self): """Font extensions are defined.""" assert ".otf" in config._FONT_EXTENSIONS assert ".ttf" in config._FONT_EXTENSIONS assert ".ttc" in config._FONT_EXTENSIONS class TestGlyphs: """Tests for glyph constants.""" def test_glitch_glyphs_defined(self): """GLITCH glyphs are defined.""" assert len(config.GLITCH) > 0 def test_kata_glyphs_defined(self): """KATA glyphs are defined.""" assert len(config.KATA) > 0 class TestSetFontSelection: """Tests for set_font_selection function.""" def test_updates_font_path(self): """Updates FONT_PATH globally.""" original = config.FONT_PATH config.set_font_selection(font_path="/new/path.otf") assert config.FONT_PATH == "/new/path.otf" config.FONT_PATH = original def test_updates_font_index(self): """Updates FONT_INDEX globally.""" original = config.FONT_INDEX config.set_font_selection(font_index=5) assert config.FONT_INDEX == 5 config.FONT_INDEX = original def test_handles_none_values(self): """Handles None values gracefully.""" original_path = config.FONT_PATH original_index = config.FONT_INDEX config.set_font_selection(font_path=None, font_index=None) assert original_path == config.FONT_PATH assert original_index == config.FONT_INDEX