""" Tests for PipelineIntrospectionSource. """ from engine.data_sources.pipeline_introspection import PipelineIntrospectionSource class TestPipelineIntrospectionSource: """Tests for PipelineIntrospectionSource.""" def test_basic_init(self): """Source initializes with defaults.""" source = PipelineIntrospectionSource() assert source.name == "pipeline-inspect" assert source.is_dynamic is True assert source.frame == 0 assert source.ready is False def test_init_with_params(self): """Source initializes with custom params.""" source = PipelineIntrospectionSource(viewport_width=100, viewport_height=40) assert source.viewport_width == 100 assert source.viewport_height == 40 def test_inlet_outlet_types(self): """Source has correct inlet/outlet types.""" source = PipelineIntrospectionSource() from engine.pipeline.core import DataType assert DataType.NONE in source.inlet_types assert DataType.SOURCE_ITEMS in source.outlet_types def test_fetch_returns_items(self): """fetch() returns SourceItem list.""" source = PipelineIntrospectionSource() items = source.fetch() assert len(items) == 1 assert items[0].source == "pipeline-inspect" def test_fetch_increments_frame(self): """fetch() increments frame counter when ready.""" source = PipelineIntrospectionSource() assert source.frame == 0 # Set pipeline first to make source ready class MockPipeline: stages = {} execution_order = [] def get_metrics_summary(self): return {"avg_ms": 10.0, "fps": 60, "stages": {}} def get_frame_times(self): return [10.0, 12.0, 11.0] source.set_pipeline(MockPipeline()) assert source.ready is True source.fetch() assert source.frame == 1 source.fetch() assert source.frame == 2 def test_get_items(self): """get_items() returns list of SourceItems.""" source = PipelineIntrospectionSource() items = source.get_items() assert isinstance(items, list) assert len(items) > 0 assert items[0].source == "pipeline-inspect" def test_set_pipeline(self): """set_pipeline() marks source as ready.""" source = PipelineIntrospectionSource() assert source.ready is False class MockPipeline: stages = {} execution_order = [] def get_metrics_summary(self): return {"avg_ms": 10.0, "fps": 60, "stages": {}} def get_frame_times(self): return [10.0, 12.0, 11.0] source.set_pipeline(MockPipeline()) assert source.ready is True class TestPipelineIntrospectionRender: """Tests for rendering methods.""" def test_render_header_no_pipeline(self): """_render_header returns default when no pipeline.""" source = PipelineIntrospectionSource() lines = source._render_header() assert len(lines) == 1 assert "PIPELINE INTROSPECTION" in lines[0] def test_render_bar(self): """_render_bar creates correct bar.""" source = PipelineIntrospectionSource() bar = source._render_bar(50, 10) assert len(bar) == 10 assert bar.count("█") == 5 assert bar.count("░") == 5 def test_render_bar_zero(self): """_render_bar handles zero percentage.""" source = PipelineIntrospectionSource() bar = source._render_bar(0, 10) assert bar == "░" * 10 def test_render_bar_full(self): """_render_bar handles 100%.""" source = PipelineIntrospectionSource() bar = source._render_bar(100, 10) assert bar == "█" * 10 def test_render_sparkline(self): """_render_sparkline creates sparkline.""" source = PipelineIntrospectionSource() values = [1.0, 2.0, 3.0, 4.0, 5.0] sparkline = source._render_sparkline(values, 10) assert len(sparkline) == 10 def test_render_sparkline_empty(self): """_render_sparkline handles empty values.""" source = PipelineIntrospectionSource() sparkline = source._render_sparkline([], 10) assert sparkline == " " * 10 def test_render_footer_no_pipeline(self): """_render_footer shows collecting data when no pipeline.""" source = PipelineIntrospectionSource() lines = source._render_footer() assert len(lines) >= 2 class TestPipelineIntrospectionFull: """Integration tests.""" def test_render_empty(self): """_render works when not ready.""" source = PipelineIntrospectionSource() lines = source._render() assert len(lines) > 0 assert "PIPELINE INTROSPECTION" in lines[0] def test_render_with_mock_pipeline(self): """_render works with mock pipeline.""" source = PipelineIntrospectionSource() class MockStage: category = "source" name = "test" class MockPipeline: stages = {"test": MockStage()} execution_order = ["test"] def get_metrics_summary(self): return {"stages": {"test": {"avg_ms": 1.5}}, "avg_ms": 2.0, "fps": 60} def get_frame_times(self): return [1.0, 2.0, 3.0] source.set_pipeline(MockPipeline()) lines = source._render() assert len(lines) > 0