From 28203bac4ba23b9b31dca645c350ae8d89e7f00e Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Mon, 16 Mar 2026 20:25:58 -0700 Subject: [PATCH] test: Fix app.py integration tests to prevent pygame window launch and mock display properly --- tests/test_app.py | 116 +++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 68 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index cd76ece..b50d811 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -29,7 +29,9 @@ class TestMain: patch("engine.app.config") as mock_config, patch("engine.app.run_pipeline_mode") as mock_run, ): + mock_config.PIPELINE_DIAGRAM = False mock_config.PRESET = "border-test" + mock_config.PIPELINE_MODE = False sys.argv = ["mainline.py"] main() mock_run.assert_called_once_with("border-test") @@ -40,7 +42,9 @@ class TestMain: patch("engine.app.config") as mock_config, patch("engine.app.list_presets", return_value=["demo", "poetry"]), ): + mock_config.PIPELINE_DIAGRAM = False mock_config.PRESET = "nonexistent" + mock_config.PIPELINE_MODE = False sys.argv = ["mainline.py"] with pytest.raises(SystemExit) as exc_info: main() @@ -78,59 +82,49 @@ class TestRunPipelineMode: """run_pipeline_mode() uses cached content if available.""" cached = ["cached_item"] with ( - patch("engine.app.load_cache", return_value=cached), + patch("engine.app.load_cache", return_value=cached) as mock_load, patch("engine.app.fetch_all") as mock_fetch, patch("engine.app.DisplayRegistry.create") as mock_create, - patch("engine.app.Pipeline") as mock_pipeline_class, - patch("engine.app.effects_plugins"), - patch("engine.app.get_registry"), - patch("engine.app.PerformanceMonitor"), - patch("engine.app.set_monitor"), - patch("engine.app.time.sleep"), ): - # Setup mocks to return early mock_display = Mock() + mock_display.init = Mock() mock_display.get_dimensions = Mock(return_value=(80, 24)) + mock_display.is_quit_requested = Mock(return_value=True) + mock_display.clear_quit_request = Mock() + mock_display.show = Mock() + mock_display.cleanup = Mock() mock_create.return_value = mock_display - mock_pipeline = Mock() - mock_pipeline.context = Mock() - mock_pipeline.context.params = None - mock_pipeline.execute = Mock(side_effect=KeyboardInterrupt) - mock_pipeline_class.return_value = mock_pipeline - - with pytest.raises(KeyboardInterrupt): + try: run_pipeline_mode("demo") + except (KeyboardInterrupt, SystemExit): + pass # Verify fetch_all was NOT called (cache was used) mock_fetch.assert_not_called() + mock_load.assert_called_once() def test_run_pipeline_mode_creates_display(self): """run_pipeline_mode() creates a display backend.""" with ( patch("engine.app.load_cache", return_value=["item"]), patch("engine.app.DisplayRegistry.create") as mock_create, - patch("engine.app.Pipeline") as mock_pipeline_class, - patch("engine.app.effects_plugins"), - patch("engine.app.get_registry"), - patch("engine.app.PerformanceMonitor"), - patch("engine.app.set_monitor"), - patch("engine.app.time.sleep"), ): mock_display = Mock() + mock_display.init = Mock() mock_display.get_dimensions = Mock(return_value=(80, 24)) + mock_display.is_quit_requested = Mock(return_value=True) + mock_display.clear_quit_request = Mock() + mock_display.show = Mock() + mock_display.cleanup = Mock() mock_create.return_value = mock_display - mock_pipeline = Mock() - mock_pipeline.context = Mock() - mock_pipeline.context.params = None - mock_pipeline.execute = Mock(side_effect=KeyboardInterrupt) - mock_pipeline_class.return_value = mock_pipeline + try: + run_pipeline_mode("border-test") + except (KeyboardInterrupt, SystemExit): + pass - with pytest.raises(KeyboardInterrupt): - run_pipeline_mode("demo") - - # Verify display was created with 'terminal' (preset display) + # Verify display was created with 'terminal' (preset display for border-test) mock_create.assert_called_once_with("terminal") def test_run_pipeline_mode_respects_display_cli_flag(self): @@ -140,25 +134,20 @@ class TestRunPipelineMode: with ( patch("engine.app.load_cache", return_value=["item"]), patch("engine.app.DisplayRegistry.create") as mock_create, - patch("engine.app.Pipeline") as mock_pipeline_class, - patch("engine.app.effects_plugins"), - patch("engine.app.get_registry"), - patch("engine.app.PerformanceMonitor"), - patch("engine.app.set_monitor"), - patch("engine.app.time.sleep"), ): mock_display = Mock() + mock_display.init = Mock() mock_display.get_dimensions = Mock(return_value=(80, 24)) + mock_display.is_quit_requested = Mock(return_value=True) + mock_display.clear_quit_request = Mock() + mock_display.show = Mock() + mock_display.cleanup = Mock() mock_create.return_value = mock_display - mock_pipeline = Mock() - mock_pipeline.context = Mock() - mock_pipeline.context.params = None - mock_pipeline.execute = Mock(side_effect=KeyboardInterrupt) - mock_pipeline_class.return_value = mock_pipeline - - with pytest.raises(KeyboardInterrupt): + try: run_pipeline_mode("demo") + except (KeyboardInterrupt, SystemExit): + pass # Verify display was created with CLI override mock_create.assert_called_once_with("websocket") @@ -172,25 +161,20 @@ class TestRunPipelineMode: ) as mock_fetch_poetry, patch("engine.app.fetch_all") as mock_fetch_all, patch("engine.app.DisplayRegistry.create") as mock_create, - patch("engine.app.Pipeline") as mock_pipeline_class, - patch("engine.app.effects_plugins"), - patch("engine.app.get_registry"), - patch("engine.app.PerformanceMonitor"), - patch("engine.app.set_monitor"), - patch("engine.app.time.sleep"), ): mock_display = Mock() + mock_display.init = Mock() mock_display.get_dimensions = Mock(return_value=(80, 24)) + mock_display.is_quit_requested = Mock(return_value=True) + mock_display.clear_quit_request = Mock() + mock_display.show = Mock() + mock_display.cleanup = Mock() mock_create.return_value = mock_display - mock_pipeline = Mock() - mock_pipeline.context = Mock() - mock_pipeline.context.params = None - mock_pipeline.execute = Mock(side_effect=KeyboardInterrupt) - mock_pipeline_class.return_value = mock_pipeline - - with pytest.raises(KeyboardInterrupt): + try: run_pipeline_mode("poetry") + except (KeyboardInterrupt, SystemExit): + pass # Verify fetch_poetry was called, not fetch_all mock_fetch_poetry.assert_called_once() @@ -202,24 +186,20 @@ class TestRunPipelineMode: patch("engine.app.load_cache", return_value=["item"]), patch("engine.app.effects_plugins") as mock_effects, patch("engine.app.DisplayRegistry.create") as mock_create, - patch("engine.app.Pipeline") as mock_pipeline_class, - patch("engine.app.get_registry"), - patch("engine.app.PerformanceMonitor"), - patch("engine.app.set_monitor"), - patch("engine.app.time.sleep"), ): mock_display = Mock() + mock_display.init = Mock() mock_display.get_dimensions = Mock(return_value=(80, 24)) + mock_display.is_quit_requested = Mock(return_value=True) + mock_display.clear_quit_request = Mock() + mock_display.show = Mock() + mock_display.cleanup = Mock() mock_create.return_value = mock_display - mock_pipeline = Mock() - mock_pipeline.context = Mock() - mock_pipeline.context.params = None - mock_pipeline.execute = Mock(side_effect=KeyboardInterrupt) - mock_pipeline_class.return_value = mock_pipeline - - with pytest.raises(KeyboardInterrupt): + try: run_pipeline_mode("demo") + except (KeyboardInterrupt, SystemExit): + pass # Verify effects_plugins.discover_plugins was called mock_effects.discover_plugins.assert_called_once()