forked from genewildish/Mainline
- Add pyproject.toml with modern Python packaging (PEP 517/518) - Add uv-based dependency management replacing inline venv bootstrap - Add requirements.txt and requirements-dev.txt for compatibility - Add mise.toml with dev tasks (test, lint, run, sync, ci) - Add .python-version pinned to Python 3.12 - Add comprehensive pytest test suite (73 tests) for: - engine/config, filter, terminal, sources, mic, ntfy modules - Configure pytest with coverage reporting (16% total, 100% on tested modules) - Configure ruff for linting with Python 3.10+ target - Remove redundant venv bootstrap code from mainline.py - Update .gitignore for uv/venv artifacts Run 'uv sync' to install dependencies, 'uv run pytest' to test.
125 lines
4.2 KiB
Python
125 lines
4.2 KiB
Python
"""
|
|
Tests for engine.terminal module.
|
|
"""
|
|
|
|
import io
|
|
import sys
|
|
from unittest.mock import patch
|
|
|
|
from engine import terminal
|
|
|
|
|
|
class TestTerminalDimensions:
|
|
"""Tests for terminal width/height functions."""
|
|
|
|
def test_tw_returns_columns(self):
|
|
"""tw() returns terminal width."""
|
|
with patch.object(sys.stdout, "isatty", return_value=True):
|
|
with patch("os.get_terminal_size") as mock_size:
|
|
mock_size.return_value = io.StringIO("columns=120")
|
|
mock_size.columns = 120
|
|
result = terminal.tw()
|
|
assert isinstance(result, int)
|
|
|
|
def test_th_returns_lines(self):
|
|
"""th() returns terminal height."""
|
|
with patch.object(sys.stdout, "isatty", return_value=True):
|
|
with patch("os.get_terminal_size") as mock_size:
|
|
mock_size.return_value = io.StringIO("lines=30")
|
|
mock_size.lines = 30
|
|
result = terminal.th()
|
|
assert isinstance(result, int)
|
|
|
|
def test_tw_fallback_on_error(self):
|
|
"""tw() falls back to 80 on error."""
|
|
with patch("os.get_terminal_size", side_effect=OSError):
|
|
result = terminal.tw()
|
|
assert result == 80
|
|
|
|
def test_th_fallback_on_error(self):
|
|
"""th() falls back to 24 on error."""
|
|
with patch("os.get_terminal_size", side_effect=OSError):
|
|
result = terminal.th()
|
|
assert result == 24
|
|
|
|
|
|
class TestANSICodes:
|
|
"""Tests for ANSI escape code constants."""
|
|
|
|
def test_ansi_constants_exist(self):
|
|
"""All ANSI constants are defined."""
|
|
assert terminal.RST == "\033[0m"
|
|
assert terminal.BOLD == "\033[1m"
|
|
assert terminal.DIM == "\033[2m"
|
|
|
|
def test_green_shades_defined(self):
|
|
"""Green gradient colors are defined."""
|
|
assert terminal.G_HI == "\033[38;5;46m"
|
|
assert terminal.G_MID == "\033[38;5;34m"
|
|
assert terminal.G_LO == "\033[38;5;22m"
|
|
|
|
def test_white_shades_defined(self):
|
|
"""White/gray tones are defined."""
|
|
assert terminal.W_COOL == "\033[38;5;250m"
|
|
assert terminal.W_DIM == "\033[2;38;5;245m"
|
|
|
|
def test_cursor_controls_defined(self):
|
|
"""Cursor control codes are defined."""
|
|
assert "?" in terminal.CURSOR_OFF
|
|
assert "?" in terminal.CURSOR_ON
|
|
|
|
|
|
class TestTypeOut:
|
|
"""Tests for type_out function."""
|
|
|
|
@patch("sys.stdout", new_callable=io.StringIO)
|
|
@patch("time.sleep")
|
|
def test_type_out_writes_text(self, mock_sleep, mock_stdout):
|
|
"""type_out writes text to stdout."""
|
|
with patch("random.random", return_value=0.5):
|
|
terminal.type_out("Hi", color=terminal.G_HI)
|
|
output = mock_stdout.getvalue()
|
|
assert len(output) > 0
|
|
|
|
@patch("time.sleep")
|
|
def test_type_out_uses_color(self, mock_sleep):
|
|
"""type_out applies color codes."""
|
|
with patch("sys.stdout", new_callable=io.StringIO):
|
|
with patch("random.random", return_value=0.5):
|
|
terminal.type_out("Test", color=terminal.G_HI)
|
|
|
|
|
|
class TestSlowPrint:
|
|
"""Tests for slow_print function."""
|
|
|
|
@patch("sys.stdout", new_callable=io.StringIO)
|
|
@patch("time.sleep")
|
|
def test_slow_print_writes_text(self, mock_sleep, mock_stdout):
|
|
"""slow_print writes text to stdout."""
|
|
terminal.slow_print("Hi", color=terminal.G_DIM, delay=0)
|
|
output = mock_stdout.getvalue()
|
|
assert len(output) > 0
|
|
|
|
|
|
class TestBootLn:
|
|
"""Tests for boot_ln function."""
|
|
|
|
@patch("sys.stdout", new_callable=io.StringIO)
|
|
@patch("time.sleep")
|
|
def test_boot_ln_writes_label_and_status(self, mock_sleep, mock_stdout):
|
|
"""boot_ln shows label and status."""
|
|
with patch("random.uniform", return_value=0):
|
|
terminal.boot_ln("Loading", "OK", ok=True)
|
|
output = mock_stdout.getvalue()
|
|
assert "Loading" in output
|
|
assert "OK" in output
|
|
|
|
@patch("sys.stdout", new_callable=io.StringIO)
|
|
@patch("time.sleep")
|
|
def test_boot_ln_error_status(self, mock_sleep, mock_stdout):
|
|
"""boot_ln shows red for error status."""
|
|
with patch("random.uniform", return_value=0):
|
|
terminal.boot_ln("Loading", "FAIL", ok=False)
|
|
output = mock_stdout.getvalue()
|
|
assert "FAIL" in output
|