feat(theme): Implement comprehensive CRT Filter (scanlines, vignette, noise)
This commit is contained in:
@@ -1,30 +1,45 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
import math
|
||||
from src.theme_nerv_fx import ScanlineOverlay, StatusFlicker
|
||||
from src.theme_nerv_fx import CRTFilter, StatusFlicker, AlertPulsing
|
||||
|
||||
class TestThemeNervFx(unittest.TestCase):
|
||||
@patch("src.theme_nerv_fx.imgui")
|
||||
def test_scanline_overlay_render(self, mock_imgui):
|
||||
def test_crt_filter_render(self, mock_imgui):
|
||||
# Setup
|
||||
mock_draw_list = MagicMock()
|
||||
mock_imgui.get_foreground_draw_list.return_value = mock_draw_list
|
||||
mock_imgui.get_color_u32.return_value = 0x12345678
|
||||
|
||||
overlay = ScanlineOverlay()
|
||||
width, height = 100.0, 10.0
|
||||
overlay = CRTFilter()
|
||||
width, height = 800.0, 600.0
|
||||
|
||||
# Act
|
||||
overlay.render(width, height)
|
||||
|
||||
# Assert
|
||||
mock_imgui.get_foreground_draw_list.assert_called_once()
|
||||
# height is 10, range(0, 10, 2) is [0, 2, 4, 6, 8] -> 5 calls
|
||||
self.assertEqual(mock_draw_list.add_line.call_count, 5)
|
||||
# height is 600, range(0, 600, 2) is 300 calls
|
||||
self.assertEqual(mock_draw_list.add_line.call_count, 300)
|
||||
# Vignette: v_steps = 15. height=600 is plenty for all insets.
|
||||
self.assertEqual(mock_draw_list.add_rect.call_count, 15)
|
||||
# Noise: 30 calls to add_rect_filled
|
||||
self.assertEqual(mock_draw_list.add_rect_filled.call_count, 30)
|
||||
|
||||
# Verify some calls
|
||||
mock_draw_list.add_line.assert_any_call((0.0, 0.0), (100.0, 0.0), 0x12345678, 1.0)
|
||||
mock_draw_list.add_line.assert_any_call((0.0, 8.0), (100.0, 8.0), 0x12345678, 1.0)
|
||||
mock_draw_list.add_line.assert_any_call((0.0, 0.0), (800.0, 0.0), 0x12345678, 1.0)
|
||||
mock_draw_list.add_line.assert_any_call((0.0, 598.0), (800.0, 598.0), 0x12345678, 1.0)
|
||||
|
||||
@patch("src.theme_nerv_fx.imgui")
|
||||
def test_crt_filter_disabled(self, mock_imgui):
|
||||
mock_draw_list = MagicMock()
|
||||
mock_imgui.get_foreground_draw_list.return_value = mock_draw_list
|
||||
|
||||
overlay = CRTFilter()
|
||||
overlay.enabled = False
|
||||
overlay.render(800.0, 600.0)
|
||||
|
||||
mock_imgui.get_foreground_draw_list.assert_not_called()
|
||||
|
||||
@patch("src.theme_nerv_fx.time")
|
||||
def test_status_flicker_get_alpha(self, mock_time):
|
||||
@@ -36,21 +51,42 @@ class TestThemeNervFx(unittest.TestCase):
|
||||
self.assertAlmostEqual(flicker.get_alpha(), 0.85)
|
||||
|
||||
# sin(pi/2) = 1 -> 1.0
|
||||
# time * 20.0 = pi/2 -> time = pi/40
|
||||
mock_time.time.return_value = math.pi / 40.0
|
||||
self.assertAlmostEqual(flicker.get_alpha(), 1.0)
|
||||
|
||||
# sin(3pi/2) = -1 -> 0.7
|
||||
# time * 20.0 = 3pi/2 -> time = 3pi/40
|
||||
mock_time.time.return_value = 3 * math.pi / 40.0
|
||||
self.assertAlmostEqual(flicker.get_alpha(), 0.7)
|
||||
|
||||
def test_alert_pulsing_update(self):
|
||||
pulse = AlertPulsing()
|
||||
self.assertFalse(pulse.active)
|
||||
|
||||
# Verify range for many samples
|
||||
for i in range(100):
|
||||
mock_time.time.return_value = i * 0.1
|
||||
alpha = flicker.get_alpha()
|
||||
self.assertGreaterEqual(alpha, 0.7)
|
||||
self.assertLessEqual(alpha, 1.0)
|
||||
pulse.update("error: something failed")
|
||||
self.assertTrue(pulse.active)
|
||||
|
||||
pulse.update("Error: alert")
|
||||
self.assertTrue(pulse.active)
|
||||
|
||||
pulse.update("idle")
|
||||
self.assertFalse(pulse.active)
|
||||
|
||||
@patch("src.theme_nerv_fx.imgui")
|
||||
@patch("src.theme_nerv_fx.time")
|
||||
def test_alert_pulsing_render(self, mock_time, mock_imgui):
|
||||
mock_draw_list = MagicMock()
|
||||
mock_imgui.get_foreground_draw_list.return_value = mock_draw_list
|
||||
mock_imgui.get_color_u32.return_value = 0xFF0000FF
|
||||
|
||||
pulse = AlertPulsing()
|
||||
pulse.active = True
|
||||
|
||||
# sin(0) = 0 -> alpha = 0.05 + 0.15 * (0+1)/2 = 0.125
|
||||
mock_time.time.return_value = 0.0
|
||||
pulse.render(800.0, 600.0)
|
||||
|
||||
mock_imgui.get_foreground_draw_list.assert_called()
|
||||
mock_draw_list.add_rect.assert_called_with((0.0, 0.0), (800.0, 600.0), 0xFF0000FF, 0.0, 0, 10.0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user