forked from genewildish/Mainline
Major changes: - Pipeline architecture with capability-based dependency resolution - Effects plugin system with performance monitoring - Display abstraction with multiple backends (terminal, null, websocket) - Camera system for viewport scrolling - Sensor framework for real-time input - Command-and-control system via ntfy - WebSocket display backend for browser clients - Comprehensive test suite and documentation Issue #48: ADR for preset scripting language included This commit consolidates 110 individual commits into a single feature integration that can be reviewed and tested before further refinement.
126 lines
3.9 KiB
Python
126 lines
3.9 KiB
Python
import pytest
|
|
|
|
from engine.effects.plugins.tint import TintEffect
|
|
from engine.effects.types import EffectConfig
|
|
|
|
|
|
@pytest.fixture
|
|
def effect():
|
|
return TintEffect()
|
|
|
|
|
|
@pytest.fixture
|
|
def effect_with_params(r=255, g=128, b=64, a=0.5):
|
|
e = TintEffect()
|
|
config = EffectConfig(
|
|
enabled=True,
|
|
intensity=1.0,
|
|
params={"r": r, "g": g, "b": b, "a": a},
|
|
)
|
|
e.configure(config)
|
|
return e
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_context():
|
|
class MockContext:
|
|
terminal_width = 80
|
|
terminal_height = 24
|
|
|
|
def get_state(self, key):
|
|
return None
|
|
|
|
return MockContext()
|
|
|
|
|
|
class TestTintEffect:
|
|
def test_name(self, effect):
|
|
assert effect.name == "tint"
|
|
|
|
def test_enabled_by_default(self, effect):
|
|
assert effect.config.enabled is True
|
|
|
|
def test_returns_input_when_empty(self, effect, mock_context):
|
|
result = effect.process([], mock_context)
|
|
assert result == []
|
|
|
|
def test_returns_input_when_transparency_zero(
|
|
self, effect_with_params, mock_context
|
|
):
|
|
effect_with_params.config.params["a"] = 0.0
|
|
buf = ["hello world"]
|
|
result = effect_with_params.process(buf, mock_context)
|
|
assert result == buf
|
|
|
|
def test_applies_tint_to_plain_text(self, effect_with_params, mock_context):
|
|
buf = ["hello world"]
|
|
result = effect_with_params.process(buf, mock_context)
|
|
assert len(result) == 1
|
|
assert "\033[" in result[0] # Has ANSI codes
|
|
assert "hello world" in result[0]
|
|
|
|
def test_tint_preserves_content(self, effect_with_params, mock_context):
|
|
buf = ["hello world", "test line"]
|
|
result = effect_with_params.process(buf, mock_context)
|
|
assert "hello world" in result[0]
|
|
assert "test line" in result[1]
|
|
|
|
def test_rgb_to_ansi256_black(self, effect):
|
|
assert effect._rgb_to_ansi256(0, 0, 0) == 16
|
|
|
|
def test_rgb_to_ansi256_white(self, effect):
|
|
assert effect._rgb_to_ansi256(255, 255, 255) == 231
|
|
|
|
def test_rgb_to_ansi256_red(self, effect):
|
|
color = effect._rgb_to_ansi256(255, 0, 0)
|
|
assert 196 <= color <= 197 # Red in 256 color
|
|
|
|
def test_rgb_to_ansi256_green(self, effect):
|
|
color = effect._rgb_to_ansi256(0, 255, 0)
|
|
assert 34 <= color <= 46
|
|
|
|
def test_rgb_to_ansi256_blue(self, effect):
|
|
color = effect._rgb_to_ansi256(0, 0, 255)
|
|
assert 20 <= color <= 33
|
|
|
|
def test_configure_updates_params(self, effect):
|
|
config = EffectConfig(
|
|
enabled=True,
|
|
intensity=1.0,
|
|
params={"r": 100, "g": 150, "b": 200, "a": 0.8},
|
|
)
|
|
effect.configure(config)
|
|
assert effect.config.params["r"] == 100
|
|
assert effect.config.params["g"] == 150
|
|
assert effect.config.params["b"] == 200
|
|
assert effect.config.params["a"] == 0.8
|
|
|
|
def test_clamp_rgb_values(self, effect_with_params, mock_context):
|
|
effect_with_params.config.params["r"] = 300
|
|
effect_with_params.config.params["g"] = -10
|
|
effect_with_params.config.params["b"] = 1.5
|
|
buf = ["test"]
|
|
result = effect_with_params.process(buf, mock_context)
|
|
assert "\033[" in result[0]
|
|
|
|
def test_clamp_alpha_above_one(self, effect_with_params, mock_context):
|
|
effect_with_params.config.params["a"] = 1.5
|
|
buf = ["test"]
|
|
result = effect_with_params.process(buf, mock_context)
|
|
assert "\033[" in result[0]
|
|
|
|
def test_preserves_empty_lines(self, effect_with_params, mock_context):
|
|
buf = ["hello", "", "world"]
|
|
result = effect_with_params.process(buf, mock_context)
|
|
assert result[1] == ""
|
|
|
|
def test_inlet_types_includes_text_buffer(self, effect):
|
|
from engine.pipeline.core import DataType
|
|
|
|
assert DataType.TEXT_BUFFER in effect.inlet_types
|
|
|
|
def test_outlet_types_includes_text_buffer(self, effect):
|
|
from engine.pipeline.core import DataType
|
|
|
|
assert DataType.TEXT_BUFFER in effect.outlet_types
|