Split monolithic scroll.py into focused modules: - viewport.py: terminal size (tw/th), ANSI positioning helpers - frame.py: FrameTimer class, scroll step calculation - layers.py: message overlay, ticker zone, firehose rendering - scroll.py: simplified orchestrator, imports from new modules Add stream controller and event types for future event-driven architecture: - controller.py: StreamController for source initialization and stream lifecycle - events.py: EventType enum and event dataclasses (HeadlineEvent, FrameTickEvent, etc.) Added tests for new modules: - test_viewport.py: 8 tests for viewport utilities - test_frame.py: 10 tests for frame timing - test_layers.py: 13 tests for layer compositing - test_events.py: 11 tests for event types - test_controller.py: 6 tests for stream controller This enables: - Testable chunks with clear responsibilities - Reusable viewport utilities across modules - Better separation of concerns in render pipeline - Foundation for future event-driven architecture Also includes Phase 1 documentation updates in code comments.
113 lines
3.2 KiB
Python
113 lines
3.2 KiB
Python
"""
|
|
Tests for engine.events module.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
|
|
from engine import events
|
|
|
|
|
|
class TestEventType:
|
|
"""Tests for EventType enum."""
|
|
|
|
def test_event_types_exist(self):
|
|
"""All expected event types exist."""
|
|
assert hasattr(events.EventType, "NEW_HEADLINE")
|
|
assert hasattr(events.EventType, "FRAME_TICK")
|
|
assert hasattr(events.EventType, "MIC_LEVEL")
|
|
assert hasattr(events.EventType, "NTFY_MESSAGE")
|
|
assert hasattr(events.EventType, "STREAM_START")
|
|
assert hasattr(events.EventType, "STREAM_END")
|
|
|
|
|
|
class TestHeadlineEvent:
|
|
"""Tests for HeadlineEvent dataclass."""
|
|
|
|
def test_create_headline_event(self):
|
|
"""HeadlineEvent can be created with required fields."""
|
|
e = events.HeadlineEvent(
|
|
title="Test Headline",
|
|
source="Test Source",
|
|
timestamp="12:00",
|
|
)
|
|
assert e.title == "Test Headline"
|
|
assert e.source == "Test Source"
|
|
assert e.timestamp == "12:00"
|
|
|
|
def test_headline_event_optional_language(self):
|
|
"""HeadlineEvent supports optional language field."""
|
|
e = events.HeadlineEvent(
|
|
title="Test",
|
|
source="Test",
|
|
timestamp="12:00",
|
|
language="ja",
|
|
)
|
|
assert e.language == "ja"
|
|
|
|
|
|
class TestFrameTickEvent:
|
|
"""Tests for FrameTickEvent dataclass."""
|
|
|
|
def test_create_frame_tick_event(self):
|
|
"""FrameTickEvent can be created."""
|
|
now = datetime.now()
|
|
e = events.FrameTickEvent(
|
|
frame_number=100,
|
|
timestamp=now,
|
|
delta_seconds=0.05,
|
|
)
|
|
assert e.frame_number == 100
|
|
assert e.timestamp == now
|
|
assert e.delta_seconds == 0.05
|
|
|
|
|
|
class TestMicLevelEvent:
|
|
"""Tests for MicLevelEvent dataclass."""
|
|
|
|
def test_create_mic_level_event(self):
|
|
"""MicLevelEvent can be created."""
|
|
now = datetime.now()
|
|
e = events.MicLevelEvent(
|
|
db_level=60.0,
|
|
excess_above_threshold=10.0,
|
|
timestamp=now,
|
|
)
|
|
assert e.db_level == 60.0
|
|
assert e.excess_above_threshold == 10.0
|
|
|
|
|
|
class TestNtfyMessageEvent:
|
|
"""Tests for NtfyMessageEvent dataclass."""
|
|
|
|
def test_create_ntfy_message_event(self):
|
|
"""NtfyMessageEvent can be created with required fields."""
|
|
e = events.NtfyMessageEvent(
|
|
title="Test Title",
|
|
body="Test Body",
|
|
)
|
|
assert e.title == "Test Title"
|
|
assert e.body == "Test Body"
|
|
assert e.message_id is None
|
|
|
|
def test_ntfy_message_event_with_id(self):
|
|
"""NtfyMessageEvent supports optional message_id."""
|
|
e = events.NtfyMessageEvent(
|
|
title="Test",
|
|
body="Test",
|
|
message_id="abc123",
|
|
)
|
|
assert e.message_id == "abc123"
|
|
|
|
|
|
class TestStreamEvent:
|
|
"""Tests for StreamEvent dataclass."""
|
|
|
|
def test_create_stream_event(self):
|
|
"""StreamEvent can be created."""
|
|
e = events.StreamEvent(
|
|
event_type=events.EventType.STREAM_START,
|
|
headline_count=100,
|
|
)
|
|
assert e.event_type == events.EventType.STREAM_START
|
|
assert e.headline_count == 100
|