import pytest from 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